PaddleNLP 昇腾 NPU 适配实战:llama2-13B 微调训练与静态图推理全流程指南

原创2026-09-24 20:29:071,630 阅读
文章标签:人工智能大模型预训练微调LoRARLHF强化学习分布式训练模型推理服务推理引擎模型量化模型压缩本地部署NLP

PaddleNLP 昇腾 NPU 适配实战:llama2-13B 微调训练与静态图推理全流程指南

本指南基于 PaddleNLP 官方在昇腾 NPU 上的适配文档(docs/zh/llm/devices/npu/llama/README.md),完整讲解如何在昇腾 910 NPU 机器上,从环境搭建、数据准备、SFT/LoRA/Pretrain 三种训练策略,到静态图导出与推理的端到端流程。读完本文,你将掌握 PaddleNLP 在 NPU 上的训推一体化入口用法、关键并行与融合配置项,以及通信掩盖、自定义算子统一抽象、Layer 级算子融合等底层优化原理。

PaddleNLP 在昇腾 NPU 上对 llama2-13B 模型进行了深度适配和优化,该套件实现了昇腾 NPU 和 GPU 的训推入口基本统一,达到了"无缝切换"的效果。也就是说,同一份 run_finetune.py / run_pretrain.py 训练代码,通过 --device npu 参数即可切换到昇腾硬件运行,无需改动组网逻辑。

一、技术亮点概览

根据官方文档,该套件在技术领先性上主要体现在四个方面:

  • 训练策略完全适配:支持 4D 混合并行(张量并行、流水线并行、Sharding、数据并行可自由组合),灵活适应多种训练策略;
  • 训练性能极致优化:官方文档说明,95% 的通信被掩盖在计算中,软硬结合提供极致性能;
  • 低门槛性能调优:分布式策略自动寻优能力打通多硬件,完全屏蔽硬件复杂性,使用户可以轻松挖掘算力极限;
  • 推理成本极致压缩:推理支持 Layer 级算子融合,且融合算子已支持动态插入功能。

这些能力在仓库中均有对应的脚本与源码支撑:训练入口脚本位于 llm/devices/npu/llama/ 目录,自定义算子统一抽象位于 paddlenlp/transformers/llama/fusion_ops.py,NPU 专用融合算子的编译入口位于 csrc/npu/。

二、硬件环境要求与芯片验证

在开始之前,你需要一台昇腾 NPU 机器。官方文档对该机器的系统要求如下:

芯片类型 驱动版本 CANN 版本
昇腾 910 23.0.3 CANN 8.0.RC1

注意:官方示例使用 8 卡机器,并通过"微调训练 + 推理"的流程演示运行方法,因此下列所有脚本均按 8 张 NPU 卡(N1C8,即 1 节点 8 卡)的资源配置。

如果要验证你的机器是否为昇腾 910B 芯片,只需在系统环境下输入以下命令,看是否有输出:

lspci | grep d802

#例如:$ lspci | grep d802 , 输出如下
28:00.0 Processing accelerators: Huawei Technologies Co., Ltd. Device d802 (rev 20)
29:00.0 Processing accelerators: Huawei Technologies Co., Ltd. Device d802 (rev 20)
38:00.0 Processing accelerators: Huawei Technologies Co., Ltd. Device d802 (rev 20)
39:00.0 Processing accelerators: Huawei Technologies Co., Ltd. Device d802 (rev 20)
48:00.0 Processing accelerators: Huawei Technologies Co., Ltd. Device d802 (rev 20)
49:00.0 Processing accelerators: Huawei Technologies Co., Ltd. Device d802 (rev 20)
59:00.0 Processing accelerators: Huawei Technologies Co., Ltd. Device d802 (rev 20)
5a:00.0 Processing accelerators: Huawei Technologies Co., Ltd. Device d802 (rev 20)
98:00.0 Processing accelerators: Huawei Technologies Co., Ltd. Device d802 (rev 20)
99:00.0 Processing accelerators: Huawei Technologies Co., Ltd. Device d802 (rev 20)
b8:00.0 Processing accelerators: Huawei Technologies Co., Ltd. Device d802 (rev 20)
b9:00.0 Processing accelerators: Huawei Technologies Co., Ltd. Device d802 (rev 20)
c8:00.0 Processing accelerators: Huawei Technologies Co., Ltd. Device d802 (rev 20)
c9:00.0 Processing accelerators: Huawei Technologies Co., Ltd. Device d802 (rev 20)
d9:00.0 Processing accelerators: Huawei Technologies Co., Ltd. Device d802 (rev 20)
da:00.0 Processing accelerators: Huawei Technologies Co., Ltd. Device d802 (rev 20)

