Ascend-SACT/train_Qwen3-14B-mindspeed-llm
模型介绍文件和版本Pull Requests讨论分析
下载使用量0

Qwen3-14B基于mindspeed-llm的训练适配

零、模型概述

Qwen3 是 Qwen 系列中的最新一代大型语言模型,提供了一整套密集型和专家混合(MoE)模型。基于广泛的训练,Qwen3 在推理、指令执行、代理能力和多语言支持方面取得了突破性进展,具有以下关键特性:

  • 在同一模型中独特地支持在思考模式(用于复杂的逻辑推理、数学和编码)和非思考模式(用于高效、通用的对话)之间无缝切换,确保在各种场景下的最佳性能。
  • 显著增强了其推理能力,在数学、代码生成和常识逻辑推理方面超过了之前的 QwQ(在思考模式下)和 Qwen2.5 指令模型(在非思考模式下)。
  • 卓越的人类偏好对齐,在创意写作、角色扮演、多轮对话和指令执行方面表现出色,提供了更自然、引人入胜和沉浸式的对话体验。
  • 在代理能力方面的专长,能够在思考和非思考模式下与外部工具精确集成,并在复杂的基于代理的任务中达到开源模型中的领先性能。
  • 支持 100 多种语言和方言,具备强大的多语言指令执行和翻译能力。

Qwen3-14B 具有以下特点:

  • 类型:因果语言模型
  • 训练阶段:预训练和后训练
  • 参数数量:14.8B
  • 非嵌入参数数量:13.2B
  • 层数:40
  • 注意力头数(GQA):Q 为 40,KV 为 8
  • 上下文长度:原生 32,768 和 使用 YaRN 的 131,072 个令牌。

一、训练环境

硬件:

设备型号NPU配置
Atlas 800T A38*128G

软件配套:

软件版本部署方式
DriverAscendHDK 25.0.RC1宿主机
FirmwareAscendHDK 25.0.RC1宿主机
Python3.10容器内
CANNCANN 8.1.RC1容器内
Torch2.6.0容器内
Torch_npurelease v7.0.0容器内
MindSpeed2.0.0_core_r0.8.0容器内
MindSpeed-LLM2.1.0容器内
Megatron-LMcore_r0.8.0容器内
Docker镜像OSUbuntu 20.04.6/

镜像:

  • 镜像Dockerfile
  • 镜像tar包

二、前期准备

2.1 训练脚本准备

已准备了Qwen3-14B模型的训练验证脚本,包括数据预处理、模型格式转换、全参微调和LoRA微调等功能,放在到scripts/qwen3-14b路径下。

scripts/qwen3-14b#
    ├── ckpt_convert_qwen3_14b_hf2mcore.sh   # 将HF权重转换为Mcore格式(TP=4, PP=2)
    ├── ckpt_convert_qwen3_lora_merge.sh  # Lora微调Lora权重合并脚本
    ├── ckpt_convert_qwen3_mcore2hf_full.sh  # 将全参微调的Mcore权重转换为HF格式
    ├── ckpt_convert_qwen3_mcore2hf_lora.sh  # 将全参微调的Mcore权重转换为HF格式
    ├── data_convert_qwen3_instruction_customed10k_qwen3.sh # qwen3 customed慢思考数据转换脚本
    ├── data_convert_qwen3_pretrain_enwiki.sh # 预训练enwiki数据转换脚本
    ├── eval_qwen3_14b_full_customed10k.sh  # 全参微调的评测脚本
    ├── eval_qwen3_14b_lora_customed10k.sh  # Lora微调的评测脚本
    ├── pretrain_qwen3_14b_enwiki_4K_ptd.sh # 预训练训练脚本
    ├── tune_qwen3_14b_4K_full_customed10k_ptd_2nodes.sh # 全参微调双机训练脚本
    ├── tune_qwen3_14b_4K_full_customed10k_ptd.sh   # 全参微调训练脚本
    └── tune_qwen3_14b_4K_lora_customed10k_ptd.sh   # Lora微调训练脚本

2.2 权重准备

从HuggingFace或ModelScope下载模型权重Qwen3-14B,已放置在models/Qwen3-14B目录下。

models/Qwen3-14B# 
    ├── config.json
    ├── configuration.json
    ├── generation_config.json
    ├── merges.txt
    ├── mg2hf
    ├── model-00001-of-00008.safetensors
    ├── model-00002-of-00008.safetensors
    ├── model-00003-of-00008.safetensors
    ├── model-00004-of-00008.safetensors
    ├── model-00005-of-00008.safetensors
    ├── model-00006-of-00008.safetensors
    ├── model-00007-of-00008.safetensors
    ├── model-00008-of-00008.safetensors
    ├── model.safetensors.index.json
    ├── README.md
    ├── tokenizer_config.json
    ├── tokenizer.json
    └── vocab.json

2.3 数据集准备

准备训练与测试数据集,放在datasets/目录下

datasets#
    ├── customed_test_1k.jsonl    # 测试集
    └── customed_train_10k.jsonl  # 训练集

三、HF权重转换为MG格式

昇腾MindSpeed-LLM要求模型权重采用Megatron-LM格式,在这里我们将原始HuggingFace权重格式转换为Megatron-Mcore格式。

使用转换脚本,获取对应切分的mg权重。这里权重切分为TP4PP2,权重转换转换脚本 ckpt_convert_qwen3_14b_hf2mcore.sh 关键代码如下:

OUTPUT_BASE_DIR=/data/qwen3
log_path="${OUTPUT_BASE_DIR}/14b/logs/ckpt_convert_qwen3_14b_hf2mcore.log"
mkdir -p ${OUTPUT_BASE_DIR}/14b/mg_weights/qwen3_14b_mcore_tp4pp2/
mkdir -p ${OUTPUT_BASE_DIR}/14b/logs

# 设置需要的权重转换参数
python convert_ckpt.py \
    --use-mcore-models \
    --model-type GPT \
    --load-model-type hf \
    --save-model-type mg \
    --target-tensor-parallel-size 4 \
    --target-pipeline-parallel-size 2 \
    --spec mindspeed_llm.tasks.models.spec.qwen3_spec layer_spec \
    --load-dir models/Qwen3-14B/ \
    --save-dir ${OUTPUT_BASE_DIR}/14b/mg_weights/qwen3_14b_mcore_tp4pp2/ \
    --tokenizer-model models/Qwen3-14B/tokenizer.json \
    --params-dtype bf16 \
    --model-type-hf qwen3 \
        | tee $log_path

参数解析

参数说明必填
--model-type GPT指定模型类型为GPT系列是
--use-mcore-models转换为Megatron-Mcore格式是
--target-tensor-parallel-size张量并行度设置是
--target-pipeline-parallel-size流水线并行度设置是
--tokenizer-model指定分词器路径是
--load-model-type加载权重的类别(可以是hf、mg)是
--save-model-type存储权重的类别(可以是hf、mg)是
--load-dir权重文件加载路径是
--save-dir权重文件保存路径是
--model-type-hfhuggingface模型类别,默认为llama2否
--params-dtype指定权重转换后的权重精度模式,默认为fp16,如果源文件格式为bf16,则需要设置为bf16是

在平台托管训练下发任务,单机单卡就能运行,更多资源会更快。执行脚本

