# GPU 通信技术全景：从 PCIe、NVLink 到 RDMA、EFA 与 NCCL

> 训练大模型时，通信会取代计算成为瓶颈。这篇文章把 GPU 互联的整条链路一次讲透：PCIe 的事务模型与 BAR、NVLink/NVSwitch 的全互联与在网规约、AMD Infinity Fabric、RDMA/InfiniBand 的 QP 与内存注册、RoCE 的无损以太网三件套、AWS EFA 的 SRD 多路径喷洒、GPUDirect 如何消除 CPU 拷贝，以及 NCCL 如何调度这一切。

- 作者: zhuermu
- 发布: 2026-06-18
- 网页版: https://zhuermu.com/blog/gpu-communication-deep-dive/

---
> 这是一篇把 GPU 互联与通信技术串成一条链路的全景文章。目标不是停留在“带宽多少、能干什么”，而是深入到总线协议、内存模型、报文封装、拥塞控制与集合通信算法这一层。

## 为什么需要 GPU 通信技术

一块现代 AI 加速卡（如 NVIDIA H100）的算力高达数百 TFLOPS，但单卡显存只有几十到上百 GB。训练一个千亿/万亿参数大模型，必须把模型和数据切分到成百上千张 GPU 上协同计算。此时**通信**会取代**计算**成为瓶颈：

```text
训练一步的时间 ≈ max(计算时间, 通信时间)   （理想重叠情况下）
```

当模型并行 / 数据并行的梯度同步（AllReduce）跟不上计算速度时，GPU 就会“算完等数据”，利用率（MFU）骤降。因此整个 AI 基础设施的核心命题之一，就是：

> **如何让数据在 GPU 之间以尽可能高的带宽、尽可能低的延迟流动。**

全文的结构，也就是数据流动的层次：**节点内**（PCIe → NVLink/NVSwitch/Infinity Fabric）、**节点间**（RDMA/InfiniBand → RoCE → EFA）、**贯穿两者的加速机制**（GPUDirect），以及**在上层调度这一切的大脑**（NCCL）。

## 一、PCIe：一切的通用基石

即便有了 NVLink，GPU 的枚举、初始化、与 CPU 的控制面交互、与网卡的部分数据通路，仍然走 PCIe。

### 1.1 从并行共享总线到点对点串行链路

早期 PCI 是并行共享总线：多设备挂在同一组并行信号线上分时复用。缺点是共享带宽、并行线间时钟偏移（skew）限制频率、扩展性差。PCIe 做了三点范式转变：

- **点对点**：每个设备独占一条到交换结构的链路。
- **串行差分信令**：一个 lane 含 TX/RX 差分对，靠差分消除共模噪声，把频率推到 GHz 级。
- **交换式结构**：通过 Root Complex 和 Switch 构成树形拓扑，类似网络交换机。

```text
              ┌──────────┐
              │   CPU    │
              │  + Root  │   Root Complex：PCIe 拓扑的根
              │ Complex  │
              └────┬─────┘
                   │ (PCIe Link)
          ┌────────┴────────┐
          │   PCIe Switch   │   含上行口与多个下行口
          └──┬───────────┬──┘
             │           │
        ┌────┴───┐   ┌───┴────┐
        │  GPU   │   │  NIC   │   Endpoint：终端设备
        └────────┘   └────────┘
```

关键点：**GPU-GPU 走 PCIe 时，数据要先上行到 Switch 或 Root Complex，再下行到目标 GPU。** 同一 Switch 下可做 Switch 内 P2P；跨 Root Complex（跨 NUMA / 跨 socket）还要经过 CPU 间互联（如 UPI），延迟更高。这正是 NVLink 要解决的问题。

### 1.2 三层协议栈与 TLP

```text
┌─────────────────────────────────┐
│  事务层 (Transaction Layer)      │  生成/解析 TLP，事务语义、流控、QoS
├─────────────────────────────────┤
│  数据链路层 (Data Link Layer)    │  序号、ACK/NAK、重传、LCRC
├─────────────────────────────────┤
│  物理层 (Physical Layer)         │  串行化、编码、加扰、链路训练
└─────────────────────────────────┘
```

事务层的基本单位是 **TLP（Transaction Layer Packet）**。理解性能的关键是 Posted 与 Non-Posted 的区别：

| 事务类型 | 说明 | 是否需要 Completion |
|----------|------|----------------------|
| Memory Read | 读内存/读 MMIO 寄存器 | 是（Non-Posted） |
| Memory Write | 写内存/写寄存器 | 否（Posted，发完即走） |
| Configuration | 读写配置空间（枚举设备） | 是 |
| Message | 中断（MSI/MSI-X）、电源管理、错误信号 | 否 |

- **Memory Write 是 Posted**：发出后立即认为完成，可流水线化、吞吐高。
- **Memory Read 是 Non-Posted**：必须等对方回 Completion TLP，引入 RTT 级延迟，受“飞行中读请求数量”限制。

> 这解释了一个贯穿全文的工程现象：**很多高性能数据通路（GPUDirect、RDMA）都尽量用“写”而非“读”来搬数据。**

还有两个影响有效带宽的参数：**MPS（Max Payload Size，单个 TLP 最大数据量，常见 128/256/512 B）** 和 **MRRS（Max Read Request Size）**。若 MPS=256B、Header=12B，加上帧定界、序号与 LCRC，协议税约 20~24B，有效率约 256/(256+24) ≈ 91%——MPS 越小，这个比例越差。

链路层负责可靠传输：给每个 TLP 加序号与 LCRC，正确回 ACK、错误回 NAK 触发重传，未被 ACK 的 TLP 留在 Replay Buffer。此外它用 DLLP 维护**基于信用的流控**——接收方告知发送方还有多少缓冲信用，发送方只在有信用时才发。**PCIe 因此天生无损，不靠丢包反压**（这一点与后文 RoCE 需要 PFC 模拟无损以太网形成鲜明对比）。

物理层负责 SerDes、加扰与编码。编码演进直接决定了带宽：PCIe 1.0/2.0 用 8b/10b（开销 20%），3.0~5.0 用 128b/130b（开销仅约 1.5%），6.0 起改用 PAM4（一个符号载 2 bit）+ FEC + FLIT 模式。

### 1.3 各代速率与带宽换算

| 版本 | 速率 (per lane) | 编码 | 单 lane 有效带宽 | x16 单向 |
|------|------------------|------|-------------------|-----------|
| 1.0 | 2.5 GT/s | 8b/10b | 0.25 GB/s | ~4 GB/s |
| 2.0 | 5.0 GT/s | 8b/10b | 0.5 GB/s | ~8 GB/s |
| 3.0 | 8.0 GT/s | 128b/130b | ~0.985 GB/s | ~16 GB/s |
| 4.0 | 16 GT/s | 128b/130b | ~1.97 GB/s | ~32 GB/s |
| 5.0 | 32 GT/s | 128b/130b | ~3.94 GB/s | ~64 GB/s |
| 6.0 | 64 GT/s (PAM4) | PAM4+FLIT+FEC | ~7.5 GB/s | ~120 GB/s |
| 7.0 | 128 GT/s (PAM4) | PAM4+FLIT+FEC | ~15 GB/s | ~240 GB/s |

