ai部署1

可以。下面给你一份从裸机 CentOS 9 到单机训练、8 GPU DDP、4×8=32 GPU 分布式语言模型训练的完整文档,并且每个关键操作都增加:

  • 做什么

  • 为什么做

  • 作用

  • 验证方法

  • 异常时看什么

  • 4 台机器哪些操作完全一样

  • 哪些参数必须每台不同

另外,我会把之前容易混淆的 Driver / CUDA / NCCL / PyTorch / DDP / FSDP / 数据 / 模型 / checkpoint / 网络 / NUMA 全部串起来。

**重要修正:**不要把“安装 CUDA Toolkit 的版本”和“NVIDIA Driver 的版本”简单理解成必须一一对应;Driver 负责 GPU 内核接口,CUDA Toolkit 提供编译器和用户态库,实际兼容关系应以 NVIDIA/PyTorch 当前支持矩阵为准。部署时四台机器必须统一版本。

CentOS 9 + 4×8 NVIDIA A100 80GB

裸机 AI 语言模型单机与 32 GPU 分布式训练完整实施文档


1. 文档目标

本文部署:

4 台 CentOS 9
    │
    ├── gpu01
    │    └── 8 × NVIDIA A100 80GB
    │
    ├── gpu02
    │    └── 8 × NVIDIA A100 80GB
    │
    ├── gpu03
    │    └── 8 × NVIDIA A100 80GB
    │
    └── gpu04
         └── 8 × NVIDIA A100 80GB

总 GPU:

4 × 8 = 32 GPU

总显存:

32 × 80GB = 2560GB

部署方式:

裸机
├── NVIDIA Driver
├── CUDA
├── NCCL
├── Python
├── PyTorch
├── Transformers
├── Datasets
└── Distributed Training

明确:

不使用 Docker
不使用 Kubernetes
不依赖容器运行训练

训练阶段:

单 GPU
   ↓
单机 8 GPU
   ↓
4机 32 GPU
   ↓
大模型 FSDP / ZeRO

2. 整体架构

整个软件栈必须理解清楚。

                    语言模型
                       │
                       ▼
              Transformers
                       │
                       ▼
                   PyTorch
                       │
            ┌──────────┴──────────┐
            │                     │
          CUDA                  NCCL
            │                     │
            ▼                     ▼
      NVIDIA Driver        GPU Collective
            │                     │
            └──────────┬──────────┘
                       │
                       ▼
                     A100

跨机器时:

gpu01                    gpu02
8 GPU                    8 GPU
 │                         │
 └────── NCCL ─────────────┘
             │
          Network
             │
      Ethernet / IB / RoCE

四台:

gpu01 ─┐
gpu02 ─┤
gpu03 ─┼── NCCL ── Network
gpu04 ─┘

3. 为什么不能直接运行训练?

因为语言模型训练实际上依赖很多层:

训练代码
   ↓
Python
   ↓
PyTorch
   ↓
CUDA
   ↓
NVIDIA Driver
   ↓
GPU

多机以后增加:

PyTorch Distributed
   ↓
NCCL
   ↓
NIC
   ↓
交换机
   ↓
其他节点

所以必须逐层验证。


4. 节点规划

以下 IP 为示例。

NodeHostnameIPGPUNode Rank
1 gpu01 10.10.10.11 8 0
2 gpu02 10.10.10.12 8 1
3 gpu03 10.10.10.13 8 2
4 gpu04 10.10.10.14 8 3

最终:

NNODES = 4
GPUS_PER_NODE = 8
WORLD_SIZE = 32

5. 哪些操作四台完全一样?

以后文档中:

【4台全部执行】

代表:

gpu01
gpu02
gpu03
gpu04

全部执行相同命令。

只有下面这些必须不同:

hostname
IP
node-rank

例如:

gpu01 → rank 0
gpu02 → rank 1
gpu03 → rank 2
gpu04 → rank 3

6. 第一阶段:操作系统检查

6.1 查看 OS

【4台全部执行】

cat /etc/redhat-release

检查:

uname -a

检查:

uname -r

作用

确认:

CentOS / RHEL 9
Kernel
Architecture

为什么?

NVIDIA Driver、CUDA、RDMA 等软件都依赖 Kernel。


7. 设置 hostname

gpu01

hostnamectl set-hostname gpu01

gpu02

hostnamectl set-hostname gpu02

gpu03

hostnamectl set-hostname gpu03

gpu04

hostnamectl set-hostname gpu04

检查:

hostname

作用

