MindSpeed-LLM 0day 模型首发支持指南:GLM-4 / GLM-Z1 系列昇腾同步首发全流程实战
MindSpeed-LLM 0day 模型首发支持指南:GLM-4 / GLM-Z1 系列昇腾同步首发全流程实战
在模型发布的 Day-0(首发当天)即可在昇腾 NPU 上同步完成预训练、评估与推理,是 MindSpeed-LLM 面向最新开源模型提供的“同步首发”能力。本文以仓库 tests/0day/README_en.md 为核心,系统梳理 0day 系列(GLM-4 与 GLM-Z1 共 6 个模型规格)的支持清单、配套依赖、脚本目录与端到端跑通流程,并结合仓库源码(权重转换、模型 Spec、预训练脚本)给出参数级解读,帮助你理解“拿到新模型当天如何在昇腾集群上跑起来”的完整技术路径。
一、0day 首发机制与认证含义
“0day”指新模型官方权重公开发布的当天(Day-0),MindSpeed-LLM 即同步提供昇腾侧的适配脚本与配置,缩短社区模型到昇腾平台的迁移周期。仓库通过“认证”标记表达支持成熟度:
Pass:已经通过昇腾官方版本测试的模型;Test:当前处于待测试/内部测试阶段的模型。
需要特别说明的是(见模型脚本声明):0day 首发的模型脚本仅支持基本功能跑通,尚未完成充分的性能测试与验收测试,实际使用中可能存在未被发现的问题。官方正式版本会在充分验证后另行发布——这是使用 0day 脚本前必须了解的前提。
二、模型支持清单(0day 首发)
以下模型均基于 Megatron-Core(MCore) 实现,序列长度为 8K,由 Ascend 贡献,认证状态均为 Test:
| 模型 | 规格 | 脚本位置 | 序列 | 实现 | 集群 | 贡献方 | 认证 |
|---|---|---|---|---|---|---|---|
| GLM-4 | 9B | 8K | MCore | 1x8 | Ascend | Test | |
| GLM-4 | 32B | 8K | MCore | 4x8 | Ascend | Test | |
| GLM-4 | 32B-Base | 8K | MCore | 4x8 | Ascend | Test | |
| GLM-Z1 | 9B | 8K | MCore | 1x8 | Ascend | Test | |
| GLM-Z1 | 32B | 8K | MCore | 4x8 | Ascend | Test | |
| GLM-Z1 | Rumination-32B | 8K | MCore | 4x8 | Ascend | Test |
注:以上 ModelScope 下载链接源自原文档,权重请以模型官方发布渠道为准;仓库内仅提供昇腾侧的适配脚本与配置。
2.1 六个模型规格的脚本目录结构
每个模型目录下均包含 6 个脚本,覆盖从数据到权重的完整生命周期(以 GLM-4-9B-0414 为例):
| 脚本 | 作用 |
|---|---|
ckpt_convert_glm4_0414_hf2mcore.sh |
HuggingFace 权重 → Megatron-Core 权重(HF→MG) |
ckpt_convert_glm4_0414_mcore2hf.sh |
Megatron-Core 权重 → HuggingFace 权重(MG→HF) |
data_convert_glm4_0414_pretrain.sh |
原始语料 → Megatron 索引格式数据集 |
pretrain_glm4_9b_0414_8k_ptd.sh |
8K 序列预训练(torchrun + PTD 并行) |
evaluate_glm4_9b_0414_ptd.sh |
下游任务评估(默认 mmlu) |
generate_glm4_9b_0414_ptd.sh |
文本生成推理 |
其余规格目录(glm4-32b-0414、glm4-base-32b-0414、glm-z1-9b-0414、glm-z1-32b-0414、glm-z1-rumination-32b-0414)结构与上述完全一致,仅模型超参与并行配置不同。
三、端到端跑通流程:数据 → 权重 → 预训练 → 评估/推理
0day 脚本的使用顺序建议如下,每个环节都以仓库内脚本为可直接复制修改的模板。
3.1 第一步:数据预处理
data_convert_glm4_0414_pretrain.sh 调用仓库根目录的 preprocess_data.py,把原始文本/parquet 语料转换为 Megatron 的索引数据集(_text_document + .idx):
# 请按照您的真实环境修改 set_env.sh 路径
source /usr/local/Ascend/ascend-toolkit/set_env.sh
mkdir -p ./dataset/glm4_9b_0414_hf/
python ./preprocess_data.py \
--input ./dataset/train-00000-of-00001-a09b74b3ef9c3b56.parquet \
--tokenizer-name-or-path ./model_from_hf/glm4_0414_hf/ \
--output-prefix ./dataset/glm4_9b_0414_hf/alpaca \
--workers 4 \
--log-interval 1000 \
--tokenizer-type PretrainedFromHF
关键参数说明:
--tokenizer-type PretrainedFromHF:直接从 HuggingFace 权重目录加载分词器,无需单独构造 tokenizer 文件;--tokenizer-name-or-path:指向 HF 权重目录(含tokenizer_config.json、tokenizer.model等);--output-prefix:生成的索引数据集前缀,预训练脚本的--data-path即指向该前缀(如./dataset/GLM-4-32B-0414/alpaca_text_document);--workers 4:并行预处理线程数,可按节点算力调整。
各规格的数据脚本结构一致,仅输入文件与 tokenizer 路径不同(例如 GLM-4-32B-0414 数据脚本、GLM-Z1-9B 数据脚本)。
3.2 第二步:权重格式转换(HF ↔ MG)
预训练需要 Megatron-Core 格式权重,官方发布的原始权重为 HuggingFace 格式,因此必须先转换。0day 脚本使用仓库根目录的统一转换入口 convert_ckpt_v2.py:
HF → MG(ckpt_convert_glm4_0414_hf2mcore.sh):
source /usr/local/Ascend/ascend-toolkit/set_env.sh
python convert_ckpt_v2.py \
--model-type-hf glm4_9b \
--load-model-type hf \
--save-model-type mg \
--target-tensor-parallel-size 2 \
--target-pipeline-parallel-size 4 \
--load-dir ./model_from_hf/GLM-4-9B-0414 \
--save-dir ./model_weights/
MG → HF(ckpt_convert_glm4_0414_mcore2hf.sh):
source /usr/local/Ascend/ascend-toolkit/set_env.sh
python convert_ckpt_v2.py \
--model-type-hf glm4_9b \
--load-model-type mg \
--save-model-type hf \
--load-dir ./model_weights/glm4_9b_0414_mcore/ \
--save-dir ./model_from_hf/glm4_9b_0414_hf/
从源码看(convert_ckpt_v2.py),--load-model-type 与 --save-model-type 的合法取值均为 hf / mg,据此在 Hf2MgConvert 与 Mg2HfConvert 之间分发(见 convert_ckpt_v2.py)。其余核心参数:
--model-type-hf:HF 侧模型类型标识,0day 模型对应的取值为glm4_9b(9B 系)与glm4(32B 系);--target-tensor-parallel-size/--target-pipeline-parallel-size:转换后权重切分的 TP/PP 维度,必须与预训练脚本中的 TP/PP 配置一致(9B 与 32B 均为 TP=2、PP=4);--num-layer-list:PP 各 stage 的层数分布,仅 32B 系转换时显式指定,如15,15,15,16(对应 61 层拆到 4 个 PP stage,见 GLM-4-32B-Base HF→MG 脚本);--load-dir/--save-dir:输入输出权重目录。
转换完成后,预训练脚本通过 --load ${CKPT_LOAD_DIR} 加载切分后的 MG 权重继续训练,或用于后续评估/推理。
3.3 第三步:8K 序列预训练
以 GLM-4-9B-0414 预训练脚本 为例,其完整命令如下:
#!/bin/bash
export CUDA_DEVICE_MAX_CONNECTIONS=1
NPUS_PER_NODE=8
MASTER_ADDR=localhost
MASTER_PORT=6000
NNODES=1
NODE_RANK=0
WORLD_SIZE=$(($NPUS_PER_NODE*$NNODES))
CKPT_SAVE_DIR="your model save ckpt path"
DATA_PATH="your data path"
TOKENIZER_PATH="your tokenizer path"
CKPT_LOAD_DIR="your model ckpt path"
TP=2
PP=4
DISTRIBUTED_ARGS="
--nproc_per_node $NPUS_PER_NODE \
--nnodes $NNODES \
--node_rank $NODE_RANK \
--master_addr $MASTER_ADDR \
--master_port $MASTER_PORT
"
GPT_ARGS="
--spec mindspeed_llm.tasks.models.spec.gemma2_spec layer_spec \
--tensor-model-parallel-size ${TP} \
--pipeline-model-parallel-size ${PP} \
--sequence-parallel \
--use-mcore-models \
--use-flash-attn \
--post-norm \
--use-fused-rmsnorm \
--use-fused-swiglu \
--overlap-grad-reduce \
--overlap-param-gather \
--use-distributed-optimizer \
--num-layers 40 \
--hidden-size 4096 \
--ffn-hidden-size 13696 \
--num-attention-heads 32 \
--seq-length 8192 \
--micro-batch-size 1 \
--global-batch-size 64 \
--max-position-embeddings 8192 \
--padded-vocab-size 151552 \
--make-vocab-size-divisible-by 1 \
--group-query-attention \
--num-query-groups 2 \
--disable-bias-linear \
--add-qkv-bias \
--position-embedding-type rope \
--use-glm-rope \
--rotary-percent 0.5 \
--no-rope-fusion \
--normalization RMSNorm \
--swiglu \
--tokenizer-type PretrainedFromHF \
--tokenizer-name-or-path ${TOKENIZER_PATH} \
--lr 1.25e-6 \
--norm-epsilon 1e-05 \
--train-iters 2000 \
--lr-decay-style cosine \
--untie-embeddings-and-output-weights \
--attention-dropout 0.0 \
--init-method-std 0.01 \
--hidden-dropout 0.0 \
--no-masked-softmax-fusion \
--attention-softmax-in-fp32 \
--min-lr 1.25e-7 \
--weight-decay 1e-1 \
--lr-warmup-fraction 0.01 \
--clip-grad 1.0 \
--adam-beta1 0.9 \
--initial-loss-scale 4096 \
--adam-beta2 0.95 \
--no-load-optim \
--no-load-rng \
--no-gradient-accumulation-fusion \
--no-bias-swiglu-fusion \
--bf16 \
--ckpt-format torch
"
DATA_ARGS="
--data-path ${DATA_PATH} \
--split 100,0,0
"
OUTPUT_ARGS="
--log-interval 1 \
--save-interval 2000 \
--eval-interval 2000 \
--eval-iters 0 \
"
torchrun ${DISTRIBUTED_ARGS} pretrain_gpt.py \
${GPT_ARGS} \
${DATA_ARGS} \
${OUTPUT_ARGS} \
--load ${CKPT_LOAD_DIR} \
--save ${CKPT_SAVE_DIR} \
--distributed-backend nccl \
--transformer-impl local \
| tee logs/pretrain_glm4_9b_0414_8k_mcore.log
3.3.1 并行策略与分布式参数
- TP=2 / PP=4:9B 在单机 8 卡(1x8)上,2 路张量并行 × 4 路流水并行恰好铺满 8 卡;32B 系则在 4 节点 32 卡(4x8)上运行(
NNODES=4),见 GLM-4-32B 预训练脚本; --sequence-parallel:开启序列并行,把 LayerNorm/Dropout 区域的激活切分到 TP 组内,降低激活显存;--use-distributed-optimizer:分布式优化器,优化器状态按 TP 维度切分到各卡;--overlap-grad-reduce/--overlap-param-gather:梯度规约与参数聚合与计算重叠,提升通信效率;--transformer-impl local:使用本地 Transformer 实现(非 TransformerEngine),与--use-flash-attn配合在昇腾上启用 FlashAttention 融合算子;--distributed-backend nccl:注意该参数名沿用 NVIDIA 生态命名,在昇腾环境对应 NPU 集合通信后端(驱动层由 torch_npu 屏蔽差异);--num-layer-list 15,15,15,16:仅 32B 系脚本使用,把 61 层显式分配到 4 个 PP stage,实现各 stage 负载均衡。
3.3.2 模型结构与关键架构参数
这些参数刻画了 GLM-4/GLM-Z1 的模型结构,必须与官方权重一一对应,不能随意修改:
| 参数 | GLM-4-9B | GLM-4/GLM-Z1-32B 系 | 说明 |
|---|---|---|---|
--num-layers |
40 | 61 | Transformer 层数 |
--hidden-size |
4096 | 6144 | 隐藏层维度 |
--ffn-hidden-size |
13696 | 23040 | FFN 中间层维度 |
--num-attention-heads |
32 | 48 | 注意力头数 |
--num-query-groups |
2 | 2(Rumination 为 8) | GQA 查询组数 |
--max-position-embeddings |
8192 | 8192 / 131072(Base 与 Rumination) | 位置编码上限 |
--padded-vocab-size |
151552 | 151552 | 补齐后的词表大小 |
--rotary-percent |
0.5 | 0.5 | GLM 系列 RoPE 旋转比例 |
--norm-epsilon |
1e-05 | 1e-05 | RMSNorm epsilon |
其余结构与训练配置要点:
--use-glm-rope+--rotary-percent 0.5+--no-rope-fusion:GLM 系列使用 50% 旋转比例的 RoPE 且不做算子融合,这是 GLM 与 Llama 系(100% RoPE)的关键差异;--post-norm:Post-Norm 结构,配合下面的gemma2_spec;--normalization RMSNorm+--use-fused-rmsnorm:RMSNorm 归一化与融合实现;--swiglu+--use-fused-swiglu:SwiGLU 激活与融合算子;--untie-embeddings-and-output-weights:embedding 与输出层权重解耦(不共享);--group-query-attention+--num-query-groups 2:GQA 注意力,KV 头数少于 Q 头数;--bf16+--initial-loss-scale 4096:BF16 混合精度训练;--lr 1.25e-6/--min-lr 1.25e-7/--lr-decay-style cosine/--lr-warmup-fraction 0.01:1.25e-6 初始学习率 + cosine 衰减 + 1% warmup;--split 100,0,0:数据全部用于训练(0day 场景下不划分验证/测试集,配合--eval-iters 0)。
3.3.3 各规格脚本差异速查
| 规格 | 集群 | TP/PP | 附加参数 |
|---|---|---|---|
| GLM-4-9B-0414 | 1x8 | 2/4 | --add-qkv-bias |
| GLM-4-32B-0414 | 4x8 | 2/4 | --num-layer-list 15,15,15,16,无 --add-qkv-bias |
| GLM-4-32B-Base-0414 | 4x8 | 2/4 | --max-position-embeddings 131072,--num-layer-list 15,15,15,16 |
| GLM-Z1-9B-0414 | 1x8 | 2/4 | 同 GLM-4-9B,--save-interval 500 |
| GLM-Z1-32B-0414 | 4x8 | 2/4 | 同 GLM-4-32B |
| GLM-Z1-Rumination-32B-0414 | 4x8 | 2/4 | --num-query-groups 8,--max-position-embeddings 131072,--num-layer-list 15,15,15,16 |
3.4 第四步:下游任务评估
评估脚本 调用仓库根目录的 evaluation.py,对已训练/转换好的 MG 权重执行任务评估:
torchrun ${DISTRIBUTED_ARGS} evaluation.py \
--spec mindspeed_llm.tasks.models.spec.gemma2_spec layer_spec \
--post-norm \
--task-data-path ${DATA_PATH} \
--task ${TASK} \
--use-mcore-models \
--tensor-model-parallel-size 2 \
--pipeline-model-parallel-size 1 \
--num-layers 40 \
--hidden-size 4096 \
--ffn-hidden-size 13696 \
--num-attention-heads 32 \
--group-query-attention \
--num-query-groups 2 \
--seq-length 8192 \
--max-new-tokens 1 \
--max-position-embeddings 8192 \
...
--no-chat-template \
--load ${CHECKPOINT} \
--tokenizer-type PretrainedFromHF \
--tokenizer-name-or-path ${TOKENIZER_PATH} \
...
--bf16 \
--ckpt-format torch
要点解读:
TASK默认配置为mmlu,DATA_PATH指向任务评测数据目录;不同任务需要不同的--max-new-tokens取值,脚本注释明确提示“请遵循 README 中的说明”进行调整;- 评估阶段通常使用
--pipeline-model-parallel-size 1(仅 TP 切分),以减少流水并行对评测吞吐的影响; --no-chat-template:0day 预训练模型为基座模型,评测时不套用对话模板;- 架构参数(
--num-layers、--hidden-size、--num-query-groups等)必须与训练/转换时完全一致,否则权重加载会失败; --exit-on-missing-checkpoint:权重文件缺失时立即报错退出,避免静默错误。
3.5 第五步:文本生成推理
生成脚本 调用 inference.py 执行单卡/双卡文本生成:
torchrun ${DISTRIBUTED_ARGS} inference.py \
--spec mindspeed_llm.tasks.models.spec.gemma2_spec layer_spec \
--tensor-model-parallel-size 2 \
--pipeline-model-parallel-size 1 \
--use-mcore-models \
--num-layers 40 \
--hidden-size 4096 \
--ffn-hidden-size 13696 \
--seq-length 8192 \
--group-query-attention \
--num-query-groups 2 \
...
--max-new-tokens 256 \
--load ${CHECKPOINT} \
--tokenizer-type PretrainedFromHF \
...
--bf16 \
--transformer-impl local \
--ckpt-format torch \
| tee logs/generate_glm4_9b_0414_mcore.log
与评估脚本的差异主要在于:--max-new-tokens 256(生成长度)、NPUS_PER_NODE=2(生成时仅用 2 卡、TP=2),其余架构参数保持一致。
四、底层模型 Spec 源码解读:为什么 GLM-4/GLM-Z1 使用 gemma2_spec
0day 脚本统一通过 --spec mindspeed_llm.tasks.models.spec.gemma2_spec layer_spec 指定模型结构。该参数指向仓库内的 mindspeed_llm/tasks/models/spec/gemma2_spec.py,它定义了一个基于 Post-Norm 结构的 Transformer Layer Spec:
- 层模块使用
TransformerLayerWithPostNorm(带 post-MLP LayerNorm 与 post-Attention LayerNorm 的变体),对应脚本中的--post-norm; - 归一化统一采用
PTNorm(Precision-Transformer Norm 包装,底层为 RMSNorm 类归一化),覆盖input_layernorm、pre_mlp_layernorm、post_mlp_layernorm、post_attn_norm,对应脚本中的--normalization RMSNorm; - 自注意力采用因果掩码(
AttnMaskType.causal),QKV 为ColumnParallelLinear,输出投影为RowParallelLinear,与脚本中 TP=2 的张量并行切分方式一致; - MLP 子模块由
_get_mlp_module_spec生成,use_te=False表示不使用 TransformerEngine 实现,对应脚本的--transformer-impl local; - 提供
sharded_state_dict_keys_map完成注意力/MLP 内部 LayerNorm 权重的 key 映射(input_layernorm.↔self_attention.linear_qkv.layer_norm_等),这是 MG 权重可以正确加载/保存的关键机制。
从源码结构可以推断:GLM-4 / GLM-Z1 系列采用与 Gemma2 相同的 Post-Norm + 层内双 LayerNorm 布局,因此直接复用 gemma2_spec 而无需为每个模型单独编写 Spec 文件——这也是 0day 适配能快速交付的原因之一。
五、配套版本与依赖说明
原文档明确给出 0day 模型的依赖配套(注意:昇腾底层组件当前均为“在研版本”):
| 依赖软件 | 版本 |
|---|---|
| 昇腾 NPU 驱动 | 在研版本 |
| 昇腾 NPU 固件 | 在研版本 |
| Toolkit(开发套件) | 在研版本 |
| Kernel(算子包) | 在研版本 |
| NNAL(Ascend Transformer Boost 加速库) | 在研版本 |
| Python | 3.10 |
| PyTorch | 2.5 |
| torch_npu 插件 | 2.5 |
| apex | 2.5 |
| transformers | 4.51.3 |
使用前提:
- 需安装昇腾 NPU 驱动、固件与 CANN 工具链(Toolkit/Kernel),并
source /usr/local/Ascend/ascend-toolkit/set_env.sh完成环境初始化(0day 脚本均内置该步骤); - Python 3.10 + PyTorch 2.5 + torch_npu 2.5 + apex 2.5 为脚本验证过的软件栈;
transformers==4.51.3与官方参考实现对齐(见下节),tokenizer 加载依赖该版本行为;- 由于驱动/固件/工具链处于在研状态,建议以昇腾官方渠道发布的配套版本为准,不要混用不同版本组合。
六、版本声明与参考实现
6.1 参考实现
0day 模型的适配以上述 transformers 版本为参考基线:
# 参考实现:HuggingFace transformers v4.51.3 分支
commit_id=5f4ecf2
该参考实现用于对齐模型结构、分词器行为与权重组织方式;MindSpeed-LLM 侧则通过 convert_ckpt_v2.py 与 gemma2_spec.py 完成格式与结构映射。
6.2 变更记录
- 2025-04-22:首次发布。首批 0day 模型(GLM-4 三规格 + GLM-Z1 三规格)上线,提供预训练/评估/推理/权重转换全套脚本。
七、使用限制与注意事项
结合模型脚本声明与脚本实际情况,使用 0day 系列脚本时请注意:
- 功能保底,性能未验证:当前脚本仅保证基本功能跑通,未完成充分的性能测试与验收测试,实际使用中可能遇到未被发现的问题;
- 认证状态为 Test:表中所有模型均为
Test(待测试)状态,正式版本待充分验证后另行发布,生产环境使用前请关注后续更新; - 路径必须按环境修改:脚本中的
CKPT_SAVE_DIR、DATA_PATH、TOKENIZER_PATH、CKPT_LOAD_DIR为占位符或示例路径,运行前必须替换为真实路径; - 并行配置一致性:权重转换时的
--target-tensor-parallel-size/--target-pipeline-parallel-size/--num-layer-list必须与预训练、评估、推理脚本中的 TP/PP 完全一致; - 架构参数不可改动:
--num-layers、--hidden-size、--num-query-groups等结构参数由模型权重决定,仅可调整学习率、batch size、训练轮次等训练策略参数; - 评测 max-new-tokens:不同评测任务需按任务说明调整
--max-new-tokens,错误取值会导致评测指标失真。
八、小结
0day 系列是 MindSpeed-LLM 在昇腾平台上“模型发布即同步支持”的落地范式:以 tests/0day/ 下每个模型的 6 个脚本为骨架,覆盖数据预处理、HF↔MG 权重转换、8K 序列预训练、任务评估与文本生成五个环节;以 gemma2_spec.py 与 convert_ckpt_v2.py 为源码级支撑,复用 Post-Norm Transformer Spec 与统一转换框架快速适配新模型。对希望在新模型发布的当天就在昇腾集群上跑通预训练的开发者而言,直接以任一 0day 模型目录为模板、按本文流程替换路径与数据,即可复现完整的 Day-0 首发流程。