> 表中 x16 一列统一按「单 lane 有效带宽 × 16」计算，因此和常见的营销口径略有差异。
> PCIe 6.0/7.0 常被标称为 128 / 256 GB/s，那是**裸速率**聚合值（64 GT/s × 16 ÷ 8 = 128），
> 没有扣除 FLIT 模式下的 FEC 与 CRC 开销；扣掉之后约为 120 / 240 GB/s。
> 注意 6.0 起不再用 128b/130b，下面的公式只适用于 3.0~5.0。

```text
适用于 PCIe 3.0~5.0（128b/130b 编码）：
单 lane 有效带宽 = 速率(GT/s) × (128/130) / 8  [GB/s]
例：PCIe 4.0 = 16 × (128/130) / 8 ≈ 1.97 GB/s
x16 单向 = 1.97 × 16 ≈ 32 GB/s；全双工双向约 64 GB/s
```

### 1.4 BAR 与 MMIO：GPUDirect 的物理基础

PCIe 设备通过 **BAR（Base Address Register）** 把自己的内存/寄存器映射到系统物理地址空间，这叫 **MMIO**。系统枚举时给每个 BAR 分配一段物理地址；CPU 访问这段地址时，Root Complex 把它翻译成 Memory Read/Write TLP 发给设备。反过来，设备做 DMA 时发出的 TLP 带的是系统物理地址（或经 IOMMU 翻译的 IOVA）。

这对 GPU 通信至关重要：

- GPU 显存可以通过 BAR（尤其 **BAR1 / Resizable BAR**）暴露到 PCIe 地址空间。
- 一旦显存对外可寻址，**另一块 GPU 或网卡就能直接对它发 Memory Write TLP**——这就是 **GPUDirect P2P / RDMA** 的物理基础。
- **IOMMU**（Intel VT-d / AMD-Vi）在设备 DMA 与物理内存之间做地址翻译与隔离；在虚拟化与 P2P 场景下，它的配置直接影响 P2P 是否可用。

### 1.5 ACS：为什么有时 GPU 间走 PCIe 特别慢

**ACS（Access Control Services）** 是一种安全机制，它可以强制要求 Switch 下行口之间的 P2P 流量先上送到 Root Complex 再下发，以便 IOMMU 检查。这在虚拟化中是安全特性，但对 P2P 性能是灾难——本可在 Switch 内直接转的流量被迫绕一大圈。

工程经验：同一 Switch 下两 GPU，关闭 ACS 重定向后可走 Switch 内 P2P；跨 socket 的 GPU P2P 要经 CPU 间互联，带宽受限、延迟高，NCCL 拓扑探测会把它判为低优先级路径。这也是数据中心 GPU 服务器倾向用 PCIe Switch 把 GPU 与 NIC 组织在同一 Switch 下、并精心规划 NUMA 亲和性的原因。

### 1.6 PCIe 的四道墙

| 维度 | PCIe 的瓶颈 |
|------|-------------|
| 带宽 | PCIe 5.0 x16 仅 ~64 GB/s 单向，H100 NVLink 达 ~450 GB/s/方向 |
| 拓扑 | 树形结构，GPU-GPU 要经 Switch/Root，跨 socket 更绕 |
| 一致性 | 不是缓存一致的互联，GPU 间共享数据要显式管理 |
| 延迟 | 经 Root Complex 转发，延迟高于直连 |

## 二、NVLink：GPU 间的高速直连

NVLink 是 NVIDIA 为突破上述限制设计的**点对点、缓存一致、高速串行互联**。

### 2.1 物理层次：Link → Sub-link → Lane

```text
一条 NVLink "Link" = 两条方向相反的 Sub-link（全双工）
       ┌──────────────── Link ────────────────┐
GPU A  │  Sub-link (TX) ───────────────►  GPU B │
       │  Sub-link (RX) ◄───────────────        │
       └────────────────────────────────────────┘

每条 Sub-link = 若干条 Lane（差分信号对），由高速 SerDes 驱动
```

与 PCIe 的关键差别：PCIe 一个端口连一个对端（树形）；**NVLink 一块 GPU 有十几条独立 Link，可以同时连多个对端**，天然适合构建 mesh 或经 NVSwitch 的全互联。

协议同样分三层（协议层 / 数据链路层 / 物理层），关键机制包括：基于 **flit（flow control unit）** 的传输、**信用流控**（链路内部无丢包）、**CRC + 重放**保证可靠，以及**地址共享与一致性**——NVLink 支持把对端 GPU 显存映射进统一虚拟地址空间（UVA），并在协议层传递一致性/原子操作消息，使多 GPU 能像访问本地内存一样访问对端显存。

### 2.2 各代演进

带宽提升来自三个杠杆：**单 lane 速率提升（SerDes 升级 + NRZ→PAM4）、每 GPU link 数量增加、引入 NVSwitch 实现全互联。**

| 代际 | 首发架构 | 单 link 双向带宽 | 每 GPU link 数 | 每 GPU 总双向带宽 | 信令 (per lane) |
|------|----------|------------------|----------------|--------------------|------|
| NVLink 1.0 | Pascal (P100) | 40 GB/s | 4 | 160 GB/s | NRZ ~20 Gbps |
| NVLink 2.0 | Volta (V100) | 50 GB/s | 6 | 300 GB/s | NRZ ~25 Gbps |
| NVLink 3.0 | Ampere (A100) | 50 GB/s | 12 | 600 GB/s | NRZ ~50 Gbps |
| NVLink 4.0 | Hopper (H100) | 50 GB/s | 18 | 900 GB/s | PAM4 ~106 Gbps |
| NVLink 5.0 | Blackwell (B200) | ~100 GB/s | 18 | 1800 GB/s | PAM4 ~212 Gbps |

> 口径说明：上表是 NVIDIA 习惯的**双向带宽**。H100 的 900 GB/s = 18 link × 50 GB/s（双向），
> 折合单向约 450 GB/s——已是 PCIe 5.0 x16 单向的 7 倍。
> 单 link 怎么来的：H100 每条 link 用 2 对差分线，每对 ~106.25 Gbps PAM4，
> 裸速率单向 ≈ 2 × 106.25 / 8 ≈ 26.5 GB/s，扣掉编码与协议开销后标称 **25 GB/s 单向 / 50 GB/s 双向**。
> 注意每代的「每 link 差分对数」也在变，所以不能只看 per-lane 速率倒推。