cd scripts/qwen3-14b && bash ckpt_convert_qwen3_14b_hf2mcore.sh

运行后部分日志截图如下

image-20250823113859320

转换后生成目录文件如下:

/data/qwen3/14b/mg_weights/qwen3_14b_mcore_tp4pp2/
├── iter_0000001
│   ├── mp_rank_00_000
│   ├── mp_rank_00_001
│   ├── mp_rank_01_000
│   ├── mp_rank_01_001
│   ├── mp_rank_02_000
│   ├── mp_rank_02_001
│   ├── mp_rank_03_000
│   └── mp_rank_03_001
└── latest_checkpointed_iteration.txt

四、微调数据集转换为bin格式

注意:由于制作慢思考数据,2.1.0的分支不支持,需要使用MindSpeed-LLM的2.1.0之后的分支或master分支代码。

这里使用的数据集为customed数据集,原始数据集目录为:

  • 训练数据集:datasets/customed_train_10k.jsonl
  • 评测数据集:datasets/customed_test_1k.jsonl

训练数据集样例如下:

{"messages": [{"role": "system", "content": "You are a helpful assistant."}, {"role": "user", "content": "请你判读用户的意图。...交互历史:用户:广州塔为什么也叫小蛮腰\n用户最后一句话所属的技能和意图是:"}, {"role": "assistant", "content": "闲聊百科_知识查询"}]}

4.1 微调数据集转换流程

由于制作慢思考数据,需要使用MindSpeed-LLM的master分支代码,相关master分支代码已提前放置在镜像/src/train25.1.0/MindSpeed-LLM 目录。

其中微调数据集转换脚本 data_convert_qwen3_instruction_customed10k_qwen3.sh 大致如下

OUTPUT_BASE_DIR=/data/qwen3
mkdir -p ${OUTPUT_BASE_DIR}/finetune_dataset_customed10k_qwen3_think
log_path="${OUTPUT_BASE_DIR}/14b/logs/data_convert_qwen3_instruction_customed10k_qwen3.log"
mkdir -p ${OUTPUT_BASE_DIR}/14b/logs

python ./preprocess_data.py \
    --input  datasets/customed_train_10k.jsonl \
    --tokenizer-name-or-path models/Qwen3-14B/ \
    --output-prefix ${OUTPUT_BASE_DIR}/finetune_dataset_customed10k_qwen3_think/customed \
    --handler-name SharegptStyleInstructionHandler \
    --tokenizer-type PretrainedFromHF \
    --enable-thinking true \
    --workers 4 \
    --log-interval 1000 \
    --map-keys '{"messages":"messages", "tags":{"role_tag": "role","content_tag": "content","user_tag": "user","assistant_tag": "assistant","system_tag": "system"}}' \
    --prompt-type qwen3 \
        | tee $log_path

参数说明:

参数说明必填
--input输入数据文件的路径,输入数据集目录或具体文件,如果是目录,则处理全部文件, 支持 .parquet \ .csv \ .json \ .jsonl \ .txt \ .arrow 格式, 同一个文件夹下的数据格式需要保持一致是
--tokenizer-name-or-path用于分词器的预训练模型的路径。是
--output-prefix输出文件的前缀。预处理后的数据会被保存为多个文件(例如,后缀为.bin和.idx),这个参数指定这些文件的前缀路径。是
--workers指定数据预处理时使用的进程数(多进程)。更多的进程数可以加快处理速度。是
-tokenizer-type指定tokenizer的类型。是
--log-interval处理进度更新的间隔步数。是
--enable-thinking快慢思考模板开关,可设定为[true,false,none],默认值是none。对于qwen3,开启后,会在数据集的Label中添加\n\n,并参与到loss计算,所有数据被当成慢思考数据;当关闭后,\n\n将被添加到提示词的`<im_start
--handler-name指定数据处理器(handler)的类名。常用的有AlpacaStylePairwiseHandler,SharegptStyleInstructionHandler,AlpacaStylePairwiseHandler等是
--prompt-type指定模型模板,能够让base模型微调后能具备更好的对话能力。prompt-type的可选项可以在templates文件内查看。是
--map-keys参数用于配置字段映射来使用数据集。其中key值"messages"、"tags"代表数据集列映射后的属性,在代码中是固定的,不应改变。value值中"conversations"对应数据集的列名、"from"对应角色标志、"human"、"gpt"、"system"、"observation"、"function_call"对应角色种类、"value"对应具体内容标志。
OpenAI风格为'{"messages":"messages", "tags":{"role_tag": "role","content_tag": "content","user_tag": "user","assistant_tag": "assistant","system_tag": "system"}}'
ShareGPT风格为 '{"messages":"conversations", "tags":{"role_tag": "from","content_tag": "value","user_tag": "human","assistant_tag": "gpt","system_tag": "system", "observation_tag":"observation", "function_tag":"function_call"}}'
是

在平台托管训练下发任务,单机单卡就能运行,更多资源会更快。执行脚本

cd scripts/qwen3-14b && bash data_convert_qwen3_instruction_customed10k_qwen3.sh

运行后部分日志截图如下

image-20250823114116049

转换后生成的文件列表如下:

.
├── customed_packed_attention_mask_document.bin
├── customed_packed_attention_mask_document.idx
├── customed_packed_input_ids_document.bin
├── customed_packed_input_ids_document.idx
├── customed_packed_labels_document.bin
├── customed_packed_labels_document.idx
├── customed_train_indexmap_49920ns_42s_shuffle_decoder_packed_idx.npy
└── customed_train_indexmap_51200ns_42s_shuffle_decoder_packed_idx.npy

4.2 慢思考数据制作说明

关于qwen3 的--enable-thinking的详细设置特殊说明如下:

4.2.1 无思考数据构造的模型输入

customed数据集为无思考数据的OpenAI格式,样例如下:

{"messages": [{"role": "system", "content": "You are a helpful assistant."}, {"role": "user", "content": "请你判读用户的意图。...交互历史:用户:广州塔为什么也叫小蛮腰\n用户最后一句话所属的技能和意图是:"}, {"role": "assistant", "content": "闲聊百科_知识查询"}]}

--enable-thinking的值可设定为[true,false,none],使用如下:

  • 本次数据制作,该参数设置为true。think标签参加loss计算, 构造的模型输入为:

    ['<|im_start|>system\nYou are a helpful assistant.<|im_end|>\n<|im_start|>user\n请你判读用户的意图。...交互历史:用户:广州塔为什么也叫小蛮腰\n用户最后一句话所属的技能和意图是:<|im_end|>\n<|im_start|>assistant\n', '\n\n闲聊百科_知识查询<|im_end|>\n']
  • 若该参数设置为false。think数据不参加loss计算 , 构造的模型输入为:

    ['<|im_start|>system\nYou are a helpful assistant.<|im_end|>\n<|im_start|>user\n请你判读用户的意图。...交互历史:用户:广州塔为什么也叫小蛮腰\n用户最后一句话所属的技能和意图是:<|im_end|>\n<|im_start|>assistant\n\n\n', '闲聊百科_知识查询<|im_end|>\n']
  • 当原始数据集中有think标签时,该参数设置为none。适合混合快慢思考数据的场景。构造的模型输入为:

    ['<|im_start|>system\nYou are a helpful assistant.<|im_end|>\n<|im_start|>user\n请你判读用户的意图。...交互历史:用户:广州塔为什么也叫小蛮腰\n用户最后一句话所属的技能和意图是:<|im_end|>\n<|im_start|>assistant\n\n\n', '闲聊百科_知识查询<|im_end|>\n']

4.2.2 带思考数据构造的模型输入

若需制作带慢思考数据,原始数据的样例,可以参考 中文基于满血DeepSeek-R1蒸馏数据集-110k-SFT版本 ,样例如下:

{"messages": [{"role": "system", "content": "You are a helpful assistant."}, {"role": "user", "content": "请你判读用户的意图。...交互历史:用户:广州塔为什么也叫小蛮腰\n用户最后一句话所属的技能和意图是:"}, {"role": "assistant", "content": "闲聊百科_知识查询"}]}
  • 该参数设置为true,构造的模型输入为:

    ['<|im_start|>system\nYou are a helpful assistant.<|im_end|>\n<|im_start|>user\n请你判读用户的意图。...交互历史:用户:广州塔为什么也叫小蛮腰\n用户最后一句话所属的技能和意图是:<|im_end|>\n<|im_start|>assistant\n', '闲聊百科_知识查询<|im_end|>\n']
  • 该参数设置为false,构造的模型输入为:

    ['<|im_start|>system\nYou are a helpful assistant.<|im_end|>\n<|im_start|>user\n请你判读用户的意图。...交互历史:用户:广州塔为什么也叫小蛮腰\n用户最后一句话所属的技能和意图是:<|im_end|>\n<|im_start|>assistant\n\n\n', '闲聊百科_知识查询<|im_end|>\n']
  • 该参数设置为none,构造的模型输入为:

    message: ['<|im_start|>system\nYou are a helpful assistant.<|im_end|>\n<|im_start|>user\n请你判读用户的意图。...交互历史:用户:广州塔为什么也叫小蛮腰\n用户最后一句话所属的技能和意图是:<|im_end|>\n<|im_start|>assistant\n', '闲聊百科_知识查询<|im_end|>\n']

4.2.3 快慢思考数据混合构造的模型输入

若原始数据如下:

{"messages": [{"role": "system", "content": "You are a helpful assistant."}, {"role": "user", "content": "请你判读用户的意图。...交互历史:用户:广州塔为什么也叫小蛮腰\n用户最后一句话所属的技能和意图是:"}, {"role": "assistant", "content": "闲聊百科_知识查询"}]}
{"messages": [{"role": "system", "content": "You are a helpful assistant."}, {"role": "user", "content": "请你判读用户的意图。...交互历史:用户:广州塔为什么也叫小蛮腰\n用户最后一句话所属的技能和意图是:"}, {"role": "assistant", "content": "闲聊百科_知识查询"}]}
  • 该参数设置为true,构造的模型输入为:

    ['<|im_start|>system\nYou are a helpful assistant.<|im_end|>\n<|im_start|>user\n请你判读用户的意图。...交互历史:用户:广州塔为什么也叫小蛮腰\n用户最后一句话所属的技能和意图是:<|im_end|>\n<|im_start|>assistant\n', '闲聊百科_知识查询<|im_end|>\n']
    ['<|im_start|>system\nYou are a helpful assistant.<|im_end|>\n<|im_start|>user\n请你判读用户的意图。...交互历史:用户:广州塔为什么也叫小蛮腰\n用户最后一句话所属的技能和意图是:<|im_end|>\n<|im_start|>assistant\n', '\n\n闲聊百科_知识查询<|im_end|>\n']
  • 该参数设置为false,构造的模型输入为:

    ['<|im_start|>system\nYou are a helpful assistant.<|im_end|>\n<|im_start|>user\n请你判读用户的意图。...交互历史:用户:广州塔为什么也叫小蛮腰\n用户最后一句话所属的技能和意图是:<|im_end|>\n<|im_start|>assistant\n\n\n', '闲聊百科_知识查询<|im_end|>\n']
    ['<|im_start|>system\nYou are a helpful assistant.<|im_end|>\n<|im_start|>user\n请你判读用户的意图。...交互历史:用户:广州塔为什么也叫小蛮腰\n用户最后一句话所属的技能和意图是:<|im_end|>\n<|im_start|>assistant\n\n\n', '闲聊百科_知识查询<|im_end|>\n']
  • 该参数设置为none,构造的模型输入为:

    ['<|im_start|>system\nYou are a helpful assistant.<|im_end|>\n<|im_start|>user\n请你判读用户的意图。...交互历史:用户:广州塔为什么也叫小蛮腰\n用户最后一句话所属的技能和意图是:<|im_end|>\n<|im_start|>assistant\n', '闲聊百科_知识查询<|im_end|>\n']
    ['<|im_start|>system\nYou are a helpful assistant.<|im_end|>\n<|im_start|>user\n请你判读用户的意图。...交互历史:用户:广州塔为什么也叫小蛮腰\n用户最后一句话所属的技能和意图是:<|im_end|>\n<|im_start|>assistant\n\n\n', '闲聊百科_知识查询<|im_end|>\n']

五、全参微调

5.1 全参微调示例脚本

启动全参微调训练,训练启动脚本tune_qwen3_14b_4K_full_customed10k_ptd.sh 关键代码如下

export CUDA_DEVICE_MAX_CONNECTIONS=1
#基础配置
NPUS_PER_NODE=16  #使用单节点的NPU
MASTER_ADDR=localhost #以本节点ip地址为master_ip
MASTER_PORT=6015 #本节点端口号为6015
NNODES=1  #单机,即一台节点,多机即多节点
NODE_RANK=0  #单机RANK为0,多机为(0,NNODES-1),不同节点不可重复
WORLD_SIZE=$(($NPUS_PER_NODE*$NNODES)) #最终使用的NPU数量

OUTPUT_BASE_DIR=/data/qwen3
mkdir -p ${OUTPUT_BASE_DIR}/14b/logs

# 根据实际情况配置权重保存、权重加载、词表、数据集路径
CKPT_LOAD_DIR="${OUTPUT_BASE_DIR}/14b/mg_weights/qwen3_14b_mcore_tp4pp2/"  #权重加载路径,填入权重转换时保存的权重路径
CKPT_SAVE_DIR="${OUTPUT_BASE_DIR}/14b/save_weights_full/qwen3_14b_mcore_tp4pp2_customed10k_qwen3_think/"  #训练完成后的权重保存路径
DATA_PATH="${OUTPUT_BASE_DIR}/finetune_dataset_customed10k_qwen3_think/customed"  #数据集路径,填入数据预处理时保存的数据路径,注意需要添加后缀
TOKENIZER_PATH="models/Qwen3-14B/" #词表路径,填入下载的开源权重词表路径
log_path="${OUTPUT_BASE_DIR}/14b/logs/tune_qwen3_14b_4K_full_customed10k_ptd.log"

TP=4  # 张量并行维度
PP=2  # 流水线并行维度
MBS=16  # 微批次大小(每NPU单次前向计算样本数)
GBS=128 # 全局批次大小
SEQ_LENGTH=800   # 最大序列长度(模型支持4096上下文)
TRAIN_ITERS=390 #训练步数

DISTRIBUTED_ARGS="
    --nproc_per_node $NPUS_PER_NODE \ 
    --nnodes $NNODES \
    --node_rank $NODE_RANK \
    --master_addr $MASTER_ADDR \
    --master_port $MASTER_PORT
"

GPT_ARGS="
    --use-mcore-models \
    --tensor-model-parallel-size ${TP} \
    --pipeline-model-parallel-size ${PP} \
    --spec mindspeed_llm.tasks.models.spec.qwen3_spec layer_spec \
    --kv-channels 128 \
    --qk-layernorm \
    --num-layers 40 \
    --hidden-size 5120 \
    --use-rotary-position-embeddings \
    --untie-embeddings-and-output-weights \
    --num-attention-heads 40 \
    --ffn-hidden-size 17408 \
    --max-position-embeddings 40960 \
    --seq-length ${SEQ_LENGTH} \
    --train-iters ${TRAIN_ITERS} \
    --micro-batch-size ${MBS} \
    --global-batch-size ${GBS} \
    --make-vocab-size-divisible-by 1 \
    --use-flash-attn \
    --padded-vocab-size 151936 \
    --rotary-base 1000000 \
    --disable-bias-linear \
    --swiglu \
    --tokenizer-type PretrainedFromHF \
    --tokenizer-name-or-path ${TOKENIZER_PATH} \
    --normalization RMSNorm \
    --position-embedding-type rope \
    --norm-epsilon 1e-6 \
    --hidden-dropout 0 \
    --attention-dropout 0 \
    --no-gradient-accumulation-fusion \
    --attention-softmax-in-fp32 \
    --exit-on-missing-checkpoint \
    --no-masked-softmax-fusion \
    --group-query-attention \
    --num-query-groups 8 \
    --seed 42 \
    --bf16 \
    --lr-warmup-fraction 0.1 \
    --clip-grad 1.0 \
    --adam-beta1 0.9 \
    --adam-beta2 0.999 \
    --no-load-optim \
    --no-load-rng \
    --lr 1.0e-5 \
    --sequence-parallel
"

DATA_ARGS="
    --data-path $DATA_PATH \
    --split 100,0,0
"

OUTPUT_ARGS="
    --log-interval 1 \
    --save-interval ${TRAIN_ITERS} \
    --eval-interval ${TRAIN_ITERS} \
    --eval-iters 0 \
    --log-throughput
"

TUNE_ARGS="
    --finetune \
    --stage sft \
    --is-instruction-dataset \
    --prompt-type qwen \
    --variable-seq-lengths
"

torchrun $DISTRIBUTED_ARGS posttrain_gpt.py \
    $GPT_ARGS \
    $DATA_ARGS \
    $OUTPUT_ARGS \
    $TUNE_ARGS \
    --tensorboard-dir ${OUTPUT_BASE_DIR}/14b/tb/full/customed10k \
    --distributed-backend nccl \
    --load ${CKPT_LOAD_DIR} \
    --save ${CKPT_SAVE_DIR} \
    | tee $log_path

5.2 训练参数对照表

LLaMAFactory在GPU的上运行的关键超参如下:

LLaMAFactory+GPU超参:
### model
model_name_or_path:  XXXXXX
trust_remote_code: true

### method
stage: sft
do_train: true
finetuning_type: full
deepspeed: examples/deepspeed/ds_z3_config.json

### dataset
dataset: customed
template: qwen3
cutoff_len: 800
max_samples: 10000
overwrite_cache: true
preprocessing_num_workers: 16
dataloader_num_workers: 4

output_dir: XXXXXX
logging_steps: 10
save_steps: 100
plot_loss: true
overwrite_output_dir: true
save_only_model: false
report_to: tensorboard  # choices: [none, wandb, tensorboard, swanlab, mlflow]

### train
per_device_train_batch_size: 2
gradient_accumulation_steps: 8
learning_rate: 1.0e-5
num_train_epochs: 5
lr_scheduler_type: cosine
warmup_ratio: 0.1
bf16: true
ddp_timeout: 180000000
resume_from_checkpoint: null

### eval
# eval_dataset: alpaca_en_demo
# val_size: 0.1
# per_device_eval_batch_size: 1
# eval_strategy: steps
# eval_steps: 500

全参微调关键训练参数MindSpeed-LLM与LLaMAFactory对照表如下:

MindSpeed-LLMLLaMAFactory备注
SEQ_LEN=800cutoff_len=800训练的序列长度
TP=4-模型并行切分
PP=2-流水线并行切分
--log-interval=1logging_steps=10打印日志频率
MBS=16per_device_train_batch_size=2micro_batch_size, 需要根据显存进行配置
-gradient_accumulation_steps=8MindSpeed-LLM梯度累计会根据MBS,GBS,DP自动计算。
World_Size = TP * PP * DP
计算方式为:GBS=MBS * MB * DP
GBS=128-全局batch_size
TRAIN_ITERS=390num_train_epochs=5训练步数,总步数=总样本数/GBS,训练步数会影响每一步的具体lr
--lr 1.0e-5learning_rate=1.0e-5学习率
--lr-decay-style cosinelr_scheduler_type=cosine余弦退火学习率衰减
--lr-warmup-fraction 0.1warmup_ratio=0.1学习率预热比例
--bf16bf16=true使用bf16格式训练
--tensorboard-dir ${OUTPUT_BASE_DIR}/14b/tb/full/customed10kreport_to: tensorboard开启tensorboard日志输出

5.3 全参任务下发

单机8卡,执行脚本

cd scripts/qwen3-14b && bash tune_qwen3_14b_4K_full_customed10k_ptd.sh

运行后部分日志截图如下

image-20250823160144519

训练后,根据配置,将生成训练日志和tensorboard日志。

镜像已预置tensorboard,根据上面训练脚本设置,tensorboard日志目录为:/data/qwen3/14b/tb/full/customed10k

打开实验环境的terminal, 使用以下命令启动tensorboard

tensorboard --logdir=/data/qwen3/14b/tb/full/customed10k --port=3000

观察Loss曲线如下:

image-20250823164707350

5.4 双机全参任务下发

多机场景下,需要修改以下配置。脚本参考 tune_qwen3_14b_4K_full_customed10k_ptd_2nodes.sh

# 基础配置
NPUS_PER_NODE=16  #使用单节点的8卡NPU
MASTER_ADDR=$(cat /etc/volcano/worker.host | head -n 1 | awk '{print $1}') #以本节点ip地址为master_ip
MASTER_PORT=6016 #本节点端口号为6015
NNODES=${VC_WORKER_NUM}  #单机,即一台节点,多机即多节点
NODE_RANK=${VC_TASK_INDEX}  #单机RANK为0,多机为(0,NNODES-1),不同节点不可重复
WORLD_SIZE=$(($NPUS_PER_NODE*$NNODES)) #最终使用的NPU数

选择2机,每机8卡,下发任务,执行脚本

cd scripts/qwen3-14b && bash tune_qwen3_14b_4K_full_customed10k_ptd_2nodes.sh

image-20250827151941411

运行后部分日志截图如下

image-20250823160258081

训练后,根据配置,将生成训练日志和tensorboard日志。

镜像已预置tensorboard,根据上面训练脚本设置,tensorboard日志目录为:/data/qwen3/14b/tb/full/customed10k

打开实验环境的terminal, 使用以下命令启动tensorboard

tensorboard --logdir=/data/qwen3/14b/tb --port=3000

观察Loss曲线如下:

image-20250823164950087

5.5 权重评测

训练好的权重基于customed评测数据集,进行评测的脚本eval_qwen3_14b_full_customed10k.sh 关键代码如下

export CUDA_DEVICE_MAX_CONNECTIONS=1

OUTPUT_BASE_DIR=/data/qwen3
CHECKPOINT="${OUTPUT_BASE_DIR}/14b/save_weights_full/qwen3_14b_mcore_tp4pp2_customed10k_qwen3_think/" # 指向微调后权重的保存路径
TOKENIZER_PATH="models/Qwen3-14B/" # 指向模型tokenizer的路径
eval_log_path="${OUTPUT_BASE_DIR}/14b/logs/eval_qwen3_14b_full_customed10k.log"
EVAL_DATA_PATH="datasets/customed_test_1k.jsonl"

# Change for multinode config
MASTER_ADDR=localhost
MASTER_PORT=6000
NNODES=1 # 集群里的节点数,以实际情况填写,
NODE_RANK=0  # 当前节点的RANK,多个节点不能重复,主节点为0, 其他节点可以是1,2..
NPUS_PER_NODE=8
WORLD_SIZE=$(($NPUS_PER_NODE*$NNODES))

TP=4  # 张量并行维度
PP=2  # 流水线并行维度
SEQ_LENGTH=800 # 最大序列长度

DISTRIBUTED_ARGS="
    --nproc_per_node $NPUS_PER_NODE \
    --nnodes $NNODES \
    --node_rank $NODE_RANK \
    --master_addr $MASTER_ADDR \
    --master_port $MASTER_PORT
"

torchrun $DISTRIBUTED_ARGS inference_4_midea_test.py \
         --use-mcore-models \
         --tensor-model-parallel-size ${TP} \
         --pipeline-model-parallel-size ${PP} \
         --load ${CHECKPOINT} \
         --spec mindspeed_llm.tasks.models.spec.qwen3_spec layer_spec \
         --kv-channels 128 \
         --qk-layernorm \
         --num-layers 40 \
         --hidden-size 5120 \
         --use-rotary-position-embeddings \
         --untie-embeddings-and-output-weights \
         --num-attention-heads 40 \
         --ffn-hidden-size 17408 \
         --max-position-embeddings 40960 \
         --seq-length ${SEQ_LENGTH} \
         --make-vocab-size-divisible-by 1 \
         --padded-vocab-size 151936 \
         --rotary-base 1000000 \
         --micro-batch-size 1 \
         --disable-bias-linear \
         --swiglu \
         --use-rotary-position-embeddings \
         --tokenizer-type PretrainedFromHF \
         --tokenizer-name-or-path ${TOKENIZER_PATH} \
         --normalization RMSNorm \
         --position-embedding-type rope \
         --norm-epsilon 1e-6 \
         --hidden-dropout 0 \
         --attention-dropout 0 \
         --max-new-tokens 256 \
         --no-gradient-accumulation-fusion \
         --attention-softmax-in-fp32 \
         --exit-on-missing-checkpoint \
         --no-masked-softmax-fusion \
         --group-query-attention \
         --num-query-groups 8 \
         --seed 42 \
         --bf16 \
      	 --eval-data-path ${EVAL_DATA_PATH} \
       	 --eval-data-size 1000 \
	     --temperature 0.00001 \
       		| tee $eval_log_path

在平台托管训练下发任务,执行脚本

cd scripts/qwen3-14b && bash eval_qwen3_14b_full_customed10k.sh

5.6 MG权重转为HF格式

使用MindSpeed-LLM 训练后,如果希望将权重转为HF格式,使用脚本 ckpt_convert_qwen3_mcore2hf_full.sh ,关键代码如下

export CUDA_DEVICE_MAX_CONNECTIONS=1

OUTPUT_BASE_DIR=/data/qwen3
log_path="${OUTPUT_BASE_DIR}/14b/logs/ckpt_convert_qwen3_mcore2hf_full.log"
mkdir -p ${OUTPUT_BASE_DIR}/14b/logs

python convert_ckpt.py \
    --use-mcore-models \
    --model-type GPT \
    --load-model-type mg \
    --save-model-type hf \
    --target-tensor-parallel-size 1 \
    --target-pipeline-parallel-size 1 \
    --spec mindspeed_llm.tasks.models.spec.qwen3_spec layer_spec \
    --load-dir ${OUTPUT_BASE_DIR}/14b/save_weights_full/qwen3_14b_mcore_tp4pp2_customed10k_qwen3_think/ \
    --save-dir models/Qwen3-14B/ \
    --params-dtype bf16 \
    --model-type-hf qwen3 \
        | tee $log_path

cp -rf models/Qwen3-14B/mg2hf ${OUTPUT_BASE_DIR}/14b/save_weights_full/

注意:

  • --save-model-type参数设置为 hf
  • save-dir 参数设置为原始hf权重的路径,脚本执行后,会在该目录下生成mg2hf的目录存放转换后的权重。
  • tp和pp都设置为1: --target-tensor-parallel-size 1 , --target-pipeline-parallel-size 1

在平台托管训练下发任务,执行脚本

cd scripts/qwen3-14b && bash ckpt_convert_qwen3_mcore2hf_full.sh

运行后部分日志截图如下

image-20250824175435606

转换后生成目录文件如下:

/data/qwen3//14b/save_weights_full/mg2hf/
├── config.json
├── generation_config.json
├── model-00001-of-00006.safetensors
├── model-00002-of-00006.safetensors
├── model-00003-of-00006.safetensors
├── model-00004-of-00006.safetensors
├── model-00005-of-00006.safetensors
├── model-00006-of-00006.safetensors
└── model.safetensors.index.json

5.8 结果总结

全参微调评测得分0.943,与GPU持平。

六、Lora微调

6.1 Lora微调示例脚本

Lora微调训练,训练启动脚本tune_qwen3_14b_4K_lora_customed10k_ptd.sh 关键代码如下

export CUDA_DEVICE_MAX_CONNECTIONS=1
# 基础配置
NPUS_PER_NODE=8  #使用单节点的8卡NPU
MASTER_ADDR=localhost #以本节点ip地址为master_ip
MASTER_PORT=6015 #本节点端口号为6015
NNODES=1  #单机,即一台节点,多机即多节点
NODE_RANK=0  #单机RANK为0,多机为(0,NNODES-1),不同节点不可重复
WORLD_SIZE=$(($NPUS_PER_NODE*$NNODES)) #最终使用的NPU数

OUTPUT_BASE_DIR=/data/qwen3
mkdir -p ${OUTPUT_BASE_DIR}/14b/logs

# 根据实际情况配置权重保存、权重加载、词表、数据集路径
CKPT_LOAD_DIR="${OUTPUT_BASE_DIR}/14b/mg_weights/qwen3_14b_mcore_tp4pp2/"  #权重加载路径,填入权重转换时保存的权重路径
CKPT_SAVE_DIR="${OUTPUT_BASE_DIR}/14b/save_weights_lora/qwen3_14b_mcore_tp4pp2_customed10k_qwen3_think/"  #训练完成后的权重保存路径
DATA_PATH="${OUTPUT_BASE_DIR}/finetune_dataset_customed10k_qwen3_think/customed"  #数据集路径,填入数据预处理时保存的数据路径,注意需要添加后缀
TOKENIZER_PATH="models/Qwen3-14B/" #词表路径,填入下载的开源权重词表路径
log_path="${OUTPUT_BASE_DIR}/14b/logs/tune_qwen3_14b_4K_lora_customed10k_ptd.log"
TP=4  # 张量并行维度
PP=2  # 流水线并行维度
SEQ_LENGTH=2048  # 最大序列长度
TRAIN_ITERS=790  #训练步数
MBS=1    # 微批次大小(每NPU单次前向计算样本数)
GBS=8    # 全局批次大小

DISTRIBUTED_ARGS="
    --nproc_per_node $NPUS_PER_NODE \
    --nnodes $NNODES \
    --node_rank $NODE_RANK \
    --master_addr $MASTER_ADDR \
    --master_port $MASTER_PORT
"

OPTIMIZE_ARGS="
    --use-flash-attn \
    --use-fused-rotary-pos-emb \
    --use-rotary-position-embeddings \
    --use-fused-swiglu \
    --use-fused-rmsnorm \
    --no-masked-softmax-fusion \
    --use-distributed-optimizer
"

TRAIN_ARGS="
    --micro-batch-size ${MBS} \
    --global-batch-size ${GBS} \
    --lr 1.0e-5 \
    --lr-decay-style cosine \
    --lr-warmup-fraction 0.1 \
    --attention-dropout 0.0 \
    --init-method-std 0.01 \
    --hidden-dropout 0.0 \
    --clip-grad 1.0 \
    --adam-beta1 0.9 \
    --adam-beta2 0.999 \
    --initial-loss-scale 4096 \
    --seed 42 \
    --bf16 \
    --train-iters ${TRAIN_ITERS} \
    --seq-length ${SEQ_LENGTH} \
    --no-shared-storage
"

MODEL_PARALLEL_ARGS="
    --tensor-model-parallel-size ${TP} \
    --pipeline-model-parallel-size ${PP}
"

GPT_ARGS="
    --use-mcore-models \
    --spec mindspeed_llm.tasks.models.spec.qwen3_spec layer_spec \
    --kv-channels 128 \
    --qk-layernorm \
    --tokenizer-name-or-path ${TOKENIZER_PATH} \
    --max-position-embeddings ${SEQ_LENGTH} \
    --num-layers 40 \
    --hidden-size 5120 \
    --ffn-hidden-size 17408 \
    --num-attention-heads 40 \
    --tokenizer-type PretrainedFromHF \
    --make-vocab-size-divisible-by 1 \
    --padded-vocab-size 151936 \
    --rotary-base 1000000 \
    --untie-embeddings-and-output-weights \
    --disable-bias-linear \
    --position-embedding-type rope \
    --normalization RMSNorm \
    --swiglu \
    --attention-softmax-in-fp32 \
    --no-gradient-accumulation-fusion \
    --group-query-attention \
    --num-query-groups 8
"

DATA_ARGS="
    --data-path $DATA_PATH \
    --split 100,0,0
"

OUTPUT_ARGS="
    --load ${CKPT_LOAD_DIR} \
    --save ${CKPT_SAVE_DIR} \
    --log-interval 1 \
    --save-interval ${TRAIN_ITERS} \
    --eval-interval ${TRAIN_ITERS} \
    --eval-iters 0 \
    --no-load-optim \
    --no-load-rng
"

TUNE_ARGS="
    --finetune \
    --stage sft \
    --is-instruction-dataset \
    --tokenizer-not-use-fast \
    --prompt-type qwen \
    --variable-seq-lengths \
    --lora-r 16 \
    --lora-alpha 32 \
    --lora-fusion \
    --lora-target-modules linear_qkv linear_proj linear_fc1 linear_fc2
"

torchrun $DISTRIBUTED_ARGS posttrain_gpt.py \
    $GPT_ARGS \
    $DATA_ARGS \
    $OUTPUT_ARGS \
    $OPTIMIZE_ARGS \
    $TRAIN_ARGS \
    $TUNE_ARGS \
    $MODEL_PARALLEL_ARGS \
    --tensorboard-dir ${OUTPUT_BASE_DIR}/14b/tb/lora/customed10k \
    --distributed-backend nccl \
    | tee $log_path

6.2 训练参数对照表

LLaMAFactory在GPU的上运行的关键超参如下:

LLaMAFactory+GPU超参:
### model
model_name_or_path: XXXXXX
trust_remote_code: true

### method
stage: sft
do_train: true
finetuning_type: lora
lora_rank: 16
lora_target: all

### dataset
dataset: customed
template: qwen3
cutoff_len: 2048
max_samples: 10000
overwrite_cache: true
preprocessing_num_workers: 16
dataloader_num_workers: 4

### output
output_dir: XXXXXX
logging_steps: 10
save_steps: 100
plot_loss: true
overwrite_output_dir: true
save_only_model: false
report_to: tensorboard  # choices: [none, wandb, tensorboard, swanlab, mlflow]

### train
per_device_train_batch_size: 4
gradient_accumulation_steps: 4
learning_rate: 1.0e-5
num_train_epochs: 5.0
lr_scheduler_type: cosine
warmup_ratio: 0.1
bf16: true
ddp_timeout: 180000000
resume_from_checkpoint: null

### eval
# eval_dataset: alpaca_en_demo
# val_size: 0.1
# per_device_eval_batch_size: 1
# eval_strategy: steps
# eval_steps: 500

Lora微调关键训练参数MindSpeed-LLM与LLaMAFactory对照表如下:

MindSpeed-LLMLLaMAFactory备注
--lora-r 16lora_rank: 16低秩矩阵的维度。较低的 rank 值模型在训练时会使用更少的参数更新,从而减少计算量和内存消耗。然而,过低的 rank 可能限制模型的表达能力。
--lora-alpha 32-控制 LoRA 权重对原始权重的影响比例, 数值越高则影响越大。一般保持为lora-r的2倍。
--lora-target-modules linear_qkv linear_proj linear_fc1 linear_fc2lora_target: all模型中添加 LoRA 的模块
--lora-fusion-是否启用CCLoRA算法,该算法通过计算通信掩盖提高性能。
SEQ_LEN=2048cutoff_len=2048训练的序列长度
TP=4-模型并行切分
PP=2-流水线并行切分
--log-interval 1logging_steps=10打印日志频率
MBS=16per_device_train_batch_size=4micro_batch_size, 需要根据显存进行配置
-gradient_accumulation_steps=4MindSpeed-LLM梯度累计会根据MBS,GBS,DP自动计算。
World_Size = TP * PP * DP
计算方式为:GBS=MBS * MB * DP
GBS=128-全局batch_size
TRAIN_ITERS=790num_train_epochs=5训练步数,总步数=总样本数/GBS,训练步数会影响每一步的具体lr
--lr 1.0e-5learning_rate=1.0e-5学习率
--lr-decay-style cosinelr_scheduler_type=cosine余弦退火学习率衰减
--lr-warmup-fraction 0.1warmup_ratio=0.1学习率预热比例
--bf16bf16=true使用bf16格式训练
--tensorboard-dir ${OUTPUT_BASE_DIR}/14b/tb/full/customed10kreport_to: tensorboard开启tensorboard日志输出

6.3 Lora任务下发

选择单机4卡,下发任务,执行脚本

cd scripts/qwen3-14b && bash tune_qwen3_14b_4K_lora_customed10k_ptd.sh

运行后部分日志截图如下

image-20250823160428061

训练后,根据配置,将生成训练日志和tensorboard日志。

镜像已预置tensorboard,根据上面训练脚本设置,tensorboard日志目录为:/data/qwen3/14b/tb/lora/customed10k

打开实验环境的terminal, 使用以下命令启动tensorboard

tensorboard --logdir=/data/qwen3/14b/tb/full/customed10k --port=3000

观察Loss曲线如下:image-20250823165222719

6.4 权重评测

训练好的权重基于customed评测数据集,进行评测的脚本eval_qwen3_14b_lora_customed10k.sh 关键代码如下

export CUDA_DEVICE_MAX_CONNECTIONS=1

OUTPUT_BASE_DIR=/data/qwen3
CHECKPOINT="${OUTPUT_BASE_DIR}/14b/save_weights_lora/qwen3_14b_mcore_tp4pp2_customed10k_qwen3_think_merge/" # 指向微调后权重的保存路径
TOKENIZER_PATH="models/Qwen3-14B/" # 指向模型tokenizer的路径
eval_log_path="${OUTPUT_BASE_DIR}/14b/logs/eval_qwen3_14b_lora_customed10k.log"
EVAL_DATA_PATH="datasets/customed_test_1k.jsonl"

# Change for multinode config
MASTER_ADDR=localhost
MASTER_PORT=6000
NNODES=1 # 集群里的节点数,以实际情况填写,
NODE_RANK=0  # 当前节点的RANK,多个节点不能重复,主节点为0, 其他节点可以是1,2..
NPUS_PER_NODE=8  # 单节点NPU芯片数量
WORLD_SIZE=$(($NPUS_PER_NODE*$NNODES)) # 全局NPU总数=单节点NPU数×节点数

TP=4
PP=2
SEQ_LENGTH=2048

DISTRIBUTED_ARGS="
    --nproc_per_node $NPUS_PER_NODE \
    --nnodes $NNODES \
    --node_rank $NODE_RANK \
    --master_addr $MASTER_ADDR \
    --master_port $MASTER_PORT
"

torchrun $DISTRIBUTED_ARGS inference_4_midea_test.py \
         --use-mcore-models \
         --tensor-model-parallel-size ${TP} \
         --pipeline-model-parallel-size ${PP} \
         --load ${CHECKPOINT} \
         --spec mindspeed_llm.tasks.models.spec.qwen3_spec layer_spec \
         --kv-channels 128 \
         --qk-layernorm \
         --num-layers 40 \
         --hidden-size 5120 \
         --use-rotary-position-embeddings \
         --untie-embeddings-and-output-weights \
         --num-attention-heads 40 \
         --ffn-hidden-size 17408 \
         --max-position-embeddings 40960 \
         --seq-length ${SEQ_LENGTH} \
         --make-vocab-size-divisible-by 1 \
         --padded-vocab-size 151936 \
         --rotary-base 1000000 \
         --micro-batch-size 1 \
         --disable-bias-linear \
         --swiglu \
         --use-rotary-position-embeddings \
         --tokenizer-type PretrainedFromHF \
         --tokenizer-name-or-path ${TOKENIZER_PATH} \
         --normalization RMSNorm \
         --position-embedding-type rope \
         --norm-epsilon 1e-6 \
         --hidden-dropout 0 \
         --attention-dropout 0 \
         --max-new-tokens 256 \
         --no-gradient-accumulation-fusion \
         --attention-softmax-in-fp32 \
         --exit-on-missing-checkpoint \
         --no-masked-softmax-fusion \
         --group-query-attention \
         --num-query-groups 8 \
         --seed 42 \
      	 --eval-data-path ${EVAL_DATA_PATH} \
       	 --eval-data-size 1000 \
  	     --temperature 0.00001 \
                | tee $eval_log_path

在平台托管训练下发任务,执行脚本

cd scripts/qwen3-14b && bash eval_qwen3_14b_lora_customed10k.sh

6.5 MG权重转为HF格式

使用MindSpeed-LLM 训练后,如果希望将权重转为HF格式,使用脚本 ckpt_convert_qwen3_mcore2hf_lora.sh ,关键代码如下

export CUDA_DEVICE_MAX_CONNECTIONS=1

OUTPUT_BASE_DIR=/data/qwen3
log_path="${OUTPUT_BASE_DIR}/14b/logs/ckpt_convert_qwen3_mcore2hf_lora.log"
mkdir -p ${OUTPUT_BASE_DIR}/14b/logs

python convert_ckpt.py \
    --use-mcore-models \
    --model-type GPT \
    --load-model-type mg \
    --save-model-type hf \
    --target-tensor-parallel-size 1 \
    --target-pipeline-parallel-size 1 \
    --spec mindspeed_llm.tasks.models.spec.qwen3_spec layer_spec \
    --load-dir  ${OUTPUT_BASE_DIR}/14b/save_weights_lora/qwen3_14b_mcore_tp4pp2_customed10k_qwen3_think_merge/ \
    --save-dir models/Qwen3-14B_lora/ \
    --model-type-hf qwen3 \
        | tee $log_path

cp -rf models/Qwen3-14B_lora/mg2hf ${OUTPUT_BASE_DIR}/14b/save_weights_lora/

注意:

  • --save-model-type参数设置为 hf

  • save-dir 参数设置为原始hf权重的路径,脚本执行后,会在该目录下生成mg2hf的目录存放转换后的权重。

  • tp和pp都设置为1: --target-tensor-parallel-size 1 , --target-pipeline-parallel-size 1

  • 由于Lora训练过程中使用fp16完成,为了不影响精度,在原始HF权重的配置文件config.json,需将 "torch_dtype": "bfloat16", 配置改为 "torch_dtype": "float16",修改后检查如下

    # grep -rn  "torch_dtype" models/Qwen3-14B_lora/config.json 
    25:  "torch_dtype": "float16",

在平台托管训练下发任务,执行脚本

cd scripts/qwen3-14b && bash ckpt_convert_qwen3_mcore2hf_lora.sh

运行后部分日志截图如下

image-20250824175509046

转换后生成目录文件如下:

/data/qwen3//14b/save_weights_lora/mg2hf/
├── config.json
├── generation_config.json
├── model-00001-of-00006.safetensors
├── model-00002-of-00006.safetensors
├── model-00003-of-00006.safetensors
├── model-00004-of-00006.safetensors
├── model-00005-of-00006.safetensors
├── model-00006-of-00006.safetensors
└── model.safetensors.index.json

6.6 结果总结

Lora微调评测得分0.894,与GPU持平。

七、预训练

7.1 预训练数据集转换为bin格式

预训练数据集使用enwiki数据集,原始数据集,下载好放到 datasets/enwiki/中,数据集转换脚本data_convert_qwen3_pretrain_enwiki.sh 关键代码如下

OUTPUT_BASE_DIR=/data/qwen3
mkdir -p ${OUTPUT_BASE_DIR}/pretrain_datasets_enwiki
log_path="${OUTPUT_BASE_DIR}/14b/logs/data_convert_qwen3_pretrain_enwiki.log"

python ./preprocess_data.py \
    --input datasets/enwiki/train-00000-of-00042-d964455e17e96d5a.parquet \
    --tokenizer-name-or-path models/Qwen3-14B/ \
    --tokenizer-type PretrainedFromHF \
    --handler-name GeneralPretrainHandler \
    --output-prefix ${OUTPUT_BASE_DIR}/pretrain_datasets_enwiki/enwiki \
    --json-keys text \
    --workers 4 \
    --log-interval 1000 \
        | tee $log_path

在平台托管训练中,选择单机8卡,下发任务,执行脚本

cd scripts/qwen3-14b && bash data_convert_qwen3_pretrain_enwiki.sh

运行后部分日志截图如下

image-20250823163245425

转换后生成的文件列表如下:

/data/qwen3/pretrain_datasets_enwiki/
├── enwiki_text_document
│   └── cache
├── enwiki_text_document.bin
└── enwiki_text_document.idx

7.2 预训练示例脚本

预训练启动脚本 pretrain_qwen3_14b_enwiki_4K_ptd.sh 关键代码如下

export CUDA_DEVICE_MAX_CONNECTIONS=1
export PYTORCH_NPU_ALLOC_CONF=expandable_segments:True
# 基础配置
NPUS_PER_NODE=16  #A3单节点16卡NPU
MASTER_ADDR=localhost #以本节点ip地址为master_ip
MASTER_PORT=6115 #本节点端口号为6015
NNODES=1  #单机,即一台节点,多机即多节点
NODE_RANK=0  #单机RANK为0,多机为(0,NNODES-1),不同节点不可重复
WORLD_SIZE=$(($NPUS_PER_NODE*$NNODES)) #最终使用的NPU数

OUTPUT_BASE_DIR=/data/qwen3

# 根据实际情况配置权重保存、权重加载、词表、数据集路径
CKPT_LOAD_DIR="${OUTPUT_BASE_DIR}/14b/mg_weights/qwen3_14b_mcore_tp4pp2/"  # 权重加载路径,填入权重转换时保存的权重路径
CKPT_SAVE_DIR="${OUTPUT_BASE_DIR}/14b/save_weights_pretrain/qwen3_14b_mcore_tp4pp2/"                # 训练完成后的权重保存路径
DATA_PATH="${OUTPUT_BASE_DIR}/pretrain_datasets_enwiki/enwiki_text_document"      # 数据集路径,填入数据预处理时保存的数据路径,注意需要添加后缀
TOKENIZER_PATH="models/Qwen3-14B/" # 词表路径,填入下载的开源权重词表路径
log_path="${OUTPUT_BASE_DIR}/14b/logs/pretrain_qwen3_14b_enwiki_4K_ptd.log"

TP=4  
PP=2 
CP=1  #序列并行
MBS=4 #设置micro-batch-size为4
GBS=64 #设置global-batch-size为128
SEQ_LENGTH=4096  #设置seq_length为4096 
TRAIN_ITERS=2000 
CP_TYPE='ulysses_cp_algo' #序列并行算法

DISTRIBUTED_ARGS="
    --nproc_per_node $NPUS_PER_NODE \
    --nnodes $NNODES \
    --node_rank $NODE_RANK \
    --master_addr $MASTER_ADDR \
    --master_port $MASTER_PORT
"

OPTIMIZE_ARGS="
    --use-flash-attn \
    --use-fused-rotary-pos-emb \
    --use-rotary-position-embeddings \
    --use-fused-swiglu \
    --use-fused-rmsnorm \
    --no-masked-softmax-fusion \
    --use-distributed-optimizer
"

TRAIN_ARGS="
    --micro-batch-size ${MBS} \
    --global-batch-size ${GBS} \
    --lr 1.25e-6 \
    --min-lr 1.25e-7 \
    --weight-decay 1e-1 \
    --lr-warmup-fraction 0.01 \
    --attention-dropout 0.0 \
    --hidden-dropout 0.0 \
    --clip-grad 1.0 \
    --adam-beta1 0.9 \
    --adam-beta2 0.95 \
    --seed 42 \
    --bf16 \
    --train-iters ${TRAIN_ITERS} \
    --seq-length ${SEQ_LENGTH} \
"

MODEL_PARALLEL_ARGS="
    --tensor-model-parallel-size ${TP} \
    --pipeline-model-parallel-size ${PP} \
    --context-parallel-size ${CP} \
    --context-parallel-algo ${CP_TYPE} \
"

GPT_ARGS="
    --use-mcore-models \
    --spec mindspeed_llm.tasks.models.spec.qwen3_spec layer_spec \
    --kv-channels 128 \
    --qk-layernorm \
    --num-layers 40 \
    --hidden-size 5120 \
    --untie-embeddings-and-output-weights \
    --num-attention-heads 40 \
    --ffn-hidden-size 17408 \
    --max-position-embeddings 40960 \
    --make-vocab-size-divisible-by 1 \
    --padded-vocab-size 151936 \
    --rotary-base 1000000 \
    --disable-bias-linear \
    --swiglu \
    --tokenizer-type PretrainedFromHF \
    --tokenizer-name-or-path ${TOKENIZER_PATH} \
    --normalization RMSNorm \
    --position-embedding-type rope \
    --norm-epsilon 1e-6 \
    --no-gradient-accumulation-fusion \
    --attention-softmax-in-fp32 \
    --exit-on-missing-checkpoint \
    --group-query-attention \
    --num-query-groups 8 \
    --no-load-optim \
    --no-load-rng \
    --tensorboard-dir MindSpeed-LLM/tb \
    --sequence-parallel
"

DATA_ARGS="
    --data-path $DATA_PATH \
    --split 100,0,0
"

OUTPUT_ARGS="
    --log-interval 1 \
    --save-interval 20000 \
    --eval-interval ${TRAIN_ITERS} \
    --eval-iters 0 \
    --log-throughput
"

torchrun $DISTRIBUTED_ARGS pretrain_gpt.py \
    $GPT_ARGS \
    $DATA_ARGS \
    $OUTPUT_ARGS \
    $OPTIMIZE_ARGS \
    $TRAIN_ARGS \
    $MODEL_PARALLEL_ARGS \
    --distributed-backend nccl \
    --tensorboard-dir ${OUTPUT_BASE_DIR}/14b/tb/pretrain/enwiki \
    --load ${CKPT_LOAD_DIR} \
    --save ${CKPT_SAVE_DIR} \
    | tee $log_path

7.3 预训练任务下发

在平台托管训练下发任务,执行脚本

cd scripts/qwen3-14b && bash pretrain_qwen3_14b_enwiki_4K_ptd.sh

运行后部分日志截图如下

image-20250823163654969

训练后,根据配置,将生成训练日志和tensorboard日志。

镜像已预置tensorboard,根据上面训练脚本设置,tensorboard日志目录为:/data/qwen3/14b/tb/pretrain/enwiki

打开实验环境的terminal, 使用以下命令启动tensorboard

tensorboard --logdir=/data/qwen3/14b/tb/full/customed10k --port=3000

观察Loss曲线如下:

image-20250823165437218

7.4 结果总结

稳定运行30小时,loss从2.075下降到1.2746