给每台服务器一个唯一名字。


8. 配置 hosts

【4台全部执行】

cat >> /etc/hosts <<'EOF'
10.10.10.11 gpu01
10.10.10.12 gpu02
10.10.10.13 gpu03
10.10.10.14 gpu04
EOF

检查:

getent hosts gpu01
getent hosts gpu02
getent hosts gpu03
getent hosts gpu04

作用

实现:

gpu01 → 10.10.10.11

为什么?

方便:

ssh gpu02
ping gpu03

以及后续分布式运维。


9. 安装基础工具

【4台全部执行】

dnf install -y \
    gcc \
    gcc-c++ \
    make \
    cmake \
    git \
    wget \
    curl \
    vim \
    tmux \
    pciutils \
    ethtool \
    numactl \
    numactl-libs \
    hwloc \
    lsof \
    net-tools \
    sysstat \
    procps-ng \
    python3 \
    python3-devel \
    python3-pip \
    openssh-server \
    openssh-clients \
    chrony

作用

这些不是 AI 框架本身,而是:

系统管理
编译
网络
NUMA
监控
SSH
Python

10. 时间同步

【4台全部执行】

systemctl enable --now chronyd

检查:

chronyc tracking

检查:

timedatectl

作用

让四台服务器保持时间同步。

为什么?

分布式训练时日志可能来自:

gpu01
gpu02
gpu03
gpu04

如果时间不一致,故障分析非常困难。


11. CPU / NUMA 检查

【4台全部执行】

lscpu
numactl -H

重点记录:

CPU(s)
Socket(s)
Core(s)
NUMA node(s)

作用

确定 CPU 和 NUMA 拓扑。

这会影响:

GPU
PCIe
NIC
CPU
内存

之间的数据路径。


12. GPU PCIe 检查

【4台全部执行】

lspci | grep -i nvidia

必须看到 8 张 GPU。

作用

这是最底层的 GPU 检查。

如果:

lspci | grep -i nvidia

没有结果:

不要检查 PyTorch。

因为 Linux PCIe 层都没有识别 GPU。


13. 查看网卡

【4台全部执行】

ip -br link
ip -br addr

查看 PCI:

lspci | grep -i -E 'ethernet|mellanox|infiniband'

作用

确定:

管理网卡
训练网卡
高速网卡
IB / RoCE

后面 NCCL 需要使用正确的高速网络。


14. Nouveau

检查:

lsmod | grep nouveau

如果有:

cat > /etc/modprobe.d/blacklist-nouveau.conf <<'EOF'
blacklist nouveau
options nouveau modeset=0
EOF

然后:

dracut --force

重启:

reboot

重新检查:

lsmod | grep nouveau

作用

避免 Nouveau 和 NVIDIA 官方 Driver 冲突。


15. NVIDIA Driver

添加 NVIDIA Repository。

【4台全部执行】

dnf config-manager --add-repo \
https://developer.download.nvidia.com/compute/cuda/repos/rhel9/x86_64/cuda-rhel9.repo

然后:

dnf clean all
dnf makecache

查看:

dnf module list nvidia-driver

安装适合当前系统和 CUDA 组合的稳定 Driver。

例如环境统一采用 580 系列:

dnf module reset -y nvidia-driver
dnf module enable -y nvidia-driver:580-dkms
dnf module install -y nvidia-driver:580-dkms

重启:

reboot

Driver 的作用

建立:

Linux
 ↓
NVIDIA Driver
 ↓
A100

没有 Driver:

CUDA
PyTorch

都不能正常使用 GPU。


16. NVIDIA Driver 验证

【4台全部执行】

nvidia-smi

检查 GPU:

nvidia-smi -L

检查版本:

nvidia-smi --query-gpu=index,name,driver_version,memory.total \
--format=csv

必须:

8 GPU
A100
80GB
Driver版本一致

17. NVIDIA Persistence

【4台全部执行】

dnf install -y nvidia-persistenced
systemctl enable --now nvidia-persistenced

检查:

systemctl status nvidia-persistenced

作用

让 GPU 保持稳定的持久化状态。


18. CUDA Toolkit

统一安装一个经过验证的 CUDA 版本。

例如:

dnf install -y cuda-toolkit-13-0

配置:

cat > /etc/profile.d/cuda.sh <<'EOF'
export CUDA_HOME=/usr/local/cuda
export PATH=/usr/local/cuda/bin:$PATH
export LD_LIBRARY_PATH=/usr/local/cuda/lib64:${LD_LIBRARY_PATH:-}
EOF

