Ascend-SACT/Qwen3-4B-GRPO-2K-VeRL
模型介绍文件和版本Pull Requests讨论分析
下载使用量0

Qwen3-4B-GRPO-2K-VeRL训练实践指导

一、 模型概述及场景

1.1. Qwen3亮点解析

通义千问3是该系列最新一代大语言模型,提供稠密模型与混合专家(MoE)模型的完整解决方案。基于海量训练构建的Qwen3在推理能力、指令遵循、智能体功能及多语言支持方面实现突破性进展,主要特性包括:

  • 独创思维模式切换:支持在单一模型内无缝切换思维模式(处理复杂逻辑推理、数学与代码任务)与非思维模式(高效通用对话),确保各类场景下的最优表现
  • 推理能力跃升:在数学解题、代码生成与常识逻辑推理方面,其思维模式表现超越前代QwQ模型,非思维模式优于Qwen2.5指令模型
  • 人性化交互优化:在创意写作、角色扮演、多轮对话及指令遵循场景中展现卓越的人类偏好对齐能力,提供更自然、生动且沉浸的对话体验
  • 顶尖智能体能力:支持思维/非思维模式下与外部工具精准对接,在开源模型的复杂智能体任务中保持领先性能
  • 百种语言支持:覆盖100+语言与方言,具备强大的多语言指令遵循与翻译能力

1.2. 模型概览-Qwen3-4B

  • 类型:因果语言模型
  • 训练阶段:预训练&后训练
  • 参数量:40亿
  • 非嵌入参数量:36亿
  • 层数:36
  • 注意力头数(GQA):Q头32个/KV头8个
  • 上下文长度:原生支持32,768 token,通过YaRN扩展至131,072 token

模型huggingface链接:Qwen/Qwen3-4B

本案例使用昇腾A3机器上,基于VeRL 框架完成Qwen3-4B-GRPO算法强化学习实践。

二、 环境准备

2.1. 硬件环境

硬件名称配置信息备注
机器型号A3 超节点
测试集群8卡Pod单机

2.2. 软件环境

安装完成后版本概览

软件版本部署方式
DriverAscendHDK 25.2.0宿主机
FirmwareAscendHDK 25.2.0宿主机
CANN8.2.RC1 (文档:8.1.RC1)容器
Python3.10.18容器
torch2.5.1容器
torch_npu2.5.1容器
transformers4.52.4容器
torchvision0.20.1容器
ray2.46.0容器

2.3. 镜像准备

MindspeedLLM 镜像已发布,使用方法请参考:昇腾训练镜像构建指导 中 VERL镜像。镜像下载链接:Ascend-SACT/ascend_train_image

三、 训练准备

3.0.1. 数据集

3.0.1.1. 数据集概述

GSM8K(小学8千数学题)是一个包含8,500道高质量、语言多样的小学数学文字题的数据集。该数据集的创建旨在支持对需要多步推理的基础数学问题进行问答的任务。

这些问题需要2到8个步骤来解决。解决方案主要涉及使用基本算术运算(+ − ×÷)进行一系列基础计算,以得出最终答案。

一个聪明的中学生应该能够解决每一个问题:根据论文所述,"这些问题所需的概念不超过初级代数水平,绝大多数问题无需显式定义变量即可解决。

解决方案以自然语言形式提供,而非纯粹的数学表达式。论文中指出:"我们认为这是最普遍有用的数据格式,并期望它能揭示大型语言模型内部独白的特性。

image-20251129114809699

3.0.1.2. 数据集集准备

测试过程中我们采用open/gsm8k,下载数据集并将数据集预处理为parquet格式,以便包含计算RL奖励所需的必要字段。

source /usr/local/Ascend/ascend-toolkit/set_env.sh
cd /src/verl_code/verl
python3 examples/data_preprocess/gsm8k.py --local_dir /data/private/datasets/gsm8k

image-20250822102811925

image-20250822103024700

3.1. 权重准备

下载HuggingFace权重到指定目录下:

image-20250824111411956

四、 H20训练

4.1. 训练脚本

export VLLM_USE_V1=1

trainer_n_gpus_per_node=8
trainer_nnodes=1
exp_num=13
trainer_project_name='verl_grpo_example_gsm8k'
trainer_experiment_name="qwen3_4b_grpo_8ka_${exp_num}"
use_dynamic_bsz=True