**NVLink-C2C（Chip-to-Chip）** 则用于 Grace Hopper（CPU+GPU）与 Blackwell 双 die 之间，提供高带宽、缓存一致的芯片间互联（如 Grace↔Hopper 达 900 GB/s 双向），让 CPU 内存与 GPU 显存共享统一地址空间。

### 2.3 软件视角

- **UVA + Peer Access**：`cudaDeviceCanAccessPeer()` 判断两 GPU 能否 P2P，`cudaDeviceEnablePeerAccess()` 打开后，一块 GPU 的 kernel 可直接解引用另一块 GPU 显存的指针，底层走 NVLink。
- **`cudaMemcpyPeer` / `cudaMemcpyPeerAsync`**：GPU 间拷贝，有 NVLink 则自动走 NVLink。
- **`nvidia-smi topo -m`**：查看 GPU 间连接类型（`NV#` 表示经 N 条 NVLink，`SYS` 表示经 PCIe+CPU，`PHB/PXB` 表示经 PCIe 桥/Switch）。

## 三、NVSwitch：节点内全互联与在网规约

NVLink 解决了“两块 GPU 之间怎么高速连”，但 GPU 数量增加后，靠两两直连无法保证“任意一对都满带宽”：8 块 GPU 两两直连需要 C(8,2) = 28 对链路，link 根本不够分，而且会出现带宽不均衡、中转 GPU 拥塞、扩展性差的问题。

解决思路和网络界一样：**引入交换机**。

### 3.1 非阻塞交叉开关

NVSwitch 本质是一颗专用的 NVLink 交换 ASIC，核心是**交叉开关（crossbar）**加上路由与缓冲逻辑：

```text
            NVLink 端口 (一颗 NVSwitch 有几十个)
   in0 ─┐  ┌─ in1 ─┐  ┌─ in2 ─┐        ...
        │  │       │  │       │
   ┌────▼──▼───────▼──▼───────▼────────────┐
   │            Crossbar 交叉开关           │  任意输入可转发到任意输出
   │      + 路由表 / 缓冲 / 仲裁逻辑         │  内部带宽 ≥ 所有端口带宽之和
   └────┬──┬───────┬──┬───────┬────────────┘
        │  │       │  │       │
  out0 ─┘  └─ out1 ─┘  └─ out2 ─┘        ...
```

- **非阻塞**：内部交换容量不低于所有端口带宽之和，任意端口同时满速收发都不会内部拥塞。
- **基于目的地址路由**：每个包带目标 GPU 标识，查路由表决定转出端口。
- **低延迟**：纯硬件一跳转发，百纳秒量级。
- **缓冲与仲裁**：多输入争同一输出时靠输出端口仲裁与缓冲排队，配合信用流控保证无丢包。

### 3.2 节点级拓扑

```text
 GPU0  GPU1  GPU2  GPU3  GPU4  GPU5  GPU6  GPU7
  │││   │││   │││   │││   │││   │││   │││   │││   ← 每块 GPU 的 18 条 NVLink
  │││   │││   │││   │││   │││   │││   │││   │││     被"打散"分配到多颗 NVSwitch
 ┌┴┴┴───┴┴┴───┴┴┴───┴┴┴───┴┴┴───┴┴┴───┴┴┴───┴┴┴┐
 │   NVSwitch 0   NVSwitch 1  ...  NVSwitch K   │
 └───────────────────────────────────────────────┘
```

每块 GPU 的 link 分散接到多颗 NVSwitch，既避免单点瓶颈，也使任意两块 GPU 之间存在多条并行路径。结果是**任意一对 GPU 之间都能达到该 GPU 的全部 NVLink 带宽**（H100 约 900 GB/s 双向），且与是哪两块 GPU 无关——不存在"某两块卡之间特别慢"的短板链路，这就是“全互联、无阻塞、带宽均衡”。

> 需要说明的是：这个 900 GB/s 是**单对 GPU 独占通信时**的上限，衡量的是"没有短板路径"。
> 8 卡同时全互联通信时，每块 GPU 的 18 条 link 要分给多个对端，单对实际拿到的带宽自然低于该上限；
> 非阻塞保证的是交换结构内部不额外制造拥塞，而不是凭空放大总带宽。

正因为没有短板链路，NCCL 的 Ring/Tree 算法跑在这张网上时不会被某一段拖慢——这是 DGX/HGX H100 单机 8 卡能在 AllReduce 中几乎打满带宽的原因。

演进路线：

| 代际 | 配套 GPU | 关键变化 |
|------|----------|----------|
| NVSwitch 1.0 | Volta (V100, DGX-2) | 首次实现 16 GPU 全互联（板内） |
| NVSwitch 2.0 | Ampere (A100) | 配合 NVLink 3.0，8 GPU HGX 全互联 |
| NVSwitch 3.0 | Hopper (H100) | 配合 NVLink 4.0；引入 SHARP 在网计算；可外置组网 |
| NVSwitch 4.0+ | Blackwell (GB200) | 机柜级 NVL72：72 GPU 单一 NVLink 域 |

**NVL72** 把一个机柜内 72 块 GPU 连成单一 NVLink 域，对软件呈现为“一个巨大的 GPU 池”，跨服务器也能用 NVLink 带宽与一致性语义，极大缩小了传统“机内 NVLink、机间 InfiniBand”的两段式延迟差异。

### 3.3 SHARP：把规约下沉到交换芯片

传统 AllReduce 中，数据要在 GPU 之间来回搬运、累加，链路上跑了很多份数据。NVSwitch 3.0 引入的 **SHARP（NVLS / NVLink SHARP）** 改变了这一点：

```text
       GPU0   GPU1   GPU2   GPU3
         \      |     |      /        各 GPU 把数据发给 NVSwitch
           ▼    ▼     ▼     ▼
      ┌──────────────────────────┐
      │  NVSwitch 内置规约引擎     │  在交换芯片里直接做 sum/max 等规约
      │  result = Σ(GPU0..GPU3)   │
      └──────────────────────────┘
           │    │     │     │        规约结果一次性广播回所有 GPU
           ▼    ▼     ▼     ▼
       GPU0   GPU1   GPU2   GPU3
```

收益是减少数据搬运量、降低延迟，并把规约从 GPU 的 SM 和带宽预算里释放出来。InfiniBand 交换机侧也有对应的 SHARP，思想一致：**让网络不只是搬运数据，还参与计算。**

运维上，NVSwitch 由 **Fabric Manager** 服务管理（初始化交换结构、配置路由、健康检查）。多 GPU 节点若 FM 未启动，NVLink 全互联可能不可用，NCCL 会退回 PCIe。NVLink 误码/降速可用 `nvidia-smi nvlink -e` 或 DCGM 监控捕获——误码率升高会显著拖慢集合通信。

## 四、AMD Infinity Fabric：一套互联，多种用途

