Files
paddlepaddle--paddlenlp/docs/zh/llm/docs/llm_trainer.rst
T
wehub-resource-sync 2aaeece67c
Codestyle Check / Lint (push) Has been cancelled
Codestyle Check / Check bypass (push) Has been cancelled
Pipelines-Test / Pipelines-Test (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:37:14 +08:00

308 lines
13 KiB
ReStructuredText
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
=====================================================
飞桨大模型统一训练器 PaddleNLP Trainer
=====================================================
Trainer 特色能力简介
==========================
- **全策略分布式策略支持**
随着模型的复杂度越来越大,大规模分布式训练能力对LLM至关重要。
Trainer 提供了多种策略支持,支持从单卡、多卡数据并行,到 sharding 并行(stage1、2、3),到张量并行、流水线并行。做到了分布式训练的全策略支持。
Trainer 提供了简单易用的接口,可以轻松实现不同策略的训练。支持了混合精度训练、master weight/gradient、梯度累积等特性, 方便用户使用。
- **大模型统一断点存储支持**
大模型时代,模型使用张量并行、流水线并行等策略训练,需要将模型切分为多个部分存储。
与单模型存储格式不同,无法适配分布式切分策略改变,无法直接用于下游精调、推理等场景。
Trainer的 ``unified_checkpoint`` 技术 提供了统一断点存储接口,统一了分布式各种情况下模型存储格式,与单卡一致。
同时还支持了跨分布式策略断点续训,支持多机动态扩、缩容启动、支持异步保存等特性。
Trainer进阶分布式能力使用介绍
============================
本教程将以PaddleNLP中的LLaMA模型预训练为例,详细介绍 Trainer 使用。
**使用示例 TL:DR**
参数文档参见 https://paddlenlp.readthedocs.io/zh/latest/trainer.html
*关键配置项:*
.. code-block:: text
--sharding "stage1" --sharding_parallel_degree 2
sharding 参数表示开启sharding功能。
sharding_parallel_degree 表示sharding发生在多少路数据流之间。如果不想跨机sharding的话,可以设置为8
--tensor_parallel_degree 2
表示张量并行 将一层 transformer 计算划分到几张卡上去计算
--pipeline_parallel_degree 2
表示将transformer模型不同层划分为几块
注:
* 总卡数=sharding_parallel_degree * tensor_parallel_degree * pipeline_parallel_degree * data_parallel_degree
* data_parallel_degree 不需要传入参数设置,由 总卡数/(sharding_parallel_degree * tensor_parallel_degree * pipeline_parallel_degree) 计算得来
.. code-block:: bash
# 单机单卡
python train.py
# 单机(多机)多卡/数据并行
paddle.distributed.launch --devices "0,1,2,3,4,5,6,7" train.py
# 单机(多机)多卡/Sharding并行
paddle.distributed.launch --devices "0,1,2,3,4,5,6,7" train.py -sharding "stage2"
# 单机(多机)多卡/Sharding并行 + 数据并行 (sharding4 dp2)
paddle.distributed.launch --devices "0,1,2,3,4,5,6,7" train.py --sharding "stage2" --sharding_parallel_degree 4
# 单机(多机)多卡/ 张量并行 TP8
paddle.distributed.launch --devices "0,1,2,3,4,5,6,7" train.py --tensor_parallel_degree 8
# 单机(多机)多卡/ 张量并行+数据并行 TP4 DP2
paddle.distributed.launch --devices "0,1,2,3,4,5,6,7" train.py --tensor_parallel_degree 4
# 单机(多机)多卡/ 张量并行+sharding并行 TP4 Sharding2
paddle.distributed.launch --devices "0,1,2,3,4,5,6,7" train.py --tensor_parallel_degree 4 \
--sharding "stage1" --sharding_parallel_degree 2
# 单机(多机)多卡/ 张量并行+流水线并行 TP2 PP4
paddle.distributed.launch --devices "0,1,2,3,4,5,6,7" train.py --tensor_parallel_degree 2 \
--pipeline_parallel_degree 4
# 单机(多机)多卡/ 张量并行+流水线并行+sharding并行 TP2 PP2 Sharding2
paddle.distributed.launch --devices "0,1,2,3,4,5,6,7" train.py --tensor_parallel_degree 2 \
--pipeline_parallel_degree 2 \
--sharding "stage1" --sharding_parallel_degree 2
# 4D 并行,需要两机
# 单机(多机)多卡/ 张量并行+流水线并行+sharding并行 TP2 PP2 Sharding2 DP2
paddle.distributed.launch --devices "0,1,2,3,4,5,6,7" train.py --tensor_parallel_degree 2 \
--pipeline_parallel_degree 2 \
--sharding "stage1" --sharding_parallel_degree 2
Trainer 分布式能力
==================
功能特色:
* TP
* 简单配置即可实现参数自动切分加载 合并
* 组网改造简便,容易对齐精度
* PP
* 同时继承 PaddleNLP PertrainedModel
* 模型参数自动加载,参数名映射到单卡模型。
* Layer初始化参数全部config化,精简参数传递
通用分布式能力: DP + Sharding
------------------------------
对于通用的分布式能力, PaddleNLP适配了数据并行data_parallel, 分布式参数sharding功能的支持。
用户使用 paddle.distributed.launch --devices "0,1,2,3" train.py即可将运行的程序切换为多卡数据并行. 如果想要使用sharding功能, 减少模型显存占用, 指定参数--sharding "stage2"即可. 更多sharding功能配置见参数介绍部分.
DP 或者sharding,这类功能无需用户修改组网, 直接多卡即可运行。目前已经支持PaddleNLP所有模型。
混合并行分布式能力: TP + PP
------------------------------
飞桨4D并行, 即: ``data parallel`` + ``sharding parallel`` + ``tensor parallel`` + ``pipeline parallel`` .
混合并行这里, 主要添加了 ``tensor parallel`` (TP) 和 ``pipeline parallel`` (PP)支持.
目前, PaddleNLP主要对一些大模型, 如 GPT, Llama(系列)Qwen等做了 TP PP支持, 用户可以使用这些策略.相关代码实现可以参考llama训练的例子
流水线并行的组网改造可以参见modeling_pp.py当组网适配好 张量并行(TP), 流水线并行(PP)之后,
用户使用 ``--tensor_parallel_degree````--pipeline_parallel_degree`` 即可启用混合并行训练.
张量并行如何接入、使用?
===========================
Tensor Parallel接入:
------------------------------
当前大模型接入 张量并行(TP) 主要有以下步骤
* 模型config配置
* 此部分只需要配置一些默认参数,比如tensor_parallel_output之类的(是否合并最后TP计算出来的logits)
* 模型组网修改
* 核心工作:主要修改的点有,
i. Attention 模块 https://github.com/PaddlePaddle/PaddleNLP/blob/acfd537f3c859d80bf5d1f0a2fb26f485ef015b5/paddlenlp/transformers/llama/modeling.py#L363-L381
ii. MLP模块 https://github.com/PaddlePaddle/PaddleNLP/blob/acfd537f3c859d80bf5d1f0a2fb26f485ef015b5/paddlenlp/transformers/llama/modeling.py#L320-L338
iii. 词表模块 https://github.com/PaddlePaddle/PaddleNLP/blob/acfd537f3c859d80bf5d1f0a2fb26f485ef015b5/paddlenlp/transformers/llama/modeling.py#L655-L659
iv. LMHead https://github.com/PaddlePaddle/PaddleNLP/blob/acfd537f3c859d80bf5d1f0a2fb26f485ef015b5/paddlenlp/transformers/llama/modeling.py#L875-L887
* 此时修改较多,建议用户可以先修改 MLP模块 ,简单对齐之后,再去修改其他模块。参数转换对齐见后文。
* 参数切分自动转换mappings
* 当我们修改了网络的时候,需要与单卡模型对齐,验证正确性。
* 如llama代码,我们自提供了自动转换的接入函数,用户只需要配置 state_dict 中一些 linear 是 行切分或者列切分即可。 is_column
* `参考代码 <https://github.com/PaddlePaddle/PaddleNLP/blob/acfd537f3c859d80bf5d1f0a2fb26f485ef015b5/paddlenlp/transformers/llama/modeling.py#L565-L602>`_
.. image:: https://github.com/PaddlePaddle/PaddleNLP/assets/16911935/1d6be372-e9de-4ec2-a8aa-705a4bafb097
* 对齐TP与单卡精度
* 注意建议使用上文自动转换的mappinng配置,将极大减小工作量
* 注意使用float32进行精度对齐,需要 export NVIDIA_TF32_OVERRIDE=0 关闭TF32
Tensor Parallel 使用
------------------------------
一般而言,对于TP单独使用的情况:
1. 只需要初始化分布式环境,获得 ``tp_degree`` ``tp_rank``
2. 然后传入到模型,即可完成模型初始化
加载的模型参数,会根据实际的 ``tp_degree`` ``tp_rank`` ,自动将参数切分好,直接 运行 ``model.forward`` 可以做到与单卡一致的体验。
.. code-block:: python
tp_degree = paddle.distributed.get_world_size()
tp_rank = 0
if tp_degree > 1:
strategy = fleet.DistributedStrategy()
strategy.hybrid_configs = {
"dp_degree": 1,
"mp_degree": tp_degree,
"pp_degree": 1,
"sharding_degree": 1,
}
fleet.init(is_collective=True, strategy=strategy)
hcg = fleet.get_hybrid_communicate_group()
tp_rank = hcg.get_model_parallel_rank()
# Load the pretrained language model.
model = AutoModelForCausalLM.from_pretrained(
model_args.model_name_or_path,
tensor_parallel_degree=tp_degree,
tensor_parallel_rank=tp_rank,
dtype="float16",
)
流水线并行 (Pipeline Parallel) 如何接入、使用?
======================================================
Pipeline Parallel 接入
---------------------------
PP接入的本质是把模型写成一个 sequential 的形式,即模型之间的层是连续的不存在一些嵌套关系。我们实现了 PipelinePretrainedModel的模型基类。用户调用 add_sequential_layer即可添加模型一层。
从结果形式上而言就是把原来的模型LlamaForCausalLM 重写为 LlamaForCausalLMPipe
当前大模型接入 流水线并行(PP) 主要有以下步骤:
* 模型基类集成
* 注意,模型需要同时继承 PipelinePretrainedModel 和 PipelineLayer
* 模型的 config_class _get_tensor_parallel_mappings _init_weights与原模型相同
* `参考此处代码 <https://github.com/PaddlePaddle/PaddleNLP/blob/b5ca5bc767eddf2593839e47665e6b4abf2de91b/examples/language_model/llama/modeling_pp.py#L192-L202>`_
.. image:: https://github.com/PaddlePaddle/PaddleNLP/assets/16911935/92b99bd6-90e4-45d0-8723-cf14fc258466
* 添加模型的层。
* 模型layer 通过 LayerDesc 包裹
* Layer的初始化,只接受模型config一个参数
* add_sequential_layer 最后一个str参数是这一层模型,在原来网络中的前缀名
i. 比如 embedding 层。原来在模型中是 llama.embedding.weight 这里的前缀是 llama
ii. 后面的Decoder层,就是 llama.layers.0 llama.layers.1 之类
iii. 此处的名字,可以将模型的命名结构映射到单卡
.. image:: https://github.com/PaddlePaddle/PaddleNLP/assets/16911935/a511bc41-1ab3-414b-a076-09d17f06d94b
* 其他。配置一些其他选项,如:
a. 指定切分pp的层
b. virtual_pp
c. 初始化权重
.. image:: https://github.com/PaddlePaddle/PaddleNLP/assets/16911935/a1085022-d3c7-4b0c-9046-73af5a39231d
Pipeline Parallel 使用
------------------------
参见 `此处单测 <https://github.com/PaddlePaddle/PaddleNLP/blob/6c6e72bab2d5282df5a36d5e283f729fa89bccc6/examples/language_model/llama/tests/test_pipeline_parallel.py#L28-L67>`_ 使用LlamaForCausalLMPipe.from_pretrained 即可加载好模型。
.. code-block:: python
world_size = paddle.distributed.get_world_size()
pp_degree = world_size
tp_degree = 1
if world_size > 2:
pp_degree = 2
assert world_size % pp_degree == 0
tp_degree = world_size // pp_degree
strategy = fleet.DistributedStrategy()
strategy.hybrid_configs = {
"dp_degree": 1,
"mp_degree": tp_degree,
"pp_degree": pp_degree,
"sharding_degree": 1,
}
fleet.init(is_collective=True, strategy=strategy)
hcg = fleet.get_hybrid_communicate_group()
if pp_degree > 1:
model_class = LlamaForCausalLMPipe
else:
model_class = LlamaForCausalLM
model_name_or_path = "./llama-7b"
model = model_class.from_pretrained(
model_name_or_path,
tensor_parallel_degree=tp_degree,
tensor_parallel_rank=hcg.get_model_parallel_rank(),
lm_shift_labels=True,
tensor_parallel_output=False,
# use_flash_attention=True,
)
model.eval()
input_ids = paddle.to_tensor([[x for x in range(100, 110)]], dtype="int64")
labels = paddle.to_tensor([[x for x in range(101, 111)]], dtype="int64")
attention_mask = None
if pp_degree > 1:
pp_model = PipelineParallel(layers=model, hcg=hcg, strategy=strategy)
ret = pp_model.eval_batch(data=[input_ids, labels], compute_loss=True)
附录并行能力简介
==================
* `数据并行 <https://www.paddlepaddle.org.cn/documentation/docs/zh/guides/06_distributed_training/data_parallel/index_cn.html>`_
* `sharding 并行 <https://www.paddlepaddle.org.cn/documentation/docs/zh/guides/06_distributed_training/group_sharded_parallel_cn.html#fenzuqiefenbingxing>`_
* `张量并行 <https://www.paddlepaddle.org.cn/documentation/docs/zh/guides/06_distributed_training/model_parallel_cn.html#zhangliangmoxingbingxing>`_
* `流水线并行 <https://www.paddlepaddle.org.cn/documentation/docs/zh/guides/06_distributed_training/pipeline_parallel_cn.html>`_