python3 -m verl.trainer.main_ppo \
    algorithm.adv_estimator=grpo \
    data.train_files=/mnt/bn/llm-lr-hl/shared/data/gsm8k/train.parquet \
    data.val_files=/mnt/bn/llm-lr-hl/shared/data/gsm8k/test.parquet  \
    data.train_batch_size=512 \
    data.max_prompt_length=1024 \
    data.max_response_length=1024 \
    data.filter_overlong_prompts=True \
    data.truncation='error' \
    actor_rollout_ref.model.path=/mnt/bn/llm-lr-hl/shared/models/Qwen3-4B \
    actor_rollout_ref.actor.optim.lr=5e-7 \
    actor_rollout_ref.model.use_remove_padding=True \
    actor_rollout_ref.actor.entropy_coeff=0.001 \
    actor_rollout_ref.actor.ppo_mini_batch_size=256 \
    actor_rollout_ref.actor.use_kl_loss=True \
    actor_rollout_ref.actor.kl_loss_coef=0.001 \
    actor_rollout_ref.actor.kl_loss_type=low_var_kl \
    actor_rollout_ref.actor.use_torch_compile=False \
    actor_rollout_ref.actor.use_dynamic_bsz=${use_dynamic_bsz} \
    actor_rollout_ref.actor.ppo_max_token_len_per_gpu=3000 \
    actor_rollout_ref.model.enable_gradient_checkpointing=True \
    actor_rollout_ref.actor.fsdp_config.param_offload=True \
    actor_rollout_ref.actor.fsdp_config.optimizer_offload=True \
    actor_rollout_ref.rollout.enforce_eager=True \
    actor_rollout_ref.rollout.log_prob_use_dynamic_bsz=${use_dynamic_bsz} \
    actor_rollout_ref.rollout.log_prob_max_token_len_per_gpu=4096 \
    actor_rollout_ref.rollout.enable_chunked_prefill=False \
    actor_rollout_ref.rollout.tensor_model_parallel_size=2 \
    actor_rollout_ref.rollout.name=vllm \
    actor_rollout_ref.rollout.gpu_memory_utilization=0.9 \
    actor_rollout_ref.rollout.n=5 \
    actor_rollout_ref.ref.log_prob_use_dynamic_bsz=${use_dynamic_bsz} \
        actor_rollout_ref.ref.log_prob_max_token_len_per_gpu=8192 \
    actor_rollout_ref.ref.fsdp_config.param_offload=True \
    actor_rollout_ref.ref.use_torch_compile=True \
    algorithm.kl_ctrl.kl_coef=0.001 \
    trainer.critic_warmup=0 \
    trainer.project_name=${trainer_project_name} \
    trainer.experiment_name=${trainer_experiment_name} \
    trainer.logger=['console','wandb'] \
    trainer.default_local_dir=/data/private/outputs/ckpt/rl/${trainer_project_name}/${trainer_experiment_name} \
    trainer.n_gpus_per_node=$trainer_n_gpus_per_node \
    trainer.nnodes=$trainer_nnodes \
    trainer.save_freq=-1 \
    trainer.test_freq=5 \
    trainer.total_epochs=15 \
    trainer.val_before_train=False

五、A3训练

5.1. 安装jemalloc(可选)

参考文档

jemalloc(由Facebook优化)和tcmalloc(Google的线程缓存分配器)在内存分配效率、碎片控制、多线程性能等方面显著优于传统的malloc(如glibc的ptmalloc2)。

# 要求Ubuntu版本>=20.04
# 安装 jemalloc
sudo apt update
sudo apt install libjemalloc2

5.2. 训练脚本

source /usr/local/Ascend/ascend-toolkit/set_env.sh
source /usr/local/Ascend/nnal/atb/set_env.sh
source ~/.bashrc

cd /data/private/code/verl_code/verl

set -xeuo pipefail

# export VLLM_ATTENTION_BACKEND=XFORMERS
export VLLM_USE_V1=1
export VLLM_VERSION=0.9.1

trainer_n_gpus_per_node=16
trainer_nnodes=1
exp_num="compare_h20_1"
trainer_project_name='verl_grpo_example_gsm8k'
trainer_experiment_name="qwen3_4b_grpo_8ka_${exp_num}"
export TENSORBOARD_DIR="/data/private/outputs/rl/tensorboard_dir/${trainer_project_name}/${trainer_experiment_name}"
mkdir -p /data/private/outputs/rl/${trainer_project_name}
log_path=/data/private/outputs/rl/${trainer_project_name}/${trainer_experiment_name}.log
use_dynamic_bsz=True