NVIDIA 的体系里 PCIe、NVLink、NVSwitch 是分立技术；AMD 则用**一套统一的 Infinity Fabric（IF）** 覆盖从片内到片间的所有互联。它逻辑上分两个平面：

- **SDF（Scalable Data Fabric）**：数据搬运——内存请求、缓存一致流量、DMA，连接 CPU 核/CCX、内存控制器、IO die、GPU 计算单元。
- **SCF（Scalable Control Fabric）**：控制面——电源管理、时钟、安全、配置、QoS、遥测。

物理层按距离分两种：

| 物理层 | 用途 | 特点 |
|--------|------|------|
| **IFOP**（On-Package） | 封装内 die 间（chiplet 之间） | 短距、超高带宽、低功耗 |
| **IFIS**（Inter-Socket） | 封装/socket 之间 | 长距，**复用 PCIe SerDes 物理通道** |

IFIS 与 PCIe 复用同一组 PHY/lane，这就是 AMD 平台上著名的 “xGMI / PCIe lane 复用”：同样的引脚，插 GPU 走 PCIe，连另一颗 CPU 走 IF。在 GPU 互联语境下，AMD 把 GPU↔GPU 的链路称为 **xGMI**，角色等价于 NVLink；8 卡 Instinct 平台（OAM 基板）多用 GPU 间直连的 fully-connected mesh，而非独立交换芯片。

**缓存一致性是 Infinity Fabric 的灵魂**，也是它与 PCIe 的本质区别。SDF 上每个代理访问内存时，IF 维护一致性目录/协议（MOESI 类模型），保证一个代理写的数据对其他代理可见，无需软件显式 flush。跨 die、跨 socket 访问呈现 NUMA 特性。正因如此，CPU 和 GPU 才能共享统一地址空间——这是 MI300A 架构的基础：

```text
        MI300A 封装内（简化）
   ┌──────────────────────────────────────┐
   │  Zen4 CPU die   ┌─────────────────┐   │
   │       │         │  CDNA3 GPU die  │   │
   │       └──IFOP──┤ (多个 XCD)       │   │
   │                 └─────────────────┘   │
   │        共享 Infinity Cache + HBM3      │  CPU/GPU 统一寻址，一致访问
   └──────────────────────────────────────┘
```

MI300X 是纯 GPU 版本：8 个 **XCD（Accelerator Complex Die，计算 die）** 堆叠在 4 个 IOD 之上、通过 IFOP 在封装内互联，配 192GB HBM3，对软件呈现为单一 GPU；MI300A 则在同一封装内集成 CPU + GPU + HBM，**消除了 PCIe 上的 H2D/D2H 拷贝**。软件栈是 ROCm + **RCCL**（对标 NCCL，API 高度兼容），跨节点仍配合 RoCE 或 InfiniBand。

> 注意术语代差：MI200/MI250X 的计算 die 叫 **GCD**（Graphics Compute Die，每卡 2 个），
> MI300 系列改称 **XCD**。看旧资料时容易混。

| 功能 | NVIDIA | AMD |
|------|--------|-----|
| GPU↔GPU 高速直连 | NVLink | xGMI |
| 节点内全互联交换 | NVSwitch | xGMI fully-connected mesh |
| CPU↔GPU 一致互联 | NVLink-C2C（Grace Hopper） | Infinity Fabric（MI300A 统一内存） |
| chiplet 片内缝合 | NV-HBI / 片内互联 | IFOP |
| 集合通信库 | NCCL | RCCL |

## 五、RDMA 与 InfiniBand：跨节点的高速通道

当训练规模超出单机，GPU 之间的数据就要跨服务器流动。传统 TCP/IP 走内核协议栈，有拷贝、上下文切换、CPU 参与，延迟高、抖动大。

```text
传统 TCP/IP 收一个包：
  网卡 → 内核 sk_buff → 协议栈处理 → 拷贝到用户缓冲 → 应用
  （多次内存拷贝 + 内核态/用户态切换 + CPU 全程参与）

RDMA 收一个包：
  对端网卡 → 直接 DMA 写入本端预注册的用户内存 → 完成
  （零拷贝 + 内核旁路 + CPU 几乎不参与）
```

RDMA 的三大支柱：**Kernel Bypass（内核旁路）**、**Zero Copy（零拷贝）**、**CPU Offload（传输、可靠性、分片重组由网卡硬件完成）**。收益是微秒级延迟、接近线速的带宽、极低的 CPU 占用。

### 5.1 InfiniBand 的架构特点

```text
┌──────────┐   IB 链路    ┌──────────────┐   IB 链路   ┌──────────┐
│  Server  │─────────────│  IB Switch   │────────────│  Server  │
│  + HCA   │             │ (Subnet 内转发)│            │  + HCA   │
└──────────┘             └──────────────┘             └──────────┘
                                │
                         ┌──────┴───────┐
                         │ Subnet Manager│  集中式：分配 LID、计算路由表
                         │     (SM)      │
                         └───────────────┘
```

IB Switch 基于 **LID** 做二层硬件直通转发，延迟极低。**Subnet Manager** 是 IB 的“大脑”——发现拓扑、分配 LID、计算下发转发表，这种集中式管理是 IB 与以太网（分布式自学习）的根本架构差异。链路层用信用流控，因此 **IB 网络天生无损**。

速率代际（网卡通常按 4 lane 聚合）：FDR 56G、EDR 100G、HDR 200G、NDR 400G、XDR 800G。

### 5.2 编程模型：QP、CQ、verbs

```text
        应用 (用户态)
          │  ① post 一个 WR (Work Request)
          ▼
   ┌──────────────┐         ┌──────────────┐
   │  Send Queue  │         │ Receive Queue│   ← QP = SQ + RQ
   │    (SQ)      │         │    (RQ)      │
   └──────┬───────┘         └──────┬───────┘
          │ 网卡硬件读取 WQE 执行    │
          ▼                         ▼
   ┌────────────────────────────────────────┐
   │            HCA / RNIC 硬件              │  做 DMA、分片、可靠传输
   └────────────────────────────────────────┘
          │ ② 完成后写一个 CQE
          ▼
   ┌──────────────┐
   │ Completion Q │  应用 poll CQ 得知操作完成
   └──────────────┘
```

- **QP（Queue Pair）**：一对 SQ + RQ，是 RDMA 通信端点，类比 TCP 的 socket。
- **WR/WQE**：应用把“要做什么”描述成工作请求 post 到队列，网卡异步执行。
- **CQ/CQE**：完成后网卡写完成事件，应用 poll 或事件通知得知——**整个 data path 无系统调用**。
- **doorbell**：post 后写网卡的 doorbell 寄存器（MMIO 写）通知硬件有活干了。

### 5.3 内存注册：地址翻译与安全的基础