然后:

ln -sfn /usr/local/cuda-13.0 /usr/local/cuda

加载:

source /etc/profile.d/cuda.sh

检查:

nvcc --version

CUDA 的作用

CUDA 是 GPU 计算平台。

提供:

CUDA Runtime
CUDA libraries
nvcc
GPU kernel execution

19. Driver 和 CUDA 的关系

一定要区分:

NVIDIA Driver

和:

CUDA Toolkit

架构:

PyTorch
   ↓
CUDA Runtime
   ↓
NVIDIA Driver
   ↓
A100

而:

nvcc

来自:

CUDA Toolkit

所以:

nvidia-smi

和:

nvcc --version

检查的是不同东西。


20. 创建 AI 用户

【4台全部执行】

useradd -m -s /bin/bash ai 2>/dev/null || true

创建目录:

mkdir -p /data/ai/{venv,models,datasets,checkpoints,logs,scripts}

授权:

chown -R ai:ai /data/ai

作用

不要使用 root 直接训练。

AI 用户负责:

模型
数据
训练
checkpoint
日志

21. Python 虚拟环境

【4台全部执行】

su - ai
python3 -m venv /data/ai/venv

激活:

source /data/ai/venv/bin/activate

升级:

pip install -U pip setuptools wheel

作用

隔离 Python 依赖。


22. PyTorch

【4台全部执行】

根据实际 CUDA/Driver 组合选择经过验证的 PyTorch wheel。

例如 CUDA 13.0:

pip install \
    torch==2.12.1 \
    torchvision==0.27.1 \
    --index-url https://download.pytorch.org/whl/cu130

PyTorch 的作用

提供:

Tensor
Autograd
Neural Network
Optimizer
DataLoader
Distributed
CUDA backend

23. PyTorch CUDA 验证

【4台全部执行】

python - <<'PY'
import torch

print("PyTorch =", torch.__version__)
print("CUDA runtime =", torch.version.cuda)
print("CUDA available =", torch.cuda.is_available())
print("GPU count =", torch.cuda.device_count())

for i in range(torch.cuda.device_count()):
    print(
        i,
        torch.cuda.get_device_name(i),
        torch.cuda.get_device_properties(i).total_memory / 1024**3
    )
PY

必须:

CUDA available = True
GPU count = 8

24. 为什么需要 PyTorch 验证?

因为:

nvidia-smi

正常只说明:

Driver → GPU

而:

torch.cuda.is_available()

验证:

PyTorch
 ↓
CUDA
 ↓
Driver
 ↓
GPU

25. 安装 Transformers

【4台全部执行】

pip install transformers

作用

提供:

Transformer
Tokenizer
Model
Trainer
Config

例如:

Qwen
Llama
BERT
GPT

等模型可以通过 Transformers 加载。


26. 安装 Datasets

pip install datasets

作用

处理训练数据:

JSON
JSONL
Parquet
Arrow

例如:

train.jsonl
validation.jsonl

转换成:

Dataset

27. 安装 Accelerate

pip install accelerate

作用

统一管理:

CPU
GPU
Multi-GPU
Mixed Precision
Distributed

后续使用:

FSDP
DeepSpeed

也经常通过 Accelerate 配置。


28. 安装 TensorBoard

pip install tensorboard

作用

观察训练:

loss
learning rate
step
epoch
throughput

29. 安装 DeepSpeed

如果以后需要:

pip install deepspeed

作用

大模型显存优化。

例如:

ZeRO-1
ZeRO-2
ZeRO-3

30. SSH 免密

在 gpu01:

su - ai
ssh-keygen -t ed25519

复制:

ssh-copy-id ai@gpu01
ssh-copy-id ai@gpu02
ssh-copy-id ai@gpu03
ssh-copy-id ai@gpu04

测试:

ssh ai@gpu01 hostname
ssh ai@gpu02 hostname
ssh ai@gpu03 hostname
ssh ai@gpu04 hostname

作用

方便:

集群管理
同步代码
同步数据
启动训练
故障排查

注意:

torchrun 的 rendezvous 本身并不依赖 SSH 免密;免密 SSH 是为了运维便利,以及后续脚本化启动/同步。


31. GPU Topology

【4台全部执行】

nvidia-smi topo -m

作用

查看:

GPU ↔ GPU
GPU ↔ CPU
GPU ↔ NIC

之间的拓扑关系。

例如:

GPU0
 │
 PCIe Switch
 │
 GPU1

可能比:

GPU0
 │
 CPU
 │
 GPU1

