ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

CoreNet 多节点分布式训练实战:从 DDP/FSDP 集群配置到 Slurm 作业脚本

CoreNet 多节点分布式训练实战:从 DDP/FSDP 集群配置到 Slurm 作业脚本 深度学习计算机视觉NLP多模态模型训练大模型【免费下载链接】corenetCoreNet: A library for training deep neural networks项目地址https://gitcode.com/GitHub_Trending/co/corenet点击查看免费下载CoreNet 原生支持基于 PyTorch DDP 与 FSDP 的多节点多卡分布式训练。本篇指南以 tutorials/guide_slurm_and_multi_node_training.md 为骨架结合仓库源码逐项拆解corenet-train的分布式启动链路、--ddp.*参数的真实语义并给出可直接套用的手动启动脚本与 Slurm 提交模板帮助你在一台或多台 GPU 主机上正确编排 rank、world size 与初始化地址跑通大规模训练任务。前置知识corenet-train 入口与配置文件本文假设你已经熟悉corenet-train的基本用法配置文件、--common.*参数等。如果还比较陌生建议先阅读 从零开始训练新模型的教程。corenet-train是 CoreNet 提供的训练命令入口。从源码结构看它由 corenet/cli/entrypoints.py 中的 entrypoint 映射注册corenet-train对应corenet.cli.main_train模块的main_worker函数并最终由setup.py生成对应的 console script。也就是说corenet-train与corenet train子命令在行为上是等价的。训练参数由 corenet/options/opts.py 中的get_training_arguments()统一组装其中与分布式训练直接相关的是arguments_ddp()见 opts.py注册的--ddp.*参数组。因此无论手动启动还是通过 Slurm 启动最终都会走到同一条参数解析与初始化路径。CoreNet 的分布式训练能力DDP 与 FSDPCoreNet 支持两种主流分布式训练方案DDPDistributedDataParallel默认方案。训练流水线在检测到 GPU 数量 ≥ 1 时自动将模型包装为torch.nn.parallel.DistributedDataParallel见 default_train_eval.py。FSDPFullyShardedDataParallel面向超大模型把模型参数、梯度与优化器状态分片到各设备。需要在配置中指定--train-eval-pipeline.name fsdp_train_eval_pipeline对应 fsdp_train_eval.py 中注册的FSDPTrainEvalPipeline。两种方案共用同一套多节点编排方式每个节点上以 GPU 为粒度计算 rank因此下面的启动命令同样适用于多节点多卡multi-node-multi-gpu与多节点单卡multi-node-single-gpu集群。手动多节点启动环境变量与启动命令详解以一个4 节点 × 8 GPU的集群为例官方推荐的手动启动方式如下原文命令逐行注释已补全# Assuming 4-node x 8-GPU Cluster: export CFG_FILEpath/to/config.yaml # 改为你的配置文件路径 export GPU_PER_NODE8 # 每个节点上可用的 GPU 数量 export NUM_NODES4 # 集群中的节点主机/机器数量 export NODE_RANK0 # 取值 [0, $NUM_NODES-1]每个节点必须使用唯一 rank export MAIN_IP_PORTtcp://IP_OF_RANK0:PORT # 将 IP_OF_RANK0 改为 rank 0 节点的主机名须能被其他节点访问PORT 改为空闲端口 export WORLD_SIZE$((NUM_NODES * GPU_PER_NODE)) export GPU_RANK$((NODE_RANK * GPU_PER_NODE)) corenet-train --common.config-file $CFG_FILE --common.results-loc results --ddp.rank $GPU_RANK --ddp.world-size $WORLD_SIZE --ddp.dist-url $MAIN_IP_PORT --ddp.backend nccl环境变量的含义与计算方法变量含义说明CFG_FILE配置文件路径通过--common.config-file传入GPU_PER_NODE每节点 GPU 数决定每个节点负责的 rank 数量NUM_NODES节点总数4 节点集群中取 4NODE_RANK节点序号每个节点取 [0, NUM_NODES-1] 中的唯一值MAIN_IP_PORT进程组初始化地址形如tcp://rank0主机:端口PyTorch 的init_methodWORLD_SIZE全局进程总数NUM_NODES × GPU_PER_NODE即 4×832GPU_RANK该节点首个进程的全局 rankNODE_RANK × GPU_PER_NODE即节点 0→0、节点 1→8、节点 2→16、节点 3→24关键注意点rank 是 GPU 索引而非节点索引正如原文档的 NOTE 所强调的从上面WORLD_SIZE与GPU_RANK的计算方式可以看出--ddp.rank与--ddp.world-size期望的是GPU 索引全局 rank而不是节点索引。但corenet-train仍然需要在每个节点上各执行一次。以 4 节点 × 8 GPU 为例四个节点上的参数应分别为节点 0NODE_RANK0→GPU_RANK0节点 1NODE_RANK1→GPU_RANK8节点 2NODE_RANK2→GPU_RANK16节点 3NODE_RANK3→GPU_RANK24WORLD_SIZE恒为 32。这样PyTorch 进程组中 rank 031 与 32 块 GPU 一一对应。深入源码--ddp.* 参数的真实语义与启动链路--ddp.* 参数定义--ddp.*参数组在 corenet/options/opts.py 中定义完整列表如下参数类型默认值说明--ddp.rankint0分布式训练的全局 rank节点 rank--ddp.world-sizeint-1DDP 世界大小默认 -1 表示使用所有 GPU--ddp.dist-urlstrNoneDDP 初始化 URLtcp://host:port--ddp.dist-portint30786仅在未指定--ddp.dist-url时使用的端口默认注释中同时出现 30786/30768以实际代码为准--ddp.device-idintNone设备 ID--ddp.backendstrncclDDP 通信后端默认 nccl--ddp.find-unused-paramsflagFalse让 DDP 查找未使用参数便于调试此外还有--ddp.use-deprecated-data-parallel旧版 DataParallel仅供调试后续将被废弃以及内部使用的ddp.use_distributed由 launcher 根据 GPU 数量自动设置见 default_train_eval.py。从命令行到进程组的调用链一次多节点训练的启动链路可以拆解为入口corenet-train调用 corenet/cli/main_train.py 中的main_worker解析出全部参数并通过TRAIN_EVAL_PIPELINE_REGISTRY按--train-eval-pipeline.name默认default构建训练流水线对象然后调用launcher。launcher 编排DefaultTrainEvalPipeline.launcher见 default_train_eval.py先完成设备设置、创建结果目录common.results-loccommon.run-label再根据 GPU 数量决定是否启用分布式启用时通过torch.multiprocessing.spawn为每张 GPU 派生一个子进程nprocsnum_gpus。子进程初始化 rank每个子进程进入_launcher_distributed_spawn_fn见 default_train_eval.py把--ddp.rank此时为空重置为ddp.start_rank device_id即把节点的GPU_RANK分配到该节点内的各张 GPU 上。初始化进程组调用 corenet/utils/ddp_utils.py 中的distributed_init()。若未指定--ddp.dist-url会自动生成tcp://本机主机名:端口随后用dist.init_process_group(backend..., init_methodddp_url, world_size..., rank...)建立进程组并执行一次 dummy all-reduce 来初始化 NCCL 通信器。这一步解释了为什么手动启动脚本中--ddp.rank必须传全局 GPU ranktorch.multiprocessing.spawn只在单个节点内分配设备序号跨节点的全局 rank 全靠你通过--ddp.rank预先给定。这也是文档要求每个节点各运行一次、且 NODE_RANK 唯一的根本原因。在 Slurm 集群上运行模板脚本逐行解析以下为官方提供的 Slurm 提交模板原文脚本逐行注释已补全。请注意官方明确声明 CoreNet 尚未在 Slurm 上做过完整测试使用前需要针对你的集群环境验证。#!/bin/bash #SBATCH --job-nameyour-job-name #SBATCH --nodes4 # 改为集群中的节点数主机/机器数量 #SBATCH --ntasks-per-node1 # 即使多 GPU 节点也无需改动这一行 #SBATCH --gpus-per-nodegpu:8 # 改为每个节点可用的 GPU 数量 export CFG_FILEpath/to/config.yaml # 改为你的配置文件路径 export GPU_PER_NODE$SLURM_GPUS_PER_NODE export NUM_NODES$SLURM_NNODES export NODE_RANK$SLURM_PROCID # Inspired by https://discuss.pytorch.org/t/distributed-training-on-slurm-cluster/150417/7 export MAIN_PORT$(expr 10000 $(echo -n $SLURM_JOBID | tail -c 4)) export MAIN_IP$(scontrol show hostnames $SLURM_JOB_NODELIST | head -n 1) export MAIN_IP_PORTtcp://$MAIN_IP:$MAIN_PORT export WORLD_SIZE$((NUM_NODES * GPU_PER_NODE)) export GPU_RANK$((NODE_RANK * GPU_PER_NODE)) corenet-train --common.config-file $CFG_FILE --common.results-loc results --ddp.rank $GPU_RANK --ddp.world-size $WORLD_SIZE --ddp.dist-url $MAIN_IP_PORT --ddp.backend ncclSlurm 模板设计要点--ntasks-per-node1每个节点只启动一个corenet-train进程。多 GPU 场景下该进程内部会通过torch.multiprocessing.spawn再派生出与 GPU 数量相等的子进程因此不需要为每张 GPU 单独建 task。$SLURM_GPUS_PER_NODESlurm 自动注入的每节点 GPU 数直接作为GPU_PER_NODE。$SLURM_NNODES本次作业分配的节点数即NUM_NODES。$SLURM_PROCIDSlurm 为每个 task 分配的全局进程 ID在--ntasks-per-node1下恰好等于节点序号0、1、2、3因此可以直接作为NODE_RANK。MAIN_PORT 生成技巧取SLURM_JOBID末尾 4 位加上 10000得到一个随作业 ID 变化的端口降低多作业并发时端口冲突的概率。MAIN_IP通过scontrol show hostnames $SLURM_JOB_NODELIST | head -n 1取出作业节点列表中的第一个节点即 rank 0 节点作为MAIN_IP。最终corenet-train在每个节点上以各自唯一的GPU_RANK0/8/16/24启动并通过统一的tcp://$MAIN_IP:$MAIN_PORT汇聚到 rank 0 节点完成进程组初始化。补充FSDP 多节点训练的注意事项如果模型规模较大需要在多节点上使用 FSDP应在配置文件中设置--train-eval-pipeline.name为fsdp_train_eval_pipeline仍需按上述方式正确设置--ddp.rank、--ddp.world-size、--ddp.dist-url因为 FSDP 依赖 DDP 的进程组见 fsdp_train_eval.py其中明确断言ddp.use_distributed必须为真。从 fsdp_trainer.py 的构造函数可以确认使用 FSDP 时有两个限制不支持梯度累积common.accum_freq 1会报错不支持 EMAema.enable会报错。此外FSDP 的混合精度由 FSDP 内部机制处理common.mixed-precisionautocast GradScaler在 FSDP 流水线中不适用fsdp_train_eval.py 中gradient_scaler属性直接抛出NotImplementedError。常见问题与调试建议端口不可达MAIN_IP_PORT中的端口必须对集群内所有节点开放。排查时可在 rank 0 节点上执行nc -l PORT或检查防火墙/安全组规则。rank 计算错误最常见的错误是把节点索引直接传给--ddp.rank。请始终使用GPU_RANK NODE_RANK × GPU_PER_NODE。每个节点只启动一次不要在一个节点上为每张 GPU 各运行一遍corenet-train正确做法是每节点运行一次由内部torch.multiprocessing.spawn按 GPU 数量派生子进程。验证进程组是否建立训练日志中会打印distributed init (rank X): tcp://...可据此确认各 rank 是否正确加入进程组见 ddp_utils.py。调试用参数遇到梯度同步异常时可尝试--ddp.find-unused-params见 opts.py辅助定位切勿使用--ddp.use-deprecated-data-parallel进行正式训练它仅供调试且即将被移除。Slurm 兼容性如前所述官方未在 Slurm 上完整测试该模板正式大规模作业前建议先用小节点数、小配置做冒烟测试。总结CoreNet 的多节点训练本质上是一个把节点/GPU 拓扑翻译成 PyTorch 进程组参数的过程通过WORLD_SIZE NUM_NODES × GPU_PER_NODE与GPU_RANK NODE_RANK × GPU_PER_NODE两个公式把每个节点映射到全局 rank 区间再借助tcp://rank0:port的初始化地址让所有进程汇合。理解了 entrypoints.py、opts.py、ddp_utils.py 与 default_train_eval.py 中的启动链路后无论是手动export启动还是通过 Slurm 脚本提交都能准确控制集群中的每一个训练进程为后续 DDP/FSDP 的大规模训练打下可靠基础。赞分享深度学习计算机视觉NLP多模态模型训练大模型【免费下载链接】corenetCoreNet: A library for training deep neural networks项目地址https://gitcode.com/GitHub_Trending/co/corenet点击查看免费下载相关推荐LinkedIn AWS 技能评估题库法语版深度解析117 道真题背后的 EC2、RDS、S3、VPC 与云架构核心知识点LinkedIn AWS 技能评估题库法语版深度解析117 道真题背后的 EC2、RDS、S3、VPC 与云架构核心知识点 本篇技术指南以开源仓库 lin文档教程知识库教育如何使用Navajo构建安全密码系统iOS开发者的完整指南如何使用Navajo构建安全密码系统iOS开发者的完整指南 在移动应用开发中用户数据安全是至关重要的环节而密码作为第一道防线其强度直接关系到用户账户的安应用安全FSDP-QLoRA分布式训练SLURM集群配置指南FSDP QLoRA分布式训练SLURM集群配置指南 FSDP QLoRA是GitHub推荐项目精选中的高效分布式训练方案专为大规模语言模型训练设计结合了人工智能大模型微调LoRA分布式训练模型量化上一篇Nintendo Switch破解终极指南如何安全稳定地使用大气层系统下一篇深入解析 Dopamine 的 create_gym_environmentGym 环境接入与预处理指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表