其中 d802 是昇腾 910B 系列芯片在 PCIe 设备列表中的设备 ID,16 条输出对应 8 卡机器(含加速器与对应管理设备)。

三、环境准备(约 5~15 分钟)

1. 拉取官方开发镜像

官方文档提醒:此镜像仅为开发环境,镜像中不包含预编译的飞桨安装包,PaddlePaddle 与 PaddleCustomDevice 需要随后单独安装。

docker pull registry.baidubce.com/device/paddle-npu:cann80RC1-ubuntu20-x86_64-gcc84-py39

2. 启动容器

参考如下命令启动容器,可以通过设置 ASCEND_RT_VISIBLE_DEVICES 指定容器可见的昇腾卡号:

docker run -it --name paddle-npu-dev -v $(pwd):/work \
    --privileged --network=host --shm-size=128G -w=/work \
    -v /usr/local/Ascend/driver:/usr/local/Ascend/driver \
    -v /usr/local/bin/npu-smi:/usr/local/bin/npu-smi \
    -v /usr/local/dcmi:/usr/local/dcmi \
    -e ASCEND_RT_VISIBLE_DEVICES="0,1,2,3,4,5,6,7" \
    registry.baidubce.com/device/paddle-npu:cann80RC1-ubuntu20-x86_64-gcc84-py39 /bin/bash

参数要点说明:

  • --privileged --network=host:以特权模式并复用宿主机网络,保证 HCCL 集合通信与驱动访问正常;
  • --shm-size=128G:增大共享内存,避免分布式训练与 DataLoader 场景下的共享内存不足;
  • -v 挂载 /usr/local/Ascend/driver、/usr/local/bin/npu-smi、/usr/local/dcmi:将宿主机的昇腾驱动、NPU 监控工具与设备管理组件透传进容器;
  • ASCEND_RT_VISIBLE_DEVICES="0,1,2,3,4,5,6,7":指定容器可见的 8 张昇腾卡逻辑编号。

3. 安装 PaddlePaddle

paddlepaddle(飞桨)深度学习框架,提供运算基础能力:

python -m pip install paddlepaddle==3.0.0b0 -i https://www.paddlepaddle.org.cn/packages/stable/cpu/

4. 安装 PaddleCustomDevice

paddleCustomDevice 是飞桨深度学习框架的自定义硬件接入实现,提供 NPU 的算子实现:

python -m pip install paddle-custom-npu==3.0.0b0 -i https://www.paddlepaddle.org.cn/packages/stable/npu/

如需源码编译安装,可参考 PaddleCustomDevice 仓库 NPU 后端的官方文档(本仓库 csrc/npu/README.md 中对安装步骤亦有提及)。

5. 克隆 PaddleNLP 仓库并安装依赖

PaddleNLP 是基于飞桨的自然语言处理和大语言模型(LLM)开发库,存放了基于飞桨框架实现的各种大模型,llama2-13B 模型也包含其中。为了便于更好地使用 PaddleNLP,需要克隆整个仓库:

git clone https://gitcode.com/gh_mirrors/pa/PaddleNLP.git
cd PaddleNLP
python -m pip install -r requirements.txt
python -m pip install -e .

6. 编译安装 paddlenlp_ops

PaddleNLP 仓库内置了部分昇腾专用的融合算子,以便用户享受到极致压缩的推理成本。编译安装命令如下:

cd csrc/npu
python setup.py build bdist_wheel
pip install dist/paddlenlp_ops-0.0.0-cp39-cp39-linux_x86_64.whl
cd -