RDMA 让网卡直接读写用户内存，必须解决地址翻译与安全。应用调用 `ibv_reg_mr()` 注册一段缓冲区时发生三件事：

1. **锁页（pin）**：把内存锁定在物理内存中，禁止换出/迁移（否则 DMA 时物理地址会变）。
2. **建立地址映射**：网卡记录虚拟地址与物理地址（或 IOVA）的映射。
3. **生成 key**：`lkey`（本地校验）与 `rkey`（交给对端；对端做 RDMA 读写本端内存时必须带正确的 rkey）——这是 RDMA 的安全边界。

> 要让远端直接写本地内存，必须先把 (地址, rkey) 通过带外通道告诉对方。**如果注册的不是 CPU 内存而是 GPU 显存，网卡就能直接 DMA 读写显存——这正是 GPUDirect RDMA 的接入点。**

### 5.4 单边 vs 双边、以及 RC/UC/UD

| 类别 | 操作 | 远端 CPU 参与 | 说明 |
|------|------|----------------|------|
| **双边** | SEND / RECV | 是 | 接收方须先 post RECV，需双方配合 |
| **单边** | RDMA WRITE / READ / Atomic | **否** | 直接读写远端已注册内存，需事先知道 (地址, rkey) |

**RDMA WRITE** 是单边操作里最快的——类似 PCIe 的 Posted Write，可流水线打满带宽，NCCL 大量使用；**RDMA READ** 受 round-trip 限制。这与 PCIe“写优于读”一脉相承。

传输服务类型：

| 类型 | 可靠 | 连接 | 支持单边 | 用途 |
|------|------|------|----------|------|
| **RC**（Reliable Connected） | 是 | 一对一 | 是 | 主流，NCCL/MPI 常用 |
| **UC**（Unreliable Connected） | 否 | 一对一 | 部分 | 少用 |
| **UD**（Unreliable Datagram） | 否 | 无连接 | 否 | 大规模、连接数受限场景 |

RC 最常用，但每对端点要建一条连接，**连接数随规模平方增长（N² 扩展性问题）**，大集群会消耗大量 QP 资源与网卡缓存。AWS EFA 的 SRD 正是为解决这个问题而设计的。

在 AI 集群里，大规模常用 Fat-Tree 等无阻塞拓扑，并采用 **rail-optimized 设计**：每台 8 卡服务器的 8 块网卡分别接入 8 个独立网络平面（rail），让同号 GPU 走同一 rail，减少跨 rail 拥塞。

## 六、RoCE：在以太网上跑 RDMA，代价是自己造无损网络

InfiniBand 性能强，但要专用 HCA、交换机和布线，成本高、与现有以太网生态割裂。**RoCE** 把 IB 的传输层与 RDMA 语义原封不动搬到以太网上。

### 6.1 v1 与 v2

**RoCE v1** 用专门的 EtherType（0x8915）直接把 IB 传输层包封进以太网帧，只能在同一二层广播域内通信，不能 IP 路由，现实中已被取代。**RoCE v2** 把 IB 传输层包封进 **UDP（固定目的端口 4791）** 再封进 IP：

```text
┌──────────┬─────────┬─────────┬──────────────┬──────────┬──────────┐
│ Ethernet │  IP     │  UDP    │  IB Transport│  RDMA    │ Payload  │
│ Header   │ Header  │ dport=  │  Header (BTH)│  Payload │ ICRC/FCS │
│          │         │  4791   │              │          │          │
└──────────┴─────────┴─────────┴──────────────┴──────────┴──────────┘
```

可路由，适配标准三层数据中心网络（Clos/Spine-Leaf）。用 UDP 而非 TCP 是因为 RDMA 自己在 IB 传输层做可靠性；UDP 只是个“信封”，其源端口还被用来做 ECMP 多路径哈希。现在说 RoCE 基本都指 v2。

### 6.2 核心难题：以太网会丢包，而 RDMA 受不了

以太网默认允许丢包、靠上层重传兜底；但 RoCE 的 RC 最初采用 **go-back-N** 重传——丢一个包要从该包开始整窗重传，对吞吐是灾难性打击。大规模 incast（多打一）场景下交换机缓冲极易溢出。所以 RoCE 必须把以太网改造成**无损以太网**，靠三件套：

**PFC（Priority Flow Control, 802.1Qbb）** 是逐跳背压。普通 PAUSE 帧会把整条链路全停掉，PFC 改进为按优先级暂停：

```text
   上游交换机                     下游交换机
   ┌─────────┐                   ┌─────────┐
   │  发送    │ ───── 数据 ────►  │ 入口缓冲 │
   │          │                   │  快满了！ │
   │  暂停发送 │ ◄── PFC PAUSE ─── │ 发 PAUSE │  针对某个优先级队列
   │ 该优先级  │                   │          │
   └─────────┘                   └─────────┘
```

数据在链路上被逐跳“憋住”而不是被丢弃。但 PFC 有严重副作用：**拥塞扩散 / Head-of-Line 阻塞**（PAUSE 逐跳向上游传播，一个热点会连累无关流量）、**PFC 风暴 / 死锁**（配置不当会让 PAUSE 帧互相触发，整个网络僵住）。所以不能单靠 PFC。

**ECN** 让交换机在不丢包的前提下告知端点拥塞：队列超阈值时在 IP 头标记 CE（Congestion Experienced），接收端网卡收到后生成 **CNP** 回送发送端。**DCQCN** 则把这个信号变成网卡硬件里的速率调节算法：收到 CNP 就快速乘性降速，持续无 CNP 则逐步恢复。

| 机制 | 层次 | 作用 | 比喻 |
|------|------|------|------|
| **PFC** | 链路级（逐跳） | 缓冲将满时背压，保证不丢包 | 堵在门口先憋住 |
| **ECN** | 端到端信号 | 拥塞时标记包，触发 CNP | 亮起"前方拥堵"指示灯 |
| **DCQCN** | 端到端控速 | 据 CNP 在源头调速率 | 司机看到灯就减速 |

理想状态是 DCQCN 在源头把速率调好、队列几乎不积压，PFC 极少触发——**调参目标是让 ECN 先于 PFC 生效**。

多路径靠变化 UDP 源端口 + ECMP，但传统 RoCE 一条 RC 连接的流会被哈希到单条路径，**单流无法用多路径**——这是 RoCE 的固有限制，也是 SRD 要解决的痛点。

### 6.3 RoCE vs InfiniBand

| 维度 | InfiniBand | RoCE v2 |
|------|------------|---------|
| 网络介质 | 专用 IB 交换机/HCA/线缆 | 标准以太网交换机 + RNIC |
| 无损机制 | 链路层信用流控（天生无损） | 需 PFC+ECN+DCQCN 人工调优 |
| 管理 | 集中式 Subnet Manager | 分布式以太网 |
| 可路由 | IB 子网内 | 是（IP 路由，跨子网） |
| 成本/生态 | 高，专用生态 | 低，复用以太网生态 |
| 调优难度 | 相对省心 | **较高**（阈值、缓冲、死锁风险） |