通信更快。


32. GPU P2P

【4台全部执行】

nvidia-smi topo -p2p p

作用

确认 GPU 间 Peer-to-Peer。

DDP/NCCL 单机 8 GPU 会大量使用 GPU collective communication。

如果 P2P 有问题:

NCCL
 ↓
GPU communication
 ↓
性能下降 / 初始化失败

33. NUMA

numactl -H

作用

确认:

CPU socket
NUMA node
Memory

例如:

NUMA 0
 ├── CPU
 ├── GPU
 └── NIC

NUMA 1
 ├── CPU
 ├── GPU
 └── NIC

如果 GPU 和 NIC 位于不同 NUMA:

GPU
 ↓
PCIe
 ↓
NUMA 0
 ↓
CPU interconnect
 ↓
NUMA 1
 ↓
NIC

通信可能产生额外开销。


34. NCCL

NCCL 是:

NVIDIA Collective Communications Library

主要负责:

AllReduce
Broadcast
Reduce
AllGather
ReduceScatter

最重要的就是:

梯度同步

35. 为什么 DDP 需要 NCCL?

假设:

GPU0
GPU1
GPU2
GPU3

每个 GPU 都计算了一部分:

gradient

最后必须:

GPU0 gradient
GPU1 gradient
GPU2 gradient
GPU3 gradient

进行同步。

例如:

             Gradient
                 │
       ┌─────────┼─────────┐
       │         │         │
      GPU0      GPU1      GPU2 ...
       │         │         │
       └────── AllReduce ──┘
                 │
          同样的 gradient

这个工作就是 NCCL 非常擅长做的。


36. NCCL 基础环境

【4台全部执行】

cat > /etc/profile.d/nccl.sh <<'EOF'
export NCCL_DEBUG=WARN
export NCCL_ASYNC_ERROR_HANDLING=1
EOF

加载:

source /etc/profile.d/nccl.sh

为什么不一开始配置一堆 NCCL 参数?

因为 NCCL 会根据:

PCIe
NUMA
GPU topology
NIC

自动选择通信路径。

在不知道实际硬件拓扑之前强制设置:

NCCL_P2P_DISABLE
NCCL_IB_DISABLE
NCCL_SOCKET_IFNAME
NCCL_NET_GDR_LEVEL

可能反而降低性能或造成问题。


37. 网络

查看:

ip -br addr

查看网卡:

ip -br link

查看速率:

ethtool <网卡>

例如:

ethtool ens1f0

作用

确定:

10GbE
25GbE
50GbE
100GbE
200GbE
400GbE

等实际链路。


38. 为什么网络对 32 GPU 很重要?

单机:

GPU0 ↔ GPU1

主要走:

PCIe

跨机:

GPU0
 ↓
PCIe
 ↓
NIC
 ↓
Switch
 ↓
NIC
 ↓
PCIe
 ↓
GPU8

所以:

GPU计算速度

和:

GPU之间通信速度

都会影响最终训练速度。


39. IB / RoCE

如果有 Mellanox/NVIDIA 高速网卡:

lspci | grep -i mellanox

安装:

dnf install -y \
    rdma-core \
    libibverbs \
    libibverbs-utils \
    infiniband-diags

检查:

ibstat
ibdev2netdev
ibv_devinfo
rdma link

作用

确认 RDMA 是否正常。


40. 单 GPU CUDA 测试

创建:

cat > /data/ai/scripts/gpu_test.py <<'PY'
import torch
import time

print("GPU count:", torch.cuda.device_count())

for i in range(torch.cuda.device_count()):
    print(i, torch.cuda.get_device_name(i))

x = torch.randn(8192, 8192, device="cuda")
y = torch.randn(8192, 8192, device="cuda")

torch.cuda.synchronize()

start = time.time()

for _ in range(20):
    z = torch.matmul(x, y)

torch.cuda.synchronize()

print("elapsed:", time.time() - start)
print("mean:", z.mean().item())
PY

运行:

CUDA_VISIBLE_DEVICES=0 \
python /data/ai/scripts/gpu_test.py

作用

验证真正 GPU 计算。

不是只验证:

nvidia-smi

而是:

Python
 ↓
PyTorch
 ↓
CUDA
 ↓
GPU kernel
 ↓
A100

41. 单机 8 GPU DDP

创建:

cat > /data/ai/scripts/ddp_test.py <<'PY'
import os
import torch
import torch.distributed as dist