从源码看,csrc/npu/setup.py 将构建产物封装为名为 paddlenlp_ops 的 Python 包,其 package_dir 指向 python 目录(即 csrc/npu/python/paddlenlp_ops/),并以 BinaryDistribution 方式发布(has_ext_modules 返回 True),表明该 wheel 内含预编译的 NPU 自定义算子二进制,安装后在飞桨运行时会被动态加载。需要说明的是,0.0.0 版本号与 cp39 标记由当前仓库的构建配置决定,实际安装请以你编译产出的 wheel 文件名为准。

四、数据准备(约 2~5 分钟)

SFT(Supervised Fine-Tuning,精调)为精调策略,仓库提供了广告生成数据集 demo 便于调试使用:

cd llm/devices/npu/llama
wget https://bj.bcebos.com/paddlenlp/datasets/examples/AdvertiseGen.tar.gz
tar -zxvf AdvertiseGen.tar.gz

解压后得到 data/ 目录,训练脚本中的 --dataset_name_or_path "data/" 即指向该目录。

PaddleNLP 支持的精调数据格式为:每行包含一个字典的 json 文件,每个字典包含以下字段:

  • src:str, List(str),指模型的输入指令(instruction)、提示(prompt),模型应该执行的任务;
  • tgt:str, List(str),指模型的输出。

样例数据:

{"src": "类型#裙*颜色#蓝色*风格#清新*图案#蝴蝶结", "tgt": "裙身处采用立体蝴蝶结装饰辅以蓝色条带点缀,令衣身造型饱满富有层次的同时为其注入一丝甜美气息。将女孩清新娇俏的一面衬托而出。"}
...
#您可以根据此格式自行制作精调数据。

五、训练:三种策略入口脚本详解

本目录提供了 Pretrain / SFT / LoRA 三个入口脚本,并且已经按照 8 张 910 芯片的训练资源优化了并行策略等配置供参考:

1. SFT 微调训练(官方文档估计耗时约 4 小时)

启动微调训练:

bash llama_npu_sft_N1C8.sh

该脚本(可在 llm/devices/npu/llama/llama_npu_sft_N1C8.sh 中查看完整内容)首先设置一组 NPU/HCCL 运行环境变量,然后调用 paddle.distributed.launch 拉起 8 卡分布式训练,最终执行 run_finetune.py。核心环境变量与含义如下:

  • FLAGS_npu_storage_format=1:启用 NPU 存储格式优化(BF16 相关数据布局优化);
  • FLAGS_use_stride_kernel=0:关闭 stride kernel 路径,使用 NPU 更友好的连续布局;
  • HCCL_OP_BASE_FFTS_MODE_ENABLE=TRUE:开启 HCCL(华为集合通信库)的 FFTS 模式;
  • HCCL_INTRA_PCIE_ENABLE=0、HCCL_INTRA_ROCE_ENABLE=1:从变量名推断,即关闭节点内 PCIe 通信、开启 RoCE 网络通信,保证 8 卡之间的高速互联;
  • MULTI_STREAM_MEMORY_REUSE=1:开启多流内存复用;
  • FLAGS_allocator_strategy=naive_best_fit:设置飞桨显存分配策略为朴素最佳适配;
  • ASCEND_RT_VISIBLE_DEVICES="0,1,2,3,4,5,6,7":指定 8 张昇腾卡;
  • FLAGS_NPU_MC2=1:开启 NPU 通信计算融合(详见后文"通信掩盖技术");
  • MC2_Recompute=1:配合 MC2 的重计算开关。

SFT 训练的关键超参与并行配置逐项说明:

参数 取值 说明
--device "npu" npu 训练后端切换为昇腾 NPU,实现与 GPU 训推入口的统一
--model_name_or_path meta-llama/Llama-2-13b 预训练模型权重来源
--dataset_name_or_path "data/" data/ 上文准备好的 AdvertiseGen 精调数据集
--output_dir ./output/sft_bf16_llama_N1C8 训练产出(含 merge 后的权重)
--per_device_train_batch_size 2 2 单卡 batch size
--gradient_accumulation_steps 64 64 梯度累积步数,等效全局 batch = 8 × 2 × 64
--max_steps 100 100 最大训练步数(脚本第一个命令行参数可覆盖,默认 100,便于快速调试)
--learning_rate 3e-06 3e-06 SFT 学习率
--warmup_steps 20 20 warmup 步数
--src_length 1024 1024 输入序列截断长度
--max_length 4096 4096 样本最大长度(与 --pad_to_multiple_of 4096 配合保证整块 padding)
--bf16 true / --fp16_opt_level "O2" true / O2 BF16 混合精度 + O2 优化等级
--tensor_parallel_degree 8 8 张量并行度,8 卡全开
--pipeline_parallel_degree 1 1 流水线并行度,本脚本未启用
--sharding "stage1" stage1 Sharding 策略一阶段
--sequence_parallel 1 1 开启序列并行
--use_flash_attention 1 1 开启 FlashAttention
--use_fused_rope 1 / --use_fused_rms_norm 1 1 启用融合 RoPE 与融合 RMSNorm 算子
--fuse_attention_qkv true / --fuse_attention_ffn true true 融合 attention 的 QKV 投影与 FFN
--amp_master_grad true true 混合精度下保留 master 梯度
--recompute false false 未开启重计算(配合 MC2_Recompute 场景可按需开启)

2. LoRA 参数高效微调

llama_npu_lora_N1C8.sh 与 SFT 脚本结构基本一致,差异在于:

  • 基座模型改为 meta-llama/Llama-2-13b-chat(对话版);
  • 增加 --lora true 与 --lora_rank 32,以 rank=32 的 LoRA 低秩适配器进行参数高效微调,输出目录为 ./output/lora_bf16_llama_N1C8;
  • 未显式配置 --sharding(默认配置),并行部分同样采用 tensor_parallel_degree 8。

启动方式相同:

bash llama_npu_lora_N1C8.sh

3. Pretrain 预训练

llama_npu_ppt_N1C8.sh 面向从头预训练场景,调用的是 llm/run_pretrain.py,其并行组合与 SFT 有所不同:

  • --tensor_parallel_degree 4 搭配 --sharding "stage1" 与 --sharding_parallel_degree 2,即 4 路张量并行 × 2 路 Sharding,仍占用 8 卡;
  • --input_dir "./pre-data"、--split 949,50,1:预训练语料目录与训练/验证/测试划分;
  • --max_seq_length 4096、--per_device_train_batch_size 2、--gradient_accumulation_steps 32;
  • 开启 --use_flash_attention 1、--use_fused_rms_norm 1、--use_fused_rope true、--fuse_attention_qkv true、--fuse_attention_ffn true 全套融合算子;
  • 张量并行侧配置 --tensor_parallel_config "enable_mp_async_allreduce enable_mp_skip_c_identity",流水线侧配置 --pipeline_parallel_config "disable_partial_send_recv";
  • 开启 --unified_checkpoint 统一检查点,并通过 --load_sharded_model true / --save_sharded_model true 使用分片模型存取。

启动方式:

bash llama_npu_ppt_N1C8.sh

六、推理:静态图导出与生成

为了保障极致压缩的推理成本,NPU 推理使用静态图实现。因此需要先从训练产出的动态图模型中导出静态图模型,再执行推理。

1. 修改推理用 config.json

推理前需要准备推理用的配置文件。在 merge 好参数的路径下(本教程路径为 ./output/sft_bf16_llama_N1C8),将 config.json 更改为下面的内容:

{
  "architectures": [
    "LlamaForCausalLM"
  ],
  "bos_token_id": 1,
  "eos_token_id": 2,
  "hidden_act": "silu",
  "hidden_size": 5120,
  "initializer_range": 0.02,
  "intermediate_size": 13824,
  "max_position_embeddings": 4096,
  "model_type": "llama",
  "num_attention_heads": 40,
  "num_hidden_layers": 40,
  "num_key_value_heads": 40,
  "pad_token_id": 0,
  "pretraining_tp": 1,
  "rms_norm_eps": 1e-05,
  "rope_scaling": null,
  "tie_word_embeddings": false,
  "torch_dtype": "float16",
  "transformers_version": "4.31.0",
  "use_cache": false,
  "vocab_size": 32000
}