> 一句话：RoCE 用“成熟廉价的以太网生态”换“自己搞定无损网络的调优复杂度”。调好了能接近 IB；调不好（PFC 风暴、丢包）性能塌方。

## 七、AWS EFA 与 SRD：拥抱有损与乱序的第三条路

在超大规模多租户云环境里，IB 太封闭，而 RoCE 的 PFC 逐跳背压会引发大范围连锁反应、运维风险极高。AWS 因此自研了 **EFA（Elastic Fabric Adapter）** 网络接口与 **SRD（Scalable Reliable Datagram）** 传输协议。

EFA 提供 **OS-bypass** 的用户态网络访问，挂载在 P 系列（P4d/P5 等）、部分 G 系列与 HPC 实例上，通过 **libfabric** 暴露给上层。它**不是** InfiniBand，也**不是**标准 RoCE。

### 7.1 SRD 的三个反向选择

**多路径喷洒（multi-path spraying）**：

```text
                    ┌──► path 1 ──┐
   发送端 ── 数据包 ─┼──► path 2 ──┼──► 接收端
   (同一条流的包     ├──► path 3 ──┤   (网卡负责重新排序)
    被打散到多条路径) └──► path N ──┘
```

SRD 把同一条流的包主动喷洒到大量不同路径上，**单流也能用满多路径带宽**，天然避开热点链路，极大降低拥塞和尾延迟。代价是包会乱序到达。

**拥抱乱序**：IB/RoCE 的 RC 要求硬件保证按序交付，一旦丢/乱就要 go-back-N 整窗重传。SRD 只保证“可靠送达”，不保证“按序”，排序责任上移到网卡与上层（libfabric / aws-ofi-nccl）。对 NCCL 这类集合通信，很多场景并不要求底层严格保序，省掉保序开销是划算的。

**端到端快速重传 + 网卡内拥塞控制**：SRD 在网卡硬件里做 ACK 与**选择性重传**（只重传真正丢失的包），拥塞控制算法基于 RTT 等信号在网卡内运行，**不依赖 PFC**——因此 AWS 网络不需要无损以太网，规避了 PFC 死锁风险。全部在 Nitro 卡硬件中执行。

| 维度 | IB RC | RoCE v2 | EFA / SRD |
|------|-------|---------|-----------|
| 保序 | 硬件保序 | 硬件保序 | **不保序**（上层重组） |
| 可靠性 | 是 | 是 | 是（选择性重传） |
| 多路径单流 | 否 | 否 | **是（多路径喷洒）** |
| 无损依赖 | 链路信用流控 | **依赖 PFC** | **不依赖 PFC** |
| 重传 | 较重 | go-back-N | 选择性重传 |
| 拥塞控制 | IB CC | DCQCN | 网卡内自研 CC |

### 7.2 软件栈

```text
┌──────────────────────────────────────────────┐
│  应用：PyTorch / Megatron                       │
├──────────────────────────────────────────────┤
│  NCCL                                          │
├──────────────────────────────────────────────┤
│  aws-ofi-nccl  （NCCL 网络插件 → libfabric）     │
├──────────────────────────────────────────────┤
│  libfabric  （OFI 抽象：efa provider）          │
├──────────────────────────────────────────────┤
│  EFA 内核驱动 + Nitro 硬件（SRD 协议）           │
└──────────────────────────────────────────────┘
```

没有 **aws-ofi-nccl** 这个插件，NCCL 默认只会用内置的 IB/socket 后端，**无法用上 EFA 的 SRD**。部署要点：EFA 实例需在同一个 cluster 策略的 Placement Group 内才有最佳网络性能；安装 EFA installer（含内核驱动、libfabric、aws-ofi-nccl）后，用 `NCCL_DEBUG=INFO` 确认日志里出现 `NET/OFI` 与 EFA provider 字样。

| 技术 | 哲学 |
|------|------|
| **InfiniBand** | 全栈专用、集中管理、链路天生无损——极致性能，但封闭、贵 |
| **RoCE** | 复用以太网，靠 PFC/ECN/DCQCN 人工造无损——灵活省钱，但调优难、有死锁风险 |
| **EFA / SRD** | 拥抱有损与乱序，多路径喷洒 + 选择性重传 + 网卡内拥塞控制——为超大规模云而生 |

> EFA 的本质创新：**把“保证网络无损/有序”的负担，从网络转移到端侧的传输协议上**，用海量路径的统计复用换取确定性的低尾延迟。

## 八、GPUDirect：把 CPU 从数据通路上摘掉

前面讲的都是“管道”。GPUDirect 是一组让数据**绕开 CPU 与系统内存中转**的技术。

没有它时，GPU 与网卡之间传数据要经 CPU 内存中转：

```text
【传统路径】
   GPU 显存 ─① cudaMemcpy D2H→ CPU 系统内存(bounce buffer) ─② 网卡 DMA→ 网卡 → 网络
   数据在 PCIe 上走了两趟，占用 CPU 内存带宽，增加延迟

【GPUDirect RDMA 路径】
   GPU 显存 ──（网卡直接 DMA 读写显存）──► 网卡 → 网络
   一趟 PCIe，不经 CPU 内存，CPU 几乎不参与
```

物理基础就是前面 PCIe 一节讲的 **BAR/MMIO**：GPU 通过 BAR（尤其 Resizable BAR）把显存映射到 PCIe 物理地址空间，一旦有了总线地址，任何能发 PCIe Memory TLP 的设备就能直接读写显存。

家族成员：

- **GPUDirect P2P**：节点内 GPU↔GPU 直接互访显存。有 NVLink/NVSwitch 则走 NVLink（最快），否则走 PCIe P2P（受 ACS 设置约束）。API 是 `cudaDeviceCanAccessPeer()` / `cudaDeviceEnablePeerAccess()`。
- **GPUDirect RDMA**：跨节点核心。内核模块 **`nvidia-peermem`** 向 RDMA 子系统注册回调，使 `ibv_reg_mr()` 能注册 **GPU 显存**而非仅 CPU 内存；之后 RDMA WRITE/READ 的地址直接指向显存。
- **GPUDirect Storage（GDS）**：让 NVMe/存储网络直接把数据 DMA 进显存（通过 `cuFile` API），把“存储 → CPU 内存 → 显存”的两趟变成一趟，对数据集加载与 checkpoint 读写显著降延迟。

把全栈串起来，看一次跨机发送到底发生了什么：