def main():
    dist.init_process_group("nccl")

    rank = dist.get_rank()
    world_size = dist.get_world_size()

    local_rank = int(os.environ["LOCAL_RANK"])

    torch.cuda.set_device(local_rank)

    x = torch.tensor(
        [float(rank + 1)],
        device="cuda"
    )

    dist.all_reduce(x)

    print(
        f"rank={rank}, "
        f"local_rank={local_rank}, "
        f"world_size={world_size}, "
        f"gpu={torch.cuda.get_device_name(local_rank)}, "
        f"allreduce={x.item()}"
    )

    dist.barrier()

    dist.destroy_process_group()

if __name__ == "__main__":
    main()
PY

运行:

torchrun \
    --standalone \
    --nproc-per-node=8 \
    /data/ai/scripts/ddp_test.py

作用

测试:

8 GPU
8 process
8 rank
NCCL
AllReduce

理论结果:

1+2+3+4+5+6+7+8 = 36

所以每个 rank 应该看到:

allreduce=36

42. torchrun 是什么?

torchrun ...

负责启动多个 PyTorch 进程。

单机:

torchrun
 ├── rank0 → GPU0
 ├── rank1 → GPU1
 ├── rank2 → GPU2
 ...
 └── rank7 → GPU7

多机:

gpu01
 ├── rank0
 ├── ...
 └── rank7

gpu02
 ├── rank8
 ├── ...
 └── rank15

gpu03
 ├── rank16
 ├── ...
 └── rank23

gpu04
 ├── rank24
 ├── ...
 └── rank31

43. --nnodes=4

--nnodes=4

作用

告诉 PyTorch:

总共有 4 台机器

44. --nproc-per-node=8

--nproc-per-node=8

作用

每台机器启动 8 个训练进程。

因为:

8 GPU

所以:

1 process ↔ 1 GPU

45. --node-rank

例如 gpu01:

--node-rank=0

gpu02:

--node-rank=1

gpu03:

--node-rank=2

gpu04:

--node-rank=3

作用

告诉系统:

我是第几台训练节点。


46. --master-addr

--master-addr=10.10.10.11

作用

指定 rendezvous/master 地址。

例如:

gpu01 = master

其他机器需要能够访问:

10.10.10.11:29500

47. --master-port

--master-port=29500

作用

提供分布式初始化通信端口。

检查:

ss -lntp | grep 29500

48. 32 GPU 启动

gpu01

torchrun \
    --nnodes=4 \
    --nproc-per-node=8 \
    --node-rank=0 \
    --master-addr=10.10.10.11 \
    --master-port=29500 \
    /data/ai/scripts/ddp_test.py

gpu02

torchrun \
    --nnodes=4 \
    --nproc-per-node=8 \
    --node-rank=1 \
    --master-addr=10.10.10.11 \
    --master-port=29500 \
    /data/ai/scripts/ddp_test.py

gpu03

torchrun \
    --nnodes=4 \
    --nproc-per-node=8 \
    --node-rank=2 \
    --master-addr=10.10.10.11 \
    --master-port=29500 \
    /data/ai/scripts/ddp_test.py

gpu04

torchrun \
    --nnodes=4 \
    --nproc-per-node=8 \
    --node-rank=3 \
    --master-addr=10.10.10.11 \
    --master-port=29500 \
    /data/ai/scripts/ddp_test.py

49. 32 GPU 成功标准

必须看到:

rank 0
rank 1
...
rank 31

并且:

world_size=32

每个 rank 都有:

local_rank=0~7

并且:

allreduce=528

因为:

1+2+...+32 = 528

50. 为什么 world_size=32

公式:

world_size
=
node_count
×
GPU_per_node

所以:

4 × 8 = 32

51. 准备语言模型数据

目录:

/data/ai/datasets/
├── train.jsonl
├── validation.jsonl
└── test.jsonl

JSONL:

{"text":"Linux 是一种开源操作系统。"}
{"text":"NVIDIA A100 是数据中心 GPU。"}
{"text":"PyTorch 可以用于深度学习训练。"}

作用

模型训练的原始数据。


52. 为什么需要 train / validation / test?

train
 ↓
更新模型参数

validation
 ↓
判断模型是否过拟合
选择参数

test
 ↓
最终评价

不能把所有数据都拿来训练。


53. Tokenizer

例如:

tokenizer = AutoTokenizer.from_pretrained(...)

作用

把:

文本

变成:

token ID

例如:

Linux 是操作系统

变成:

[1234, 567, 8910, ...]

GPU 不能直接训练字符串。


54. Causal Language Model