该配置对应 llama2-13B 的标准结构:40 层 decoder、40 个注意力头、hidden_size=5120、intermediate_size=13824、num_key_value_heads=40(非 GQA 分组,K/V 头数与 Q 头数一致),激活函数为 silu(即 SwiGLU 门控),位置编码采用 RoPE(rope_scaling: null 表示不缩放)。

2. 导出静态图模型

执行如下命令,将 ./output/sft_bf16_llama_N1C8/ 下的动态图权重导出为 ./inference 静态图推理模型:

bash export_npu.sh ./output/sft_bf16_llama_N1C8/ ./inference

export_npu.sh 内部先加载昇腾 CANN 与 ATB 运行环境,随后调用 llm/predict/export_model.py:

python predict/export_model.py --model_name_or_path ${src_path} --inference_model --output_path ${dst_path} --dtype float16 --device npu --block_attn

关键参数:

  • --inference_model:导出为推理专用静态图模型;
  • --dtype float16:推理精度为 FP16;
  • --device npu:目标硬件为昇腾 NPU;
  • --block_attn:开启 Block Attention(分块 KV Cache)支持。

脚本中两个位置参数默认值分别为 .npu/llama/output/sft_bf16_llama_N1C8/ 与 ./inference,均可按需覆盖。

3. 静态图推理

通过静态图模型执行推理:

bash predict_npu.sh ./inference

predict_npu.sh 同样先加载 CANN 与 ATB 环境,再调用 llm/predict/predictor.py:

python predict/predictor.py --model_name_or_path ${model_path} --inference_model --dtype "float16" --mode "static" --block_attn --device npu

其中 --mode "static" 明确指定以静态图模式加载推理模型,其余参数与导出阶段保持一致。

成功运行后,可以查看到推理结果的生成,样例如下:

***********Source**********
解释一下"温故而知新"
***********Target**********

***********Output**********
 "温故而知新" (wēn gù er zhī xīn) is a Chinese idiom that means "to know the old and appreciate the new." It is often used to describe the idea of learning from the past and being open to new experiences and ideas.

The word "温" (wēn) in this idiom means "old" or "past," and "故" (gù) means "origin" or "beginning." The word "知" (zhī) means "to know" or "to understand," and "新" (xīn) means "new."

So, the idiom "温故而知新" can be translated as "to know the old and appreciate the new," or "to learn from the past and embrace the new." It suggests that by understanding the past, we can gain a deeper appreciation for the present and be more open to new ideas and experiences.

This idiom is often used in Chinese culture to encourage people to learn from their heritage and traditions, while also being open to new ideas and perspectives. It is a reminder that knowledge and understanding are not limited to the present, but can also be gained from the past, and that by combining the old and the new, we can gain a more complete and nuanced understanding of the world.

七、核心特性源码级解析

1. 通信掩盖技术(MC2)

当模型训练开启张量并行后,计算过程中会出现很多"通信(AllReduce / ReduceScatter / AllGather)+ 矩阵乘(Matmul)"的算子组合。昇腾 910 芯片提供了一种高效的并行机制来掩盖通信开销。

通过设置 FLAGS_NPU_MC2=1 开启通信计算融合 pass,可以将绝大部分的张量并行通信开销掩藏在计算中,有效提升训练性能。在 llama_npu_sft_N1C8.sh 等三个训练脚本中均显式设置了 export FLAGS_NPU_MC2=1 与 export MC2_Recompute=1,即官方默认在 NPU 训练场景开启该特性。官方文档说明该方案可让 95% 的通信被掩盖在计算中。

2. 自定义算子的统一抽象

在实践中我们发现,fusion 算子对于大模型训练的性能影响往往很大。为了全面支持昇腾以及其他各种硬件的高性能算子,同时保持组网代码的简洁性,PaddleNLP 提供了统一的自定义算子接口实现。目前覆盖了 llama 中常见的 fusion_rope、fusion_rms_norm、fusion_flash_attention 在 NPU、GPU、XPU、GCU 等硬件上的实现。