```text
① NCCL 决定从 节点A-GPU0 把数据发到 节点B-GPU0
② 数据已在 GPU0 显存，且该显存已通过 nvidia-peermem 注册给网卡
③ NCCL 经网络插件 post 一个 RDMA WRITE WQE，
   源地址 = 本地 GPU 显存地址，目的 = 对端 GPU 显存地址 + rkey
④ 本地网卡读 WQE → 直接 DMA 读 GPU0 显存（GPUDirect RDMA）
⑤ 网卡切包，经网络（IB / RoCE 无损以太网 / EFA-SRD）送到对端网卡
⑥ 对端网卡收到 → 直接 DMA 写入 节点B-GPU0 显存
⑦ 网卡写 CQE，NCCL poll 到完成
   —— 全程数据没碰过任何一端的 CPU 系统内存
```

**启用条件与排错**：任何一环不满足都会“静默回退”到经 CPU 的慢路径——带宽掉一截却不报错。

| 条件 | 说明 |
|------|------|
| 内核模块 | 加载 `nvidia-peermem`（或 DMABUF 路径） |
| PCIe 拓扑 | GPU 与网卡最好在同一 PCIe Switch / 同一 NUMA，跨 socket 会很慢甚至不可用 |
| ACS 设置 | ACS 重定向会强制 P2P 绕到 Root Complex，需按需关闭 |
| Resizable BAR | 大块显存 P2P 需要 BAR 覆盖足够地址空间 |
| 驱动/固件 | GPU 驱动与网卡固件版本需匹配 |

排错工具：`nvidia-smi topo -m` 看 GPU↔NIC 连接（`PIX/PXB` 同 Switch 较好，`SYS` 跨 NUMA 差）；`NCCL_DEBUG=INFO` 日志里确认 GDR 已启用。

## 九、NCCL：跑在这些道路上的调度大脑

**NCCL** 把分布式训练需要的集合操作翻译成具体数据流，自动探测拓扑、选择算法、选最优链路，并用 GPU kernel 高效执行。它是 PyTorch/Megatron 等框架分布式训练的事实标准通信后端。

| 操作 | 语义 | 训练中的用途 |
|------|------|--------------|
| **AllReduce** | 所有 GPU 各有一份，规约后结果分发给所有 GPU | **数据并行梯度同步**（最核心） |
| **AllGather** | 收集各片，每个 GPU 都拥有全部拼接结果 | ZeRO/FSDP 收集参数分片 |
| **ReduceScatter** | 规约后按片分散到各 GPU | ZeRO 梯度分片 |
| **Broadcast** | 一个 GPU 的数据复制到所有 GPU | 初始化广播权重 |
| **All-to-All** | 每个 GPU 给每个 GPU 发不同数据 | MoE 专家路由、序列并行 |

> 关键恒等式：**AllReduce = ReduceScatter + AllGather**。NCCL 正是这样实现高效 AllReduce 的。

### 9.1 Ring AllReduce 与带宽最优性

把 N 块 GPU 在逻辑上连成环，每块只和左右邻居通信，数据切成 N 份，分两阶段：**ReduceScatter（N-1 步，每步把自己负责的片发给下一个、收上一个的片并累加）**，然后 **AllGather（再传 N-1 步，把每片的最终结果传给所有人）**。

```text
设总数据量 S，GPU 数 N。每块 GPU 在整个过程中：
  发送数据量 = 2 × S × (N-1)/N  ≈ 2S （当 N 大时趋于常数）
  即每块 GPU 收发的数据量与 N 几乎无关 → "带宽最优"
```

缺点是**步数 = 2(N-1)，延迟随 N 线性增长**。所以 NCCL 引入 **Tree** 算法：把 GPU 组织成树，规约沿树向上汇聚到根再向下广播，延迟从 O(N) 降到 **O(log N)**。实际用的是**双二叉树**——构造两棵互补的二叉树，让每个节点在一棵树里是中间节点、在另一棵里是叶子，从而同时利用上下行带宽。

```text
Ring：延迟 O(N)，带宽最优 → 适合大消息、中等规模
Tree：延迟 O(log N)      → 适合小消息、大规模
NVLS/CollNet：把规约下沉到 NVSwitch 或 IB 交换机的 SHARP 引擎
```

NCCL 会根据消息大小和规模自动在三者之间选择，也可用 `NCCL_ALGO` 强制。

### 9.2 拓扑感知与 channel

NCCL 的“智能”很大程度来自启动时的拓扑探测：

```text
① 探测系统拓扑：通过 NVML/系统信息发现 GPU、NVLink/NVSwitch 连接、PCIe 树、网卡、NUMA，
   构建带"链路类型与带宽"的图（NVLink > PCIe P2P > 经 CPU > 网络）
② 计算最优 channel：在图上搜索多条 Ring/Tree 路径，尽量走高带宽链路，
   避开跨 NUMA、跨 rail 的瓶颈
③ 分层：节点内用 NVLink/NVSwitch（GPUDirect P2P），节点间用 IB/RoCE/EFA（GPUDirect RDMA）
   典型做法：节点内 ReduceScatter → 跨节点 AllReduce → 节点内 AllGather
```

**channel** 是并行的通信流水线：每个 channel 是一个 ring 或一棵 tree 的实例，绑定一组 SM 与一份链路带宽。多 channel 并行才能把多条 NVLink、多个网卡的带宽聚合打满（H100 有 18 条 NVLink，需要多个 channel 才用得满）。NCCL 用 GPU kernel 同时做“通信 + 规约”，数据流过时就地累加，避免额外拷贝与 kernel 启动。

运行时分工：节点内 NCCL kernel 直接经 NVLink/NVSwitch 读写对端显存；跨节点由 CPU 上的 **proxy 线程**驱动网络插件 post RDMA 操作，但数据本身经 GPUDirect RDMA 直达显存——CPU 只发命令不碰数据。**网络插件机制**让 NCCL 能支持 IB、RoCE，也能通过 aws-ofi-nccl 接到 libfabric/EFA。

### 9.3 一次数据并行 step

```text
① 各 GPU 前向 + 反向，算出本地梯度
② NCCL AllReduce 对所有 GPU 的梯度求和求平均
     - 节点内：NVLink/NVSwitch 上做 ReduceScatter
     - 节点间：IB/RoCE/EFA 上做跨节点规约（可能用 SHARP/NVLS 在网规约）
     - 节点内：AllGather 把结果铺回每块 GPU
③ 各 GPU 用同步后的梯度更新参数
④ 进入下一 step
通信与反向计算尽量重叠（梯度桶 bucketing + 异步），把通信时间藏到计算后面
```

### 9.4 常用调优旋钮

