【教程】PyTorch多机多卡分布式训练的参数说明 | 附通用启动脚本

转载请注明出处:小锋学长生活大爆炸[xfxuezhagn.cn]

如果本文帮助到了你,欢迎[点赞、收藏、关注]哦~

目录

torchrun

一、什么是 torchrun

二、torchrun 的核心参数讲解

三、torchrun 会自动设置的环境变量

四、torchrun 启动过程举例

机器 A(node_rank=0)上运行

机器 B(node_rank=1)上运行

五、小结表格

PyTorch

一、背景回顾

二、init_process_group

三、脚本中通常的典型写法

通用启动脚本


torchrun 与 torch.multiprocessing.spawn 的对比可以看这篇:

【知识】torchrun 与 torch.multiprocessing.spawn 的对比

torchrun

一、什么是 torchrun

torchrun 是 PyTorch 官方推荐的分布式训练启动器,它的作用是:

  • 启动 多进程分布式训练(支持多 GPU,多节点)

  • 自动设置每个进程的环境变量

  • 协调节点之间建立通信

二、torchrun 的核心参数讲解

torchrun \--nnodes=2 \--nproc_per_node=2 \--node_rank=0 \--master_addr=192.168.5.228 \--master_port=29400 \xxx.py

🔹 1. --nnodes(Number of Nodes)

  • 表示参与训练的总机器数

  • 你有几台服务器,就写几。

  • 在分布式训练中,一个 node 就是一台物理或虚拟的主机。

  • node的编号从0开始。

✅ 例子:你用 2 台机器 → --nnodes=2


🔹 2. --nproc_per_node(Processes Per Node)

  • 表示每台机器上要启动几个训练进程。

  • 一个进程对应一个 GPU,因通常设置为你机器上要用到的GPU数。

  • 因此,整个分布式环境下,总训练进程数 = nnodes * nproc_per_node

✅ 例子:每台机器用了 2 张 GPU → --nproc_per_node=2


🔹 3. --node_rank

  • 表示当前机器是第几台机器

  • 从 0 开始编号,必须每台机器都不同!

✅ 例子:

机器 IPnode_rank
192.168.5.2280
192.168.5.2291

🔹 4. --master_addr--master_port

  • 指定主节点的 IP 和端口,用于 rendezvous(进程对齐)和通信初始化。

  • 所有机器必须填写相同的值!

✅ 建议:

  • master_addr 就是你指定为主节点的那台机器的 IP

  • master_port 选一个未被占用的端口,比如 29400

三、torchrun 会自动设置的环境变量

当用 torchrun 启动后,它会自动给每个进程设置这些环境变量

环境变量含义
RANK当前进程在全局中的编号(0 ~ world_size - 1)
LOCAL_RANK当前进程在本机中的编号(0 ~ nproc_per_node - 1)
WORLD_SIZE总进程数 = nnodes * nproc_per_node

你可以在训练脚本里用 os.environ["RANK"] 来读取这些信息:

import os
rank = int(os.environ["RANK"])
local_rank = int(os.environ["LOCAL_RANK"])
world_size = int(os.environ["WORLD_SIZE"])

示例分配图:

四、torchrun 启动过程举例

假设:

  • 有 2 台机器

  • 每台机器有 2 个 GPU

  • 总共会启动 4 个进程

机器 A(node_rank=0)上运行

torchrun \--nnodes=2 \--nproc_per_node=2 \--node_rank=0 \--master_addr=192.168.5.228 \--master_port=29400 \xxx.py

机器 B(node_rank=1)上运行

torchrun \--nnodes=2 \--nproc_per_node=2 \--node_rank=1 \--master_addr=192.168.5.228 \--master_port=29400 \xxx.py

torchrun 给每个进程编号的顺序(分配 RANK / LOCAL_RANK)

torchrun 按照每台机器上 node_rank 的顺序,并在每台机器上依次启动 LOCAL_RANK=0, 1, ..., n-1,最后合成 RANK。

RANK = node_rank × nproc_per_node + local_rank

Step 1:按 node_rank 升序处理(node 0 → node 1)

Step 2:每个 node 内部从 local_rank=0 开始递增