从源码看,fusion_ops.py 的调度逻辑非常清晰——通过 get_env_device() 判断当前硬件后端,再分发到对应的自定义算子:

  • fusion_rope(L58-L131):在 NPU 上调用 core.eager._run_custom_op("fused_rope", ...),在 GCU 上调用 fused_rotary_embedding_gcu,在 GPU 上则回退到 paddle.incubate.nn.functional.fused_rotary_position_embedding;
  • fusion_rms_norm(L143-L163):分别对接 NPU 的 rms_norm_npu、MLU 的 rms_norm_mlu、GCU 的 rms_norm_gcu、Intel HPU 与 XPU 的各自实现,GPU 上可选用 fast_ln / fused_ln 第三方库;
  • fusion_flash_attention(L166-L313):NPU 上调用 flash_attention_npu 自定义算子(含 npu_is_casual 因果掩码开关),GCU/Intel HPU/GPU 各有独立路径,GPU 侧还支持 FlashMask 稀疏注意力与 Ring Flash Attention(上下文并行场景)。

这套统一抽象意味着:上层 llama 模型代码完全不需要感知底层硬件差异,只需通过 --use_flash_attention 1、--use_fused_rope 1、--use_fused_rms_norm 1 等开关开启融合,这也是"NPU 与 GPU 训推入口统一、无缝切换"的落地机制之一。

3. Layer 级算子融合

Layer 级算子融合显著提升计算效率,同时融合算子支持动态插入功能。在执行推理的过程中可以看到如下日志,即 IR pass 在静态图编译阶段动态插入各层融合算子:

--- Running IR pass [remove_residual_in_fused_bias_residual_layernorm]
--- Running IR pass [remove_residual_in_rms_norm]
--- Running IR pass [remove_blha_get_max_len]
--- Running IR pass [llama_fuse_attention_layer_begin]
--- Running IR pass [llama_fuse_attention_layer_end]
--- Running IR pass [llama_fuse_attention_layer]
--- Running IR pass [llama_fuse_lm_head_with_slice]
--- Running IR pass [llama_fuse_lm_head]
--- Running IR pass [llama_fuse_get_padding_offset]

从 pass 名称可以清晰看到融合的执行链条:先消除残差分支上的冗余算子(remove_residual_in_rms_norm 等),再融合整个 attention 层(llama_fuse_attention_layer*),最后融合 LM Head 与 padding offset 相关算子(llama_fuse_lm_head、llama_fuse_get_padding_offset),从而把整层计算压缩为极少数高效算子,显著降低推理阶段的算子调度与访存开销。

八、排错与验证建议

  • 芯片识别:若 lspci | grep d802 无输出,说明当前机器并非昇腾 910B 系列,需要更换硬件或确认驱动加载情况;
  • 环境变量生效:训练脚本依赖 /usr/local/Ascend/ascend-toolkit/set_env.sh 加载 CANN 环境,若脚本报找不到 npu-smi 或 CANN 相关错误,请先确认宿主机已正确安装驱动与 CANN 8.0.RC1 并挂载进容器;
  • 快速冒烟:SFT 脚本默认 max_steps=100(可通过 bash llama_npu_sft_N1C8.sh 20 覆盖为 20 步),适合先做端到端冒烟验证,再按需调大;
  • 推理链路检查:导出阶段必须确保 config.json 已按上文替换,且权重路径指向 merge 后的 ./output/sft_bf16_llama_N1C8,否则 export_model.py 会因结构信息不匹配而失败。

总结

PaddleNLP 在昇腾 NPU 上对 llama2-13B 提供了完整的训推一体化方案:以统一的 --device npu 入口复用 GPU 同款训练代码,通过 4D 混合并行(张量并行 × Sharding × 序列并行等)组织 8 卡资源,以 FLAGS_NPU_MC2=1 通信掩盖、fusion_ops.py 自定义算子统一抽象、推理期 Layer 级融合 IR pass 三层手段压榨性能,最终以"动态图训练 → 静态图导出 → 静态图推理"的链路完成从微调到落地的完整流程。文中的所有脚本与源码均可在本仓库 llm/devices/npu/llama/、paddlenlp/transformers/llama/fusion_ops.py 与 csrc/npu/ 中查看与验证。

登录后查看全文
PaddleNLP