| 环境变量 | 作用 |
|----------|------|
| `NCCL_DEBUG=INFO` | 打印拓扑、算法、GDR 是否启用（排错第一步） |
| `NCCL_ALGO` | 强制 Ring / Tree / CollNet / NVLS |
| `NCCL_PROTO` | 选择 LL/LL128/Simple（延迟 vs 带宽权衡） |
| `NCCL_P2P_LEVEL` | 控制 P2P 使用范围 |
| `NCCL_NET_GDR_LEVEL` | 控制 GPUDirect RDMA 启用条件 |
| `NCCL_MIN/MAX_NCHANNELS` | 调 channel 数以聚合带宽 |
| `NCCL_IB_HCA` / `NCCL_SOCKET_IFNAME` | 指定使用的网卡 |
| `NCCL_TOPO_DUMP_FILE` | 导出探测到的拓扑 XML 供检查 |

## 十、把全景拼起来

一台 P5 实例（8×H100）参与大规模训练时，完整图景是这样的：

```text
节点内（单机 8 卡）:
   GPU ──NVLink 4.0──► NVSwitch ──► GPU   （GPUDirect P2P，900 GB/s 级）

节点间（跨实例）:
   GPU 显存 ──(GPUDirect RDMA)──► EFA 网卡
        ══ SRD 多路径喷洒 over 以太网底座 ══►
   EFA 网卡 ──(GPUDirect RDMA)──► GPU 显存

调度层:
   NCCL（拓扑感知）+ aws-ofi-nccl + libfabric
   - 节点内 ReduceScatter 走 NVLink/NVSwitch
   - 跨节点 AllReduce 走 EFA/SRD
   - 节点内 AllGather 铺回
```

每一层各自的角色：

- **PCIe** 提供可寻址性（BAR），让别的设备能打到显存；同时承载控制面。
- **NVLink / NVSwitch / Infinity Fabric** 提供节点内高速通道与全互联，并能在交换芯片里做规约。
- **RDMA（IB / RoCE / EFA）** 提供跨节点通道，三者代表三种关于“无损与有序”的工程哲学。
- **GPUDirect** 是把各层焊接成端到端通路的黏合剂——没有它，再快的管道两端也要被 CPU 内存拷贝拖累。
- **NCCL** 在上层做拓扑感知的算法选择与调度，把这一切变成一次 AllReduce 调用。

理解这条链路的价值在于：当训练跑不满带宽时，你能沿着它逐层定位——是 ACS 挡住了 P2P，是 Fabric Manager 没起来导致退回 PCIe，是 GDR 静默回退到了 bounce buffer，是 PFC 阈值配错引发拥塞扩散，还是 channel 数不够没能聚合多链路带宽。

---

## 常见问题

### 为什么 GPU 之间的通信会成为大模型训练的瓶颈？

一块 H100 的算力高达数百 TFLOPS，但单卡显存只有几十到上百 GB，训练千亿/万亿参数模型必须把模型和数据切分到成百上千张卡上协同计算。理想重叠情况下，训练一步的时间约等于 max(计算时间, 通信时间)——当梯度同步（AllReduce）跟不上计算速度时，GPU 就会「算完等数据」，MFU（算力利用率）骤降。

### 为什么高性能数据通路都偏爱「写」而不是「读」？

因为 PCIe 的 Memory Write 是 Posted（投递型）事务，发送方发出后立即认为完成、不等应答，因此可以流水线化、打满带宽；而 Memory Read 是 Non-Posted，必须等对端返回 Completion TLP，受 round-trip 延迟和「飞行中读请求数量」限制。RDMA 同理：RDMA WRITE 是单边投递型操作，吞吐远优于 RDMA READ，所以 NCCL 等集合通信库大量使用 WRITE。

### NVLink 和 PCIe 是替代关系吗？

不是，两者并存、各司其职。GPU 仍然通过 PCIe 被 CPU 枚举和管理、与网卡/存储交互（控制面与部分数据面）；GPU 之间的大流量数据走 NVLink。带宽差距很大：PCIe 5.0 x16 单向约 64 GB/s，而 H100 的 NVLink 4.0 单向约 450 GB/s，是前者的 7 倍。

### InfiniBand、RoCE 和 AWS EFA 三者的根本差异是什么？

是三种不同的工程哲学。InfiniBand 全栈专用、集中式 Subnet Manager 管理、链路层信用流控天生无损，性能极致但封闭且贵。RoCE 复用以太网生态，靠 PFC + ECN + DCQCN 人工把以太网改造成无损网络，成本低但调优难、有 PFC 死锁风险。EFA/SRD 则反向选择：不追求网络无损，拥抱乱序，用多路径喷洒加选择性重传和网卡内拥塞控制，把可靠性负担从网络转移到端侧传输协议。

### GPUDirect RDMA 没生效会有什么表现？怎么排查？

最危险的是它会「静默回退」到经 CPU bounce buffer 的慢路径——带宽掉一截却不报错。排查要点：确认加载了 nvidia-peermem（或 DMABUF 路径）内核模块；用 nvidia-smi topo -m 检查 GPU 与网卡是否在同一 PCIe Switch / 同一 NUMA（PIX/PXB 较好，SYS 跨 NUMA 很差）；检查 PCIe ACS 重定向是否需要关闭、Resizable BAR 是否够大、驱动与网卡固件版本是否匹配。最后必须用 NCCL_DEBUG=INFO 看日志确认 GDR 真的启用了。

### Ring AllReduce 为什么被称为「带宽最优」？它有什么缺点？

设总数据量 S、GPU 数 N，Ring AllReduce 分 ReduceScatter 和 AllGather 两阶段各 N-1 步，每块 GPU 全程发送的数据量约为 2S(N-1)/N，当 N 较大时趋于常数 2S——即每卡通信量与 GPU 数几乎无关，因此带宽最优。缺点是总步数为 2(N-1)，延迟随 N 线性增长，所以在几百上千卡规模下传小消息很吃亏。NCCL 因此引入延迟为 O(log N) 的双二叉树算法，并按消息大小和规模自动在 Ring / Tree / NVLS 之间选择。


---

## 参考资料

- [NVIDIA NVLink and NVSwitch](https://www.nvidia.com/en-us/data-center/nvlink/) — NVIDIA
- [NVIDIA Collective Communications Library (NCCL) Documentation](https://docs.nvidia.com/deeplearning/nccl/user-guide/docs/index.html) — NVIDIA Docs
- [GPUDirect RDMA Documentation](https://docs.nvidia.com/cuda/gpudirect-rdma/index.html) — NVIDIA Docs
- [PCI Express Base Specification](https://pcisig.com/specifications) — PCI-SIG
- [A Cloud-Optimized Transport Protocol for Elastic and Scalable HPC (SRD)](https://ieeexplore.ieee.org/document/9167399) — IEEE Micro
- [Elastic Fabric Adapter (EFA) User Guide](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/efa.html) — AWS Documentation
- [AMD Instinct MI300 Series Architecture](https://www.amd.com/en/products/accelerators/instinct/mi300.html) — AMD
- [aws-ofi-nccl: NCCL network plugin for libfabric](https://github.com/aws/aws-ofi-nccl) — GitHub