训练目标:

输入:

我 喜欢

预测:

学习

即:

x1 → x2
x1 x2 → x3
x1 x2 x3 → x4

核心:

next token prediction

55. Forward

模型:

token IDs
 ↓
Embedding
 ↓
Transformer layers
 ↓
Logits

得到:

logits

表示每一个 token 的预测概率。


56. Loss

使用:

Cross Entropy

比较:

预测 token

和:

真实 token

差异。

训练目标:

loss ↓

57. Backward

执行:

loss.backward()

计算:

∂Loss / ∂Parameter

也就是:

gradient

58. Optimizer

例如:

AdamW

负责:

Parameter
+
Gradient
→
新的 Parameter

也就是:

模型更新

59. DDP 中的 AllReduce

这是多 GPU 训练的核心。

每个 GPU:

Forward
 ↓
Loss
 ↓
Backward
 ↓
Gradient

然后:

GPU0 ─┐
GPU1 ─┤
GPU2 ─┼── AllReduce
...   ┤
GPU7 ─┘

最后:

所有 GPU
拥有一致的 gradient

然后各自更新模型。


60. 单机训练

先:

CUDA_VISIBLE_DEVICES=0 \
python train_lm.py

作用

验证:

模型
数据
Tokenizer
Loss
Optimizer

61. 单机 8 GPU 训练

torchrun \
    --standalone \
    --nproc-per-node=8 \
    train_lm.py

作用

验证:

单机 8 GPU
DDP
NCCL
梯度同步

62. Global Batch Size

公式:

Global Batch Size
=
per_device_batch_size
×
gradient_accumulation_steps
×
world_size

例如:

per_device = 1
gradient_accumulation = 16
world_size = 32

得到:

1 × 16 × 32
=
512

63. Gradient Accumulation

如果:

GPU显存不够

不能继续增加:

batch size

可以:

batch = 1
gradient accumulation = 16

等效增加训练 batch。


64. BF16

A100 支持 BF16。

训练大模型通常优先考虑:

bf16=True

作用:

降低显存
提高吞吐
保持比 FP16 更大的指数范围

65. Gradient Checkpointing

gradient_checkpointing=True

作用:

保存更少 activation

训练时重新计算一部分 activation。

结果:

显存 ↓
计算量 ↑

66. Sequence Length

例如:

2048
4096
8192

长度越大:

显存需求 ↑
计算量 ↑

因此第一次训练建议:

2048

确认正常后再增加。


67. DataLoader

dataloader_num_workers=8

作用

多个 CPU worker 并行准备数据。

流程:

磁盘
 ↓
CPU workers
 ↓
DataLoader
 ↓
GPU

如果 worker 太少:

GPU 等数据

如果太多:

CPU / 内存 / IO 压力

68. TensorBoard

tensorboard \
    --logdir /data/ai/logs \
    --bind_all \
    --port 6006

作用

观察:

loss
learning rate
step
epoch

69. GPU 监控

watch -n 1 nvidia-smi

或者:

nvidia-smi dmon -s pucm

作用

观察:

GPU utilization
memory
power
clock

70. CPU 监控

mpstat -P ALL 1

作用

检查 CPU 是否成为瓶颈。


71. 内存监控

free -h

72. NUMA 监控

numastat

作用

检查是否存在:

NUMA remote memory

73. IO 监控

iostat -xz 1

作用

判断训练是不是卡在:

NVMe
磁盘
文件系统

74. 网络监控

sar -n DEV 1

作用

观察:

RX
TX
bandwidth
packet

75. checkpoint

训练过程中:

checkpoint-500
checkpoint-1000
checkpoint-1500

作用

防止:

服务器宕机
GPU故障
进程异常
网络异常

导致全部重训。


76. checkpoint 应保存什么?

至少:

model
optimizer
scheduler
trainer state
global step
random state

不能只保存:

model.safetensors

否则只能恢复模型,不能完整恢复训练过程。


77. 单纯 DDP 的局限

DDP 的基本模型:

GPU0 → 一份模型
GPU1 → 一份模型
GPU2 → 一份模型
...
GPU31 → 一份模型

也就是说:

32 GPU
=
32 model replicas

如果模型很大:

70B

可能根本放不下。


78. FSDP

FSDP:

Fully Sharded Data Parallel

核心思想:

模型参数
梯度
Optimizer State

进行分片。

例如:

GPU0 → shard0
GPU1 → shard1
GPU2 → shard2
...

因此:

单 GPU 显存压力 ↓

79. DeepSpeed ZeRO