本质上:torchrun 是主从结构调度的

  • 所有 node 启动后,都会和 master_addr 通信。

  • master 会统一收集所有 node 的状态。

  • 每个 node 根据你给的 node_rank 自行派生 local_rank=0~n-1

  • 所有节点通过 RANK = node_rank * nproc_per_node + local_rank 得到自己的全局编号。

这个机制是 可预测、可控、可复现 的。


📦 node_rank=0 (机器 1)
    ├── local_rank=0 → RANK=0
    └── local_rank=1 → RANK=1

📦 node_rank=1 (机器 2)
    ├── local_rank=0 → RANK=2
    └── local_rank=1 → RANK=3

最终分配:

Node RankLocal RankGlobal Rank (RANK)使用 GPU
0000
0111
1020
1131

五、小结表格

参数作用设置方式
--nnodes总节点数你写在命令里
--nproc_per_node每台节点的进程数(= GPU 数)你写在命令里
--node_rank当前机器编号(0开始)每台机器唯一
--master_addr主节点 IP(所有节点需一致)你设置
--master_port主节点端口(所有节点需一致)你设置
RANK当前进程在所有进程中的编号torchrun 自动设置
LOCAL_RANK当前进程在本节点上的编号torchrun 自动设置
WORLD_SIZE总进程数 = nnodes * nproc_per_node自动设置

PyTorch

PyTorch 的分布式通信是如何通过 init_process_grouptorchrun 生成的环境变量配合起来工作的。

一、背景回顾

你已经用 torchrun 启动了多个训练进程,并且 torchrun 为每个进程自动设置了这些环境变量:

变量名含义
RANK当前进程的全局编号(从 0 开始)
LOCAL_RANK本机上的编号(一般等于 GPU ID)
WORLD_SIZE总进程数
MASTER_ADDR主节点的 IP
MASTER_PORT主节点用于通信的端口

那么 这些变量是如何参与进程通信初始化的? 这就涉及到 PyTorch 的核心函数:


二、init_process_group

torch.distributed.init_process_group 是 PyTorch 初始化分布式通信的入口:

torch.distributed.init_process_group(backend="nccl",  # 或者 "gloo"、"mpi"init_method="env://",  # 通过环境变量读取设置
)

关键点:

  • backend="nccl":推荐用于 GPU 分布式通信(高性能)

  • init_method="env://":表示通过环境变量来初始化


你不需要自己设置 RANK / WORLD_SIZE / MASTER_ADDR,只要写:

import torch.distributed as distdist.init_process_group(backend="nccl", init_method="env://")

PyTorch 会自动去环境中读这些变量:

  • RANK → 当前进程编号

  • WORLD_SIZE → 总进程数

  • MASTER_ADDRMASTER_PORT → 主节点 IP 和端口

然后就能正确初始化所有通信进程。

三、脚本中通常的典型写法

import os
import torch# 初始化 PyTorch 分布式通信环境
torch.distributed.init_process_group(backend="nccl", init_method="env://")# 获取全局/本地 rank、world size
rank = int(os.environ.get("RANK", -1))
local_rank = int(os.environ.get("LOCAL_RANK", -1))
world_size = int(os.environ.get("WORLD_SIZE", -1))# 设置 GPU 显卡绑定
torch.cuda.set_device(local_rank)
device = torch.device("cuda")# 打印绑定信息
print(f"[RANK {rank} | LOCAL_RANK {local_rank}] Using CUDA device {torch.cuda.current_device()}: {torch.cuda.get_device_name(torch.cuda.current_device())} | World size: {world_size}")

这段代码在所有进程中都一样写,但每个进程启动时带的环境变量不同,所以最终 ranklocal_rankworld_size 就自然不同了。

通用启动脚本