# 开启二级流水
export TASK_QUEUE_ENABLE=2
export CPU_AFFINITY_CONF=1
# 内存分配优化
if [ -f "/usr/lib/aarch64-linux-gnu/libjemalloc.so.2" ]; then
    export LD_PRELOAD="/usr/lib/aarch64-linux-gnu/libjemalloc.so.2${LD_PRELOAD:+:$LD_PRELOAD}"
    echo "jemalloc enabled"
else
    echo "Running without jemalloc - consider installing it for better performance"
    echo "sudo apt-get install libjemalloc2"
fi
echo "当前 LD_PRELOAD 值: $LD_PRELOAD"

python3 -m verl.trainer.main_ppo \
    algorithm.adv_estimator=grpo \
    data.train_files=/data/private/datasets/gsm8k/train.parquet \
    data.val_files=/data/private/datasets/gsm8k/test.parquet \
    data.train_batch_size=512 \
    data.max_prompt_length=1024 \
    data.max_response_length=1024 \
    data.filter_overlong_prompts=True \
    data.truncation='error' \
    actor_rollout_ref.model.path=/data/share/1950833868382666752/hw/weights/Qwen3-4B \
    actor_rollout_ref.actor.optim.lr=5e-7 \
    actor_rollout_ref.model.use_remove_padding=True \
    actor_rollout_ref.actor.entropy_coeff=0.001 \
    actor_rollout_ref.actor.ppo_mini_batch_size=256 \
    actor_rollout_ref.actor.use_kl_loss=True \
    actor_rollout_ref.actor.kl_loss_coef=0.001 \
    actor_rollout_ref.actor.kl_loss_type=low_var_kl \
    actor_rollout_ref.actor.use_torch_compile=False \
    actor_rollout_ref.actor.use_dynamic_bsz=${use_dynamic_bsz} \
    actor_rollout_ref.actor.ppo_max_token_len_per_gpu=3000 \
    actor_rollout_ref.model.enable_gradient_checkpointing=True \
    actor_rollout_ref.actor.fsdp_config.param_offload=True \
    actor_rollout_ref.actor.fsdp_config.optimizer_offload=True \
    actor_rollout_ref.rollout.enforce_eager=True \
    actor_rollout_ref.rollout.log_prob_use_dynamic_bsz=${use_dynamic_bsz} \
    actor_rollout_ref.rollout.log_prob_max_token_len_per_gpu=4096 \
    actor_rollout_ref.rollout.enable_chunked_prefill=False \
    actor_rollout_ref.rollout.tensor_model_parallel_size=2 \
    actor_rollout_ref.rollout.name=vllm \
    actor_rollout_ref.rollout.gpu_memory_utilization=0.9 \
    actor_rollout_ref.rollout.n=5 \
    actor_rollout_ref.ref.log_prob_use_dynamic_bsz=${use_dynamic_bsz} \
	actor_rollout_ref.ref.log_prob_max_token_len_per_gpu=8192 \
    actor_rollout_ref.ref.fsdp_config.param_offload=True \
    actor_rollout_ref.ref.use_torch_compile=True \
    algorithm.kl_ctrl.kl_coef=0.001 \
    trainer.critic_warmup=0 \
    trainer.project_name=${trainer_project_name} \
    trainer.experiment_name=${trainer_experiment_name} \
    trainer.logger=['console','tensorboard'] \
    trainer.default_local_dir=/data/private/outputs/ckpt/rl/${trainer_project_name}/${trainer_experiment_name} \
    trainer.n_gpus_per_node=$trainer_n_gpus_per_node \
    trainer.nnodes=$trainer_nnodes \
    trainer.save_freq=-1 \
    trainer.test_freq=5 \
    trainer.total_epochs=15 \
    trainer.val_before_train=False \
    trainer.device=npu 2>&1 | tee $log_path

六、指标对比

6.1. 版本对比

组件NPUGPU
卡数88
机器A3H20
CANN25.2.0-
HDK25.2.0-
python3.10.183.10.18+
torch2.5.12.7.1+cu126
torch-npu2.5.1.post1-
ray2.49.12.50.0
transformers4.52.44.53.0
vllm0.9.10.9.2
vllm_ascend0.9.1-
verl0.5.0 br 796871d7d
a4d8952edc6653e9661bbe37722ede13f2a7b0c7
0.5.0
cb809d66e46dfd3342d008628891a14a054fa424

6.2. 指标曲线

image-20251202162616597

image-20251202162729475

image-20251202162808479

image-20251202162838210

6.3. 性能对比

指标对比H20
端到端时间1.58倍
平均生成时间(秒)0.80倍
平均演员更新时间(秒)2.35倍
平均步骤时间(秒)1.53倍