ZeRO:

ZeRO-1
ZeRO-2
ZeRO-3

逐步切分:

Optimizer states
        ↓
Gradients
        ↓
Parameters

ZeRO-3 可以进一步切分模型参数。


80. 什么时候 DDP?

适合:

小模型
中等模型
显存充足
追求简单

例如:

0.6B
1B
3B
7B

具体还取决于:

sequence length
batch size
optimizer
activation

81. 什么时候 FSDP / ZeRO?

例如:

14B
32B
70B

如果 DDP:

每张 GPU 都保存完整模型

显存压力会非常大。

这时:

FSDP

或者:

ZeRO-3

更加合理。


82. 训练故障排查顺序

GPU 不识别

lspci
 ↓
nvidia-smi
 ↓
Driver

CUDA 不可用

nvidia-smi
 ↓
nvcc
 ↓
PyTorch
 ↓
torch.cuda.is_available()

单机 DDP 卡住

torchrun
 ↓
NCCL
 ↓
GPU topology
 ↓
P2P

多机 DDP 卡住

优先:

IP
 ↓
port
 ↓
firewall
 ↓
NCCL interface
 ↓
NIC
 ↓
IB/RoCE
 ↓
NCCL

83. 多机 NCCL Debug

临时:

export NCCL_DEBUG=INFO

如果重点看网络:

export NCCL_DEBUG_SUBSYS=NET

然后运行:

torchrun ...

重点看:

Socket
IB
NET
P2P

84. NCCL 网卡指定

只有确认高速网卡以后再设置。

例如:

ens1f0

可以:

export NCCL_SOCKET_IFNAME==ens1f0

如果是 IB/RoCE,还要进一步确认:

RDMA
verbs
NIC
GDR
NCCL

不能只看到 Mellanox 就认为 NCCL 一定使用 RDMA。


85. 防火墙

查看:

firewall-cmd --list-all

测试端口:

nc -zv 10.10.10.11 29500

作用

确认:

其他节点
 ↓
gpu01
 ↓
29500

能够访问。

生产环境不要长期:

systemctl stop firewalld

而应该只开放必要端口。


86. 训练时 GPU 低利用率

例如:

GPU = 20%
CPU = 100%

优先检查:

DataLoader
Tokenizer
CPU
IO
NUMA

87. 单机高,多机低

例如:

8 GPU:
95%

32 GPU:
40%

优先检查:

NCCL
网络
NIC
RDMA
PCIe
NUMA
GPU-NIC topology

而不是首先修改:

learning rate
batch size

88. GPU OOM

出现:

CUDA out of memory

推荐顺序:

1. batch size ↓
2. sequence length ↓
3. gradient checkpointing
4. gradient accumulation
5. BF16
6. FSDP / ZeRO

89. 训练数据和代码一致性

四台必须保持:

train_lm.py
transformers版本
PyTorch版本
CUDA环境
模型配置
Tokenizer

一致。

例如不要:

gpu01 transformers 5.x
gpu02 transformers 4.x

90. 四台环境检查脚本

建议创建:

cat > /data/ai/scripts/check_env.sh <<'EOF'
#!/bin/bash

set -e

echo "========== HOST =========="
hostname

echo "========== OS =========="
cat /etc/redhat-release

echo "========== KERNEL =========="
uname -r

echo "========== NVIDIA =========="
nvidia-smi --query-gpu=index,name,driver_version,memory.total \
--format=csv

echo "========== CUDA =========="
nvcc --version | tail -n 4

echo "========== PYTORCH =========="
python - <<'PY'
import torch

print("torch:", torch.__version__)
print("cuda:", torch.version.cuda)
print("available:", torch.cuda.is_available())
print("count:", torch.cuda.device_count())

for i in range(torch.cuda.device_count()):
    print(i, torch.cuda.get_device_name(i))
PY

echo "========== TOPOLOGY =========="
nvidia-smi topo -m

echo "========== NUMA =========="
numactl -H

echo "========== NETWORK =========="
ip -br addr
EOF

授权:

chmod +x /data/ai/scripts/check_env.sh

执行:

/data/ai/scripts/check_env.sh

作用

统一检查四台机器环境。


91. 四台机器最终应该完全一致的内容

OS
Kernel
NVIDIA Driver
CUDA
NCCL
Python
PyTorch
Transformers
Datasets
Accelerate
DeepSpeed
训练代码

92. 四台机器必须不同的内容

只有:

hostname
IP
node-rank

例如:

gpu01:
node-rank=0