#!/bin/bash# 设置基本参数
MASTER_ADDR=192.168.5.228           # 主机IP
MASTER_PORT=29400                   # 主机端口
NNODES=2                            # 参与训练的总机器数
NPROC_PER_NODE=2                    # 每台机器上的进程数# 所有网卡的IP地址,用于筛选
ALL_LOCAL_IPS=$(hostname -I)
# 根据本机 IP 配置通信接口
if [[ "$ALL_LOCAL_IPS" == *"192.168.5.228"* ]]; thenNODE_RANK=0                       # 表示当前机器是第0台机器IFNAME=ens1f1np1  mytorchrun=~/anaconda3/envs/dglv2/bin/torchrun
elif [[ "$ALL_LOCAL_IPS" == *"192.168.5.229"* ]]; thenNODE_RANK=1                       # 表示当前机器是第1台机器IFNAME=ens2f1np1mytorchrun=/opt/software/anaconda3/envs/dglv2/bin/torchrun
elseexit 1
fi# 设置 RDMA 接口
export NCCL_IB_DISABLE=0            # 是否禁用InfiniBand
export NCCL_IB_HCA=mlx5_1           # 使用哪个RDMA接口进行通信
export NCCL_SOCKET_IFNAME=$IFNAME   # 使用哪个网卡进行通信
export NCCL_DEBUG=INFO              # 可选:调试用
export GLOO_IB_DISABLE=0            # 是否禁用InfiniBand
export GLOO_SOCKET_IFNAME=$IFNAME   # 使用哪个网卡进行通信
export PYTHONUNBUFFERED=1           # 实时输出日志# 启动分布式任务
$mytorchrun \--nnodes=$NNODES \--nproc_per_node=$NPROC_PER_NODE \--node_rank=$NODE_RANK \--master_addr=$MASTER_ADDR \--master_port=$MASTER_PORT \cluster.py## 如果想获取准确报错位置,可以加以下内容,这样可以同步所有 CUDA 操作,错误不会“延迟触发”,你会看到确切是哪一行代码出了问题:
## CUDA_LAUNCH_BLOCKING=1 torchrun ...

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/76906.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

计算机视觉——基于 Yolov8 目标检测与 OpenCV 光流实现目标追踪

1. 概述 目标检测(Object Detection)和目标追踪(Object Tracking)是计算机视觉中的两个关键技术,它们在多种实际应用场景中发挥着重要作用。 目标检测指的是在静态图像或视频帧中识别出特定类别的目标对象&#xff0…

MySQL——流程控制

一、IF条件语句 语法 IF condition THENstatements; ELSEIF condition THENstatements; ELSEstatements; END IF; 判断成绩等级 # 判断成绩等级 # 输入学生的编号,取出学生的第一门课,然后判断当前的课程的等级 drop procedure if exists p2; delimiter $$ crea…

C# + Python混合开发实战:优势互补构建高效应用

