PaddleNLP Topology 分布式训练拓扑详解:混合并行组的构建、rank 计算与种子管理

发布时间:2026/9/24 5:17:51
PaddleNLP Topology 分布式训练拓扑详解:混合并行组的构建、rank 计算与种子管理 人工智能大模型预训练微调LoRARLHF强化学习分布式训练【免费下载链接】PaddleNLPEasy-to-use and powerful LLM and SLM library with awesome model zoo.项目地址https://gitcode.com/gh_mirrors/pa/PaddleNLP点击查看免费下载导读在 PaddleNLP 的大模型训练框架中混合并行数据并行、流水并行、Sharding、张量并行、序列并行是支撑千亿级参数模型训练的核心手段而所有这些并行维度最终都要落到「如何把全局进程号rank映射到一个个通信组」这一基础问题上。paddlenlp.ops.distributed.utils.topo模块提供的Topology类正是这一映射的实现它以纯 NumPy 的数组索引方式从给定的各并行维度度数中推导出每个进程所属的 dp/pp/sharding/mp/sep 通信组并进一步派生出数据并行组data_info、is_last等训练调度所需的关键属性。读完本文你将掌握Topology的完整构造参数与内部推导逻辑理解order参数如何决定通信组的索引顺序并能在 PaddleNLP 的 Trainer 与自动并行auto parallel训练脚本中正确使用它完成随机种子管理与并行组查询。本文对应的 API 文档入口为 docs/zh/source/paddlenlp.ops.distributed.utils.topo.rst核心实现位于 paddlenlp/ops/distributed/utils/topo.py。模块定位PaddleNLP 混合并行体系中的拓扑抽象PaddleNLP 的分布式能力分为两条技术路线一条基于 Paddle 框架的fleet使用paddle.distributed.fleet.base.topology.CommunicateTopology等见 paddlenlp/rl/utils/reshard_utils.py另一条则是本模块提供的、与框架无关的纯 Python 拓扑推导工具。Topology属于后者它不依赖通信后端只负责纯数学层面的 rank 与通信组映射因此既轻量又易于测试与移植。模块的导出链路为paddlenlp/ops/distributed/utils/init.py 中导出Topology与get_rng_state_trackerpaddlenlp/ops/distributed/init.py 通过from .utils import *向上透出paddlenlp/ops/init.py 再通过from .distributed import *将Topology暴露到paddlenlp.ops顶层最终用户可直接from paddlenlp.ops import Topology这正是 paddlenlp/trainer/trainer_utils.py 的导入方式。Topology 构造参数五大并行维度与轴顺序Topology.__init__的完整签名如下对应 topo.pyTopology( device_rank, # 当前进程的全局 rank取自 paddle.distributed.get_rank() world_size, # 全部参与训练的进程数 dp_degreeNone, # 数据并行度数默认 None pp_degree1, # 流水并行度数默认 1 sharding_degree1, # Sharding 并行度数默认 1 mp_degree1, # 张量模型并行度数默认 1 sep_degree1, # 序列并行度数默认 1 order[dp, pp, sharding, mp, sep], # 轴顺序 )各维度含义参数并行维度说明dp_degree数据并行data parallel每个进程持有完整模型副本、切分数据梯度 AllReduce 同步pp_degree流水并行pipeline parallel模型按层切分到不同设备前后向按 micro-batch 流水执行sharding_degree参数分片sharding优化器状态与参数分片代表 ZeRO 式参数切分维度mp_degree张量并行tensor/model parallel单个算子内部的矩阵切分Transformer 中常为列/行并行sep_degree序列并行sequence parallel序列维度的切分对应上下文/序列并行能力五个维度的度数乘积必须等于world_size即dp × pp × sharding × mp × sep world_size否则np.arange(...).reshape(shape)会直接抛出 reshape 错误。构造函数的第一个约束是校验orderassert set(order) {dp, pp, sharding, mp, sep}, fIllegal order : {order}即order必须恰好包含这五个关键字仅允许排列顺序不同。order 的作用决定进程如何排列成多维数组order决定了全局 rank 到五维坐标的映射方式。构造时先按order收集各维度度数组成shape然后用np.arange(0, dp*pp*sharding*mp*sep).reshape(shape)将 0 到world_size-1的连续整数填充成一个五维数组见 topo.py。由于 NumPy 默认按 C 顺序行优先填充排在order越靠后的维度其相邻进程的全局 rank 越接近。例如order[dp, pp, sharding, mp, sep]默认值且各维度度数为 (2, 2, 1, 2, 1) 时五维数组形状为 (2, 2, 1, 2, 1)rank 0 的坐标为 (0, 0, 0, 0, 0)rank 1 落在mp轴最后一个度数为 2 的维度因此默认顺序下张量并行组的成员是全局 rank 相邻的进程这与常见的 TP 优先使用同机 GPU 的部署习惯一致。PaddleNLP 的自动并行脚本也把order的选择暴露成了命令行参数--hybrid_parallel_topo_order支持pp_first与sharding_first两种策略pp_first默认order [pp, dp, sharding, mp, sep]sharding_firstorder [dp, sharding, pp, mp, sep]。该映射在 llm/auto_parallel/llama/run_pretrain_auto.py、llm/auto_parallel/gpt-3/run_pretrain_auto.py、llm/auto_parallel/deepseek-v3/run_pretrain_auto.py 中实现一致在 XPU 上的 Llama2-13B 训练脚本中通过--hybrid_parallel_topo_order sharding_first显式指定见 llm/auto_parallel/llama/run_llama2_13b_xpu.sh。GroupInfo通信组的统一描述结构Topology中用namedtuple定义了一种极简的通信组描述结构topo.pyGroupInfo namedtuple(GroupInfo, [size, rank, world])三个字段的含义为size该通信组内的进程数量即对应维度的度数rank当前进程在该通信组内的局部编号0 到 size-1world该通信组内全部全局 rank 的列表直接可用于paddle.distributed.new_group(world)之类的建组操作。Topology的全局信息同样以GroupInfo形式保存在self.world属性中topo.pyself.world GroupInfo(sizeworld_size, rankdevice_rank, worldlist(range(0, world_size)))核心推导逻辑rank 定位与通信组切片构造的核心步骤可以拆成四步对应 topo.py构造五维坐标数组arr np.arange(0, ...).reshape(shape)其中shape按order排列各维度度数定位当前进程坐标ranks [rank[0] for rank in np.where(arr device_rank)]np.where返回device_rank在每个轴上的下标构成五元组坐标逐轴切片得到通信组对第i个轴把该轴替换为slice(None)全取其余轴固定为当前坐标即indexes tuple(ranks[:i] [slice(None)] ranks[(i 1):]) worlds.append(arr[indexes])固定其余四轴、只放开第i轴得到的正是一条沿该轴方向的「直线」也就是该维度对应的通信组成员 4.按 key 落盘根据self.order[i]的值将结果分别写入dp_info、pp_info、sharding_info、mp_info、sep_info五个属性topo.py。is_last流水并行末级判断构造完成后Topology额外暴露了一个训练调度高频使用的布尔属性topo.pyself.is_last self.pp_info.rank self.pp_info.size - 1即「当前进程是否为流水并行最后一组rank 最大的那级」。在流水并行训练中最后一组进程承担 loss 计算与权重同步的收尾工作is_last可以直接作为if topo.is_last:的判断条件避免再手动比较pp_rank pp_size - 1。data_info数据并行 × Sharding 的联合数据组在实际训练中数据集加载与采样只关心「数据并行维 Sharding 维」组成的联合组数据并行进程消费不同 batchSharding 维度内共享同一份 batch。Topology据此派生出data_infotopo.pydata_arr np.arange(0, dp_degree * sharding_degree).reshape([dp_degree, sharding_degree]) for i, key in enumerate(self.order): if key ! dp and key ! sharding: data_arr np.expand_dims(data_arr, axisi).repeat(degree_map[key], axisi) self.data_info GroupInfo( sizeint(self.dp_info.size * self.sharding_info.size), rankint(self.dp_info.rank * self.sharding_info.size self.sharding_info.rank), worlddata_arr.reshape(-1).tolist(), )其含义是data_info.size dp_degree × sharding_degree即参与同一份数据消费的进程总数data_info.rank按「dp 优先、sharding 次之」的方式编码为dp_rank * sharding_size sharding_rank。代码还用self.data_info.world[device_rank] self.data_info.rank做了自校验一旦推导出错会抛出Data rank calculate error!。基于data_info又派生出data_inner_timestopo.pyself.data_inner_times self.world.size // self.data_info.size它表示整个集群里存在多少个互不重叠的数据组即world_size / (dp × sharding)可用于推导全局 batch size 与单卡 micro-batch 的关系global_batch micro_batch × data_inner_times × ...。repr一次打印全部拓扑信息Topology重写了__repr__topo.py打印格式如下便于在日志中一次性核对所有通信组dp_info: GroupInfo(size..., rank..., world[...]), pp_info: GroupInfo(size..., rank..., world[...]), sharding_info: GroupInfo(size..., rank..., world[...]), mp_info: GroupInfo(size..., rank..., world[...]), sep_info: GroupInfo(size..., rank..., world[...]), data_info: GroupInfo(size..., rank..., world[...]), order: [dp, pp, sharding, mp, sep]实战一在 Trainer 中借助 Topology 做分布式种子管理Topology在 PaddleNLP 中最核心的消费方是 paddlenlp/trainer/trainer_utils.py 中的_get_distributed_seeds(seed, topo)函数。当topo非空且world_size 1时它从拓扑中读取各维度信息dp_rank, dp_size topo.dp_info.rank, topo.dp_info.size pp_rank, pp_size topo.pp_info.rank, topo.pp_info.size mp_rank, mp_size topo.mp_info.rank, topo.mp_info.size sep_rank, sep_size topo.sep_info.rank, topo.sep_info.size sharding_rank topo.sharding_info.rank随后按如下规则计算三类种子源码注释已给出设计意图参数初始化 seeddp、未分片的 mp 参数、sharding 使用相同种子其余组不同保证不同副本间参数一致可复现计算 seed如 dropoutglobal seed 只在 mp 组内相同local seed 则各组互不相同random_seedseed 100 * pp_rank让不同流水级获得不同的随机序列。最终返回三元组(global_seed, local_seed, random_seed)并在set_seed中通过paddle.seed(global_seed)、random.seed(random_seed)以及get_rng_state_tracker()的add(global_seed, ...)/add(local_seed, ...)注册 RNG 状态paddlenlp/trainer/trainer_utils.py。也就是说只要在 Trainer 初始化前正确构造Topology整个混合并行训练中的参数初始化与 dropout 随机性就能在 dp/sharding 维度保持一致、在 pp/mp 维度相互独立这直接决定了多卡训练结果是否可复现。实战二自动并行训练脚本中的 Topology 使用在自动并行--enable_auto_parallel 1模式下PaddleNLP 的预训练脚本用Topology统一推导所有并行组并完成种子初始化以 llm/auto_parallel/llama/run_pretrain_auto.py 的init_seed为例def init_seed(seed: int 1234, argsNone): if args is None: random.seed(seed) np.random.seed(seed) paddle.seed(seed) else: assert not args.use_hybrid_parallel and args.enable_auto_parallel if dist.get_world_size() 1: if args.hybrid_parallel_topo_order is None or args.hybrid_parallel_topo_order pp_first: order [pp, dp, sharding, mp, sep] elif args.hybrid_parallel_topo_order sharding_first: order [dp, sharding, pp, mp, sep] if args.context_parallel_degree is not None and args.context_parallel_degree 1: sep_degree args.context_parallel_degree elif args.sep_parallel_degree is not None and args.sep_parallel_degree 1: sep_degree args.sep_parallel_degree else: sep_degree 1 topo Topology( dist.get_rank(), dist.get_world_size(), dp_degreeargs.dataset_world_size, pp_degreeargs.pipeline_parallel_degree, mp_degreeargs.tensor_parallel_degree, sep_degreesep_degree, sharding_degree1, # auto_parallel 的 sharding 与 dp/mp/pp 非正交 orderorder, ) global_seed, local_seed, random_seed _get_distributed_seeds(args.seed, topo) paddle.seed(local_seed) random.seed(random_seed) np.random.seed(random_seed) else: random.seed(args.seed) np.random.seed(args.seed) paddle.seed(args.seed)关键点在于dp_degree取--dataset_world_sizepp_degree取--pipeline_parallel_degreemp_degree取--tensor_parallel_degreesep_degree优先取--context_parallel_degree其次取--sep_parallel_degree两者都未开启时回落为 1自动并行场景下sharding_degree固定为 1源码注释明确指出 auto parallel 的 sharding 与 dp/mp/pp 并非正交由框架内部统一编排order由--hybrid_parallel_topo_order决定默认pp_first。llm/auto_parallel/gpt-3/run_pretrain_auto.py 与 llm/auto_parallel/deepseek-v3/run_pretrain_auto.py 中的用法完全一致仅dp_degree取值略有差异GPT-3 脚本使用max(args.data_parallel_degree, args.sharding_parallel_degree)可作为对照阅读。从配置到运行一个完整的参数对照示例在非自动并行混合并行场景下各并行度数在配置文件中以 JSON 形式给出llm/config/yuan/README.md 提供了一个直观示例{ mp_degree: 8, pp_degree: 1, sharding_degree: 1 }配合fleet.init(is_collectiveTrue, strategystrategy)与hcg fleet.get_hybrid_communicate_group()使用。可见两种路线fleet的CommunicateTopology与本模块的Topology在概念上一一对应区别仅在于前者由框架创建通信组后者是纯计算、可独立构造与验证。小结paddlenlp.ops.distributed.utils.topo.Topology是 PaddleNLP 分布式体系里一个轻量而关键的组件用五维 NumPy 数组统一刻画 dp/pp/sharding/mp/sep 五个并行维度order控制全局 rank 到多维坐标的映射以GroupInfo(size, rank, world)的统一定义输出每个通信组world列表可直接用于建组额外派生出数据组data_info、流水末级标记is_last与data_inner_times覆盖了训练循环中数据加载、loss 汇聚等高频需求在 Trainer 的_get_distributed_seeds与自动并行脚本的init_seed中被实际消费直接决定了混合并行训练的随机种子布局与可复现性。如果你正在阅读或调试 PaddleNLP 的分布式训练代码遇到topo.dp_info.rank、topo.is_last、hybrid_parallel_topo_order这类符号它们的最终出处都可以追溯到这一个不到百行的纯 Python 文件建议直接阅读 paddlenlp/ops/distributed/utils/topo.py 全文并结合本文的推导过程对照理解。赞分享人工智能大模型预训练微调LoRARLHF强化学习分布式训练【免费下载链接】PaddleNLPEasy-to-use and powerful LLM and SLM library with awesome model zoo.项目地址https://gitcode.com/gh_mirrors/pa/PaddleNLP点击查看免费下载相关推荐PaddleNLP 分布式工具集 paddlenlp.ops.distributed.utils 深度解析RNG 状态追踪与并行拓扑建模PaddleNLP 分布式工具集 paddlenlp.ops.distributed.utils 深度解析RNG 状态追踪与并行拓扑建模 导读 paddlen人工智能大模型预训练微调LoRARLHF强化学习分布式训练模型推理服务推理引擎模型量化模型压缩本地部署NLPDeepSpeed MoE 训练完全指南稀疏专家混合层 API、并行拓扑组合与 ZeRO-Offload 实战DeepSpeed MoE 训练完全指南稀疏专家混合层 API、并行拓扑组合与 ZeRO Offload 实战 导读本文是 DeepSpeed 官方《Mix人工智能大模型深度学习分布式训练预训练强化学习模型优化PyTorch tutorials分布式训练DDP与FSDP2并行计算架构解析PyTorch tutorials分布式训练DDP与FSDP2并行计算架构解析 在深度学习模型训练中随着模型规模和数据量的增长单GPU已难以满足需求。分布示例工程创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考