gpu02:
node-rank=1

gpu03:
node-rank=2

gpu04:
node-rank=3

93. 第一轮实验顺序

严格按照:

阶段 1
裸机检查
   ↓
阶段 2
Driver
   ↓
阶段 3
CUDA
   ↓
阶段 4
PyTorch
   ↓
阶段 5
单 GPU CUDA
   ↓
阶段 6
单机 8 GPU NCCL
   ↓
阶段 7
单机 8 GPU DDP
   ↓
阶段 8
4机网络
   ↓
阶段 9
4机 32 GPU NCCL
   ↓
阶段 10
4机 32 GPU DDP
   ↓
阶段 11
小语言模型训练
   ↓
阶段 12
正式数据
   ↓
阶段 13
7B+
   ↓
阶段 14
FSDP / ZeRO

94. 不要直接做的事情

不要第一步就:

32 GPU
70B
8192 sequence

因为出了问题不知道是哪一层。

正确方法:

GPU
 ↓
CUDA
 ↓
PyTorch
 ↓
NCCL
 ↓
DDP
 ↓
Model
 ↓
Data
 ↓
Large Model

逐层验证。


95. 最终完整架构

最终生产环境:

                       AI Training
                            │
                     Transformer LM
                            │
                     PyTorch Trainer
                            │
                 ┌──────────┴──────────┐
                 │                     │
                DDP                  FSDP
                 │                     │
                 └──────────┬──────────┘
                            │
                          NCCL
                            │
          ┌─────────────────┼─────────────────┐
          │                 │                 │
        gpu01             gpu02             gpu03       gpu04
          │                 │                 │           │
       8 × A100          8 × A100          8 × A100    8 × A100
          │                 │                 │           │
          └─────────────────┴─────────────────┴───────────┘
                            │
                         Network
                            │
                     IB / RoCE / Ethernet

96. 资源关系

最终可以把整个系统理解为:

A100
 │
 │ 负责计算
 ▼
CUDA
 │
 │ 提供GPU计算接口
 ▼
PyTorch
 │
 │ 负责Tensor/Autograd/Training
 ▼
NCCL
 │
 │ 负责GPU之间通信
 ▼
Network
 │
 │ 负责机器之间通信
 ▼
Distributed Training
 │
 ▼
Transformer
 │
 ▼
Language Model

97. 最终验收表

层级检查命令正常结果
OS cat /etc/redhat-release CentOS/RHEL 9
Kernel uname -r 统一
PCIe lspci | grep -i nvidia 8 GPU
Driver nvidia-smi 正常
GPU nvidia-smi -L 8 GPU
CUDA nvcc --version 统一
PyTorch python -c 'import torch' 正常
CUDA/PyTorch torch.cuda.is_available() True
GPU count torch.cuda.device_count() 8
Topology nvidia-smi topo -m 正常
NUMA numactl -H 正常
Network ping 正常
TCP nc 正常
RDMA ibstat 如使用 IB
NCCL DDP test 正常
单机 DDP torchrun 8 ranks
多机 DDP torchrun 32 ranks
模型 train_lm.py loss 正常
Checkpoint checkpoint-* 正常
TensorBoard tensorboard 正常

98. 最终目标

最终形成:

              4台裸机
                 │
       ┌─────────┴─────────┐
       │                   │
    每台8 GPU            每台统一环境
       │                   │
       └─────────┬─────────┘
                 │
              32 GPU
                 │
              PyTorch
                 │
               NCCL
                 │
          Distributed DDP
                 │
          Language Model
                 │
      ┌──────────┴──────────┐
      │                     │
   单机训练               分布式训练
      │                     │
    8 GPU                  32 GPU
      │                     │
      └──────────┬──────────┘
                 │
          大模型训练
                 │
          FSDP / ZeRO

核心原则:

先把硬件层打通
    ↓
再把 Driver 打通
    ↓
再把 CUDA 打通
    ↓
再把 PyTorch 打通
    ↓
再把单机 NCCL 打通
    ↓
再把单机 DDP 打通
    ↓
再把跨机网络打通
    ↓
再把 32 GPU NCCL 打通
    ↓
再做 32 GPU DDP
    ↓
最后才进入正式语言模型训练

这套顺序可以把问题明确定位到具体层,而不是出现“32 GPU 训练卡住”以后同时怀疑 Driver、CUDA、NCCL、网络、模型、数据和代码

posted on 2026-08-24 17:10  小镇-做题家  阅读(3)  评论(0)    收藏  举报

导航