文章目录 前言🥏一、典型应用场景1. 桌面应用智能化2. 服务端性能优化3. 自动化运维工具 二、四大技术实现方案方案1:进程调用(推荐指数:★★★★☆)方案2:嵌入Python解释器(推荐指数&#xff1…

MLflow 入门

官方主页 MLflow | MLflow官方文档 MLflow: A Tool for Managing the Machine Learning Lifecycle | MLflow 0. 简介 MLflow 是一个开源平台,专门为了帮助机器学习的从业者和团队处理机器学习过程中的复杂性而设计。MLflow 关注机器学习项目的完整生命周期&#x…

【蓝桥杯选拔赛真题101】Scratch吐丝的蜘蛛 第十五届蓝桥杯scratch图形化编程 少儿编程创意编程选拔赛真题解析

目录 scratch吐丝的蜘蛛 一、题目要求 1、准备工作 2、功能实现 二、案例分析 1、角色分析 2、背景分析 3、前期准备 三、解题思路 四、程序编写 五、考点分析 六、推荐资料 1、scratch资料 2、python资料 3、C++资料 scratch吐丝的蜘蛛 第十五届青少年蓝桥杯s…

智谱最新模型GLM4是如何练成的

写在前面 这篇博客将基于《ChatGLM: A Family of Large Language Models from GLM-130B to GLM-4 All Tools》,深入剖析 GLM-4 系列在**模型架构设计、预训练、后训练(对齐)、以及关键技术创新(如长上下文处理、Agent 能力构建)**等环节的实现逻辑与设计考量,带你全面了…

第二届电气技术与自动化工程国际学术会议 (ETAE 2025)

重要信息 2025年4月25-27日 中国广州 官网: http://www.icetae.com/ 部分 征稿主题 Track 1:电气工程 输配电、电磁兼容、高电压和绝缘技术、电气工程、电气测量、电力电子及其应用、机电一体化、电路与系统、电能质量和电磁兼容性、电力系统及其自…

设备调试--反思与总结

最近回顾项目, 发现:在调试过程中最耽误时间的可能不是技术难度,而是惯性思维; 例如: 我写can通信滤波器的时候,可能是不过滤的;是接收所有的id报文,然后用业务逻辑过滤&#xff08…

C++项目:高并发内存池_下

目录 8. thread cache回收内存 9. central cache回收内存 10. page cache回收内存 11. 大于256KB的内存申请和释放 11.1 申请 11.2 释放 12. 使用定长内存池脱离使用new 13. 释放对象时优化成不传对象大小 14. 多线程环境下对比malloc测试 15. 调试和复杂问题的调试技…

深度学习入门:神经网络的学习

目录 1 从数据中学习1.1 数据驱动1.2 训练数据和测试数据 2损失函数2.1 均方误差2.2 交叉熵误差2.3 mini-batch学习2.4 mini-batch版交叉熵误差的实现2.5 为何要设定损失函数 3 数值微分3.1 数值微分3.3 偏导数 4 梯度4.1 梯度法4.2 神经网络的梯度 5 学习算法的实现5.1 2层神经…

【第45节】windows程序的其他反调试手段上篇

目录 引言 一、通过窗口类名和窗口名判断 二、检测调试器进程 三、父进程是否是Explorer 四、RDTSC/GetTickCount时间敏感程序段 五、StartupInfo结构的使用 六、使用BeingDebugged字段 七、 PEB.NtGlobalFlag,Heap.HeapFlags,Heap.ForceFlags 八、DebugPort:CheckRem…

Golang|select

文章目录 多路监听超时控制 多路监听 如果selcet外面没有for循环,则只会监听一次,要实现一直监听的话要加for循环但是如果要设置退出条件的话,break语句只会退出这个select而不会退出for循环 select也可以有default,用于不用等cha…

无人机的群体协同与集群控制技术要点!

一、技术要点 通信技术 高效可靠的通信链路:无人机集群需要稳定、低延迟的通信网络,以实现实时数据传输和指令交互。通信方式包括无线自组织网络(Ad Hoc)、蜂窝网络、卫星通信等,需根据任务场景选择合适的通信技术。…

新手小白如何给个人电脑安装Deepseek?

准备工作:Ollama安装包、Chatbox安装包 一、安装Ollama 官网下载: 在 Windows 上下载 Ollama:https://ollama.com/download/windows 下载较慢,大家可以自行搜索资源下载,直接双击安装即可。 安装完毕后,…

Redis之RedLock算法以及底层原理

自研redis分布式锁存在的问题以及面试切入点 lock加锁关键逻辑 unlock解锁的关键逻辑 使用Redis的分布式锁 之前手写的redis分布式锁有什么缺点?? Redis之父的RedLock算法 Redis也提供了Redlock算法,用来实现基于多个实例的分布式锁。…

【控制学】控制学分类

【控制学】控制学分类 文章目录 [TOC](文章目录) 前言一、工程控制论1. 经典控制理论2. 现代控制理论 二、生物控制论三、经济控制论总结 前言 控制学是物理、数学与工程的桥梁 提示:以下是本篇文章正文内容,下面案例可供参考 一、工程控制论 1. 经典…

Android 15 中 ApnPreferenceController 的 onStart 和 onStop 调用失效

背景 AOSP对APN入口(Access Point Name)实现中,overried了 onStart 和 onStop ,但实际执行中根本不会进入这两个接口的逻辑。 Q:MobileNetworkSettings (APN入口Preference所在的界面Fragement承载,TAG是NetworkSettings)的生命周期和ApnPreference 有什么关系? Not…

React 在组件间共享状态

在组件间共享状态 有时候,你希望两个组件的状态始终同步更改。要实现这一点,可以将相关 state 从这两个组件上移除,并把 state 放到它们的公共父级,再通过 props 将 state 传递给这两个组件。这被称为“状态提升”,这…

阶段性使用总结-通义灵码

序言 前段时间用通义灵码,参加了下数字中国闽江流域的比赛。https://www.dcic-china.com/competitions/10173 最后成绩一般般,106名,大概有2000多人参加这题目,估计有一堆小号。 按照下面这个思路建模的,迭代了大概15…

游戏引擎学习第228天

对上次的内容进行回顾,并为今天的开发环节做铺垫。 目前大部分功能我们已经完成了,唯一剩下的是一个我们知道存在但目前不会实际触发的 bug。这个 bug 的本质是在某些线程仍然访问一个已经被销毁的游戏模式(mode)之后的状态&…