HiHuo
首页
博客
手册
工具
关于
首页
博客
手册
工具
关于
  • AI 基础设施深度教程

    • AI Infra 深度教程
    • GPU容器化

      • 01-GPU 架构基础
      • NVIDIA 容器运行时
      • GPU 共享与隔离
      • GPU 监控与调试
    • Kubernetes GPU调度

      • Device Plugin 机制深度解析
      • GPU 调度器实现
      • 拓扑感知调度
      • 弹性 GPU 调度
    • AI训练平台

      • 分布式训练框架
      • 训练任务调度
      • 模型存储与管理
      • 实验管理
      • 超参数优化
    • 推理服务

      • 推理引擎原理
      • 模型服务框架
      • 动态批处理
      • 推理优化技术
      • 多模型服务
    • 异构计算

      • 05-异构计算
      • 异构计算概述
      • GPU 虚拟化技术
      • NPU 与专用 AI 芯片
      • 设备拓扑感知调度
      • 算力池化与弹性调度
    • AI工作流引擎

      • 06-AI工作流引擎
      • AI 工作流引擎概述
      • Kubeflow Pipelines 深度实践
      • 03-Argo Workflows 深度实践
      • 04-数据版本管理
      • 05-实验跟踪与模型注册
    • MLOps实践

      • 07-MLOps实践
      • 01-MLOps 成熟度模型
      • 02-数据集工程
      • 03-Feature Store 特征存储
      • 04-模型评测体系
      • 05-模型安全与治理
    • AIOps实践

      • 08-AIOps实践
      • 01-AIOps概述与架构
      • 02-异常检测算法
      • 03-根因分析与告警聚合
      • 04-智能运维决策
      • 05-AIOps平台实战
    • 面试专题

      • 09-面试专题
      • 01-AI基础设施核心面试题
      • 02-大模型面试题
      • 03-系统设计面试题
    • CUDA编程与算子开发

      • 10-CUDA 编程与算子开发
      • 01-CUDA编程模型与内存层次
      • 02-高性能 Kernel 开发实战
      • 03-Tensor Core 与矩阵运算
      • 04-算子融合与优化技术
      • 05-Triton 编程入门
    • 通信与网络底层

      • 11-通信与网络底层
      • 01-NCCL 源码深度解析
      • 02-AllReduce 算法实现
      • 03-RDMA与InfiniBand原理
      • 04-网络拓扑与通信优化
      • 05-大规模集群网络架构
    • 框架源码解析

      • 12-框架源码解析
      • 01-PyTorch分布式源码解析
      • 02-DeepSpeed源码深度解析
      • 03-Megatron-LM源码解析
      • 04-vLLM推理引擎源码解析
      • 05-HuggingFace Transformers源码解析
    • 编译优化与图优化

      • 13-编译优化与图优化
      • 01-深度学习编译器概述
      • 02-TorchDynamo与torch.compile
      • 03-XLA编译器深度解析
      • 04-算子融合与Kernel优化
      • 05-自动调度与代码生成

04-网络拓扑与通信优化

概述

大规模分布式训练的性能高度依赖于网络拓扑设计和通信优化。本章深入讲解数据中心网络拓扑、GPU集群互联架构、以及NCCL的拓扑感知优化策略。

GPU 服务器互联架构

单机多卡拓扑

┌─────────────────────────────────────────────────────────────────────────┐
│                    单机 8 卡 GPU 服务器拓扑                              │
├─────────────────────────────────────────────────────────────────────────┤
│                                                                          │
│  DGX A100 / HGX A100 架构                                               │
│  ═══════════════════════                                                 │
│                                                                          │
│            ┌─────────────────────────────────────────────┐              │
│            │               NVSwitch x 6                   │              │
│            │         (每个NVSwitch 900GB/s)              │              │
│            └────┬────┬────┬────┬────┬────┬────┬────┬────┘              │
│                 │    │    │    │    │    │    │    │                    │
│         ┌──────┼────┼────┼────┼────┼────┼────┼────┼──────┐             │
│         │      │    │    │    │    │    │    │    │      │             │
│      ┌──▼──┐┌──▼──┐┌──▼──┐┌──▼──┐┌──▼──┐┌──▼──┐┌──▼──┐┌──▼──┐          │
│      │GPU0 ││GPU1 ││GPU2 ││GPU3 ││GPU4 ││GPU5 ││GPU6 ││GPU7 │          │
│      │ A100││ A100││ A100││ A100││ A100││ A100││ A100││ A100│          │
│      │80GB ││80GB ││80GB ││80GB ││80GB ││80GB ││80GB ││80GB │          │
│      └──┬──┘└──┬──┘└──┬──┘└──┬──┘└──┬──┘└──┬──┘└──┬──┘└──┬──┘          │
│         │      │      │      │      │      │      │      │              │
│         │      │      │      │      │      │      │      │              │
│      ┌──┴──────┴──────┴──────┴──────┴──────┴──────┴──────┴──┐          │
│      │                    PCIe Switch                        │          │
│      │                   (Gen4 x16)                         │          │
│      └──┬──────┬──────┬──────┬──────┬──────┬──────┬──────┬──┘          │
│         │      │      │      │      │      │      │      │              │
│      ┌──▼──┐┌──▼──┐┌──▼──┐┌──▼──┐┌──▼──┐┌──▼──┐┌──▼──┐┌──▼──┐          │
│      │NIC0 ││NIC1 ││NIC2 ││NIC3 ││NIC4 ││NIC5 ││NIC6 ││NIC7 │          │
│      │200G ││200G ││200G ││200G ││200G ││200G ││200G ││200G │          │
│      │ IB  ││ IB  ││ IB  ││ IB  ││ IB  ││ IB  ││ IB  ││ IB  │          │
│      └─────┘└─────┘└─────┘└─────┘└─────┘└─────┘└─────┘└─────┘          │
│                                                                          │
│  带宽特性:                                                               │
│  • GPU-GPU (NVLink): 600 GB/s 双向                                       │
│  • GPU-GPU (通过NVSwitch): 任意两卡全速互联                               │
│  • GPU-NIC (PCIe): 32 GB/s (Gen4 x16)                                   │
│  • 总网络带宽: 8 x 200Gbps = 1.6Tbps                                     │
│                                                                          │
├─────────────────────────────────────────────────────────────────────────┤
│                                                                          │
│  PCIe 拓扑示例 (nvidia-smi topo -m)                                      │
│  ══════════════════════════════════                                      │
│                                                                          │
│        GPU0  GPU1  GPU2  GPU3  GPU4  GPU5  GPU6  GPU7  NIC0  NIC1       │
│  GPU0   X    NV12  NV12  NV12  NV12  NV12  NV12  NV12  SYS   SYS        │
│  GPU1  NV12   X    NV12  NV12  NV12  NV12  NV12  NV12  SYS   SYS        │
│  GPU2  NV12  NV12   X    NV12  NV12  NV12  NV12  NV12  SYS   SYS        │
│  GPU3  NV12  NV12  NV12   X    NV12  NV12  NV12  NV12  SYS   PHB        │
│  GPU4  NV12  NV12  NV12  NV12   X    NV12  NV12  NV12  SYS   SYS        │
│  GPU5  NV12  NV12  NV12  NV12  NV12   X    NV12  NV12  SYS   SYS        │
│  GPU6  NV12  NV12  NV12  NV12  NV12  NV12   X    NV12  PHB   SYS        │
│  GPU7  NV12  NV12  NV12  NV12  NV12  NV12  NV12   X    SYS   SYS        │
│                                                                          │
│  图例:                                                                   │
│  • X    = 自身                                                           │
│  • NV12 = NVLink (12条链路)                                              │
│  • PHB  = PCIe Host Bridge (同一PCIe switch)                            │
│  • SYS  = 跨NUMA/CPU                                                     │
│                                                                          │
└─────────────────────────────────────────────────────────────────────────┘

PCIe 拓扑影响

┌─────────────────────────────────────────────────────────────────────────┐
│                      PCIe 拓扑对性能的影响                               │
├─────────────────────────────────────────────────────────────────────────┤
│                                                                          │
│  理想拓扑: GPU 和 NIC 在同一 PCIe Switch                                 │
│  ════════════════════════════════════════                                │
│                                                                          │
│                    ┌──────────────┐                                      │
│                    │  CPU Socket  │                                      │
│                    └──────┬───────┘                                      │
│                           │                                              │
│                    ┌──────▼───────┐                                      │
│                    │ PCIe Root    │                                      │
│                    │ Complex      │                                      │
│                    └──────┬───────┘                                      │
│                           │                                              │
│              ┌────────────┼────────────┐                                │
│              │            │            │                                │
│       ┌──────▼──────┐    ...    ┌──────▼──────┐                        │
│       │ PCIe Switch │           │ PCIe Switch │                        │
│       └──┬──────┬───┘           └──┬──────┬───┘                        │
│          │      │                  │      │                            │
│       ┌──▼──┐┌──▼──┐           ┌──▼──┐┌──▼──┐                         │
│       │GPU0 ││NIC0 │           │GPU4 ││NIC4 │                         │
│       └─────┘└─────┘           └─────┘└─────┘                         │
│                                                                          │
│       GPU0 ↔ NIC0: PHB (同一Switch, 最优)                               │
│       GPU0 ↔ NIC4: SYS (跨Switch, 性能下降)                             │
│                                                                          │
├─────────────────────────────────────────────────────────────────────────┤
│                                                                          │
│  不同路径的带宽/延迟对比                                                 │
│  ════════════════════════                                                │
│                                                                          │
│  ┌──────────────────┬──────────────┬──────────────┬───────────────┐    │
│  │     连接类型      │    带宽      │    延迟      │   适用场景     │    │
│  ├──────────────────┼──────────────┼──────────────┼───────────────┤    │
│  │ NVLink (直连)    │ 600 GB/s    │ ~1 μs       │ GPU间通信     │    │
│  │ NVSwitch (任意)  │ 600 GB/s    │ ~1-2 μs     │ GPU间通信     │    │
│  │ PCIe (同Switch)  │ 32 GB/s     │ ~2-3 μs     │ GPU↔NIC      │    │
│  │ PCIe (跨Switch)  │ 32 GB/s     │ ~5-10 μs    │ GPU↔NIC      │    │
│  │ PCIe (跨NUMA)    │ 25 GB/s     │ ~10-20 μs   │ GPU↔NIC      │    │
│  │ IB 网络          │ 25 GB/s     │ ~1-2 μs     │ 节点间通信    │    │
│  └──────────────────┴──────────────┴──────────────┴───────────────┘    │
│                                                                          │
│  NCCL 拓扑感知:                                                          │
│  • 自动检测 GPU-NIC 亲和性                                               │
│  • 优先使用同一 PCIe switch 下的 NIC                                     │
│  • 避免跨 NUMA 的数据传输                                                │
│                                                                          │
└─────────────────────────────────────────────────────────────────────────┘

数据中心网络拓扑

Fat-Tree 拓扑

┌─────────────────────────────────────────────────────────────────────────┐
│                        Fat-Tree 网络拓扑                                 │
├─────────────────────────────────────────────────────────────────────────┤
│                                                                          │
│                    ┌───────────────────────────────────┐                │
│                    │           Core Layer              │                │
│                    │                                   │                │
│     ┌──────┐  ┌──────┐  ┌──────┐  ┌──────┐  ┌──────┐  │                │
│     │Core0 │  │Core1 │  │Core2 │  │Core3 │  │Core4 │  │                │
│     │Switch│  │Switch│  │Switch│  │Switch│  │Switch│  │                │
│     └───┬──┘  └───┬──┘  └───┬──┘  └───┬──┘  └───┬──┘  │                │
│         │        │        │        │        │        │                  │
│         └────┬───┴────┬───┴────┬───┴────┬───┴────┘   │                  │
│              │        │        │        │            │                  │
│    ┌─────────┴────────┴────────┴────────┴─────────┐  │                  │
│    │                 Spine Layer                   │  │                  │
│    │                                               │  │                  │
│    │ ┌──────┐  ┌──────┐  ┌──────┐  ┌──────┐      │  │                  │
│    │ │Spine0│  │Spine1│  │Spine2│  │Spine3│      │  │                  │
│    │ │Switch│  │Switch│  │Switch│  │Switch│      │  │                  │
│    │ └───┬──┘  └───┬──┘  └───┬──┘  └───┬──┘      │  │                  │
│    │     │        │        │        │            │  │                  │
│    │     └────────┴────────┴────────┴────────┐   │  │                  │
│    └─────────────────────────────────────────┼───┘  │                  │
│                                              │      │                  │
│    ┌─────────────────────────────────────────┼──────┘                  │
│    │                 Leaf Layer              │                          │
│    │                                         │                          │
│    │ ┌──────┐  ┌──────┐  ┌──────┐  ┌──────┐ │                          │
│    │ │Leaf0 │  │Leaf1 │  │Leaf2 │  │Leaf3 │ │                          │
│    │ │Switch│  │Switch│  │Switch│  │Switch│ │                          │
│    │ └───┬──┘  └───┬──┘  └───┬──┘  └───┬──┘ │                          │
│    │     │        │        │        │      │                          │
│    └─────┼────────┼────────┼────────┼──────┘                          │
│          │        │        │        │                                  │
│     ┌────┴────┐┌──┴───┐┌───┴───┐┌───┴───┐                             │
│     │Rack 0   ││Rack 1││Rack 2 ││Rack 3 │                             │
│     │8x GPU   ││8x GPU││8x GPU ││8x GPU │                             │
│     │Server   ││Server││Server ││Server │                             │
│     └─────────┘└──────┘└───────┘└───────┘                             │
│                                                                          │
│  Fat-Tree 特点:                                                          │
│  • 等分带宽: 任意两点间带宽相等                                          │
│  • 多路径: 多条等价路径, 支持负载均衡                                    │
│  • 可扩展: 三层结构易于扩展                                              │
│                                                                          │
│  带宽计算 (假设 400Gbps IB):                                             │
│  • 同一Leaf下: 全速 (400Gbps)                                            │
│  • 跨Leaf: 取决于上联收敛比                                              │
│  • 收敛比 1:1 = 无阻塞                                                   │
│                                                                          │
└─────────────────────────────────────────────────────────────────────────┘

Rail-Optimized 拓扑

┌─────────────────────────────────────────────────────────────────────────┐
│                    Rail-Optimized 网络拓扑                               │
├─────────────────────────────────────────────────────────────────────────┤
│                                                                          │
│  传统拓扑问题:                                                           │
│  • 8卡服务器的8个NIC分布在多个Leaf Switch                                │
│  • AllReduce需要跨Switch通信, 增加延迟                                   │
│                                                                          │
│  Rail-Optimized 设计:                                                    │
│  • 相同位置的GPU/NIC连接到同一组交换机 (Rail)                            │
│  • GPU0 of all nodes → Rail 0 switches                                  │
│  • GPU1 of all nodes → Rail 1 switches                                  │
│                                                                          │
│           Rail 0        Rail 1        Rail 2        Rail 3              │
│         ┌───────┐     ┌───────┐     ┌───────┐     ┌───────┐            │
│         │Spine0 │     │Spine1 │     │Spine2 │     │Spine3 │            │
│         └───┬───┘     └───┬───┘     └───┬───┘     └───┬───┘            │
│             │             │             │             │                  │
│         ┌───┴───┐     ┌───┴───┐     ┌───┴───┐     ┌───┴───┐            │
│         │Leaf0  │     │Leaf1  │     │Leaf2  │     │Leaf3  │            │
│         └───┬───┘     └───┬───┘     └───┬───┘     └───┬───┘            │
│             │             │             │             │                  │
│   ┌─────────┼─────────────┼─────────────┼─────────────┼─────────┐      │
│   │         │             │             │             │         │      │
│   │   ┌─────▼─────┐ ┌─────▼─────┐ ┌─────▼─────┐ ┌─────▼─────┐  │      │
│   │   │   NIC0    │ │   NIC1    │ │   NIC2    │ │   NIC3    │  │      │
│   │   └─────┬─────┘ └─────┬─────┘ └─────┬─────┘ └─────┬─────┘  │      │
│   │         │             │             │             │         │      │
│   │   ┌─────▼─────┐ ┌─────▼─────┐ ┌─────▼─────┐ ┌─────▼─────┐  │      │
│   │   │   GPU0    │ │   GPU1    │ │   GPU2    │ │   GPU3    │  │      │
│   │   └───────────┘ └───────────┘ └───────────┘ └───────────┘  │      │
│   │                         Server 0                            │      │
│   └─────────────────────────────────────────────────────────────┘      │
│                                                                          │
│   ┌─────────┼─────────────┼─────────────┼─────────────┼─────────┐      │
│   │         │             │             │             │         │      │
│   │   ┌─────▼─────┐ ┌─────▼─────┐ ┌─────▼─────┐ ┌─────▼─────┐  │      │
│   │   │   NIC0    │ │   NIC1    │ │   NIC2    │ │   NIC3    │  │      │
│   │   └─────┬─────┘ └─────┬─────┘ └─────┬─────┘ └─────┬─────┘  │      │
│   │         │             │             │             │         │      │
│   │   ┌─────▼─────┐ ┌─────▼─────┐ ┌─────▼─────┐ ┌─────▼─────┐  │      │
│   │   │   GPU0    │ │   GPU1    │ │   GPU2    │ │   GPU3    │  │      │
│   │   └───────────┘ └───────────┘ └───────────┘ └───────────┘  │      │
│   │                         Server 1                            │      │
│   └─────────────────────────────────────────────────────────────┘      │
│                                                                          │
│  优势:                                                                   │
│  • 相同Rail内的GPU直接通信,无需跨Rail                                    │
│  • AllReduce可以在Rail内完成大部分通信                                   │
│  • 减少网络拥塞和跳数                                                    │
│                                                                          │
└─────────────────────────────────────────────────────────────────────────┘

Dragonfly 拓扑

┌─────────────────────────────────────────────────────────────────────────┐
│                       Dragonfly 网络拓扑                                 │
├─────────────────────────────────────────────────────────────────────────┤
│                                                                          │
│  适用于超大规模集群 (万卡以上)                                           │
│                                                                          │
│  结构层次:                                                               │
│  1. Group (组): 多个节点组成一个全互联的组                               │
│  2. 组间连接: 各组之间通过少量链路互联                                   │
│                                                                          │
│      ┌──────────────────────────────────────────────────────────┐       │
│      │                        Group 0                           │       │
│      │    ┌────────────────────────────────────────────┐       │       │
│      │    │    ┌───┐  ┌───┐  ┌───┐  ┌───┐  ┌───┐     │       │       │
│      │    │    │N0 │══│N1 │══│N2 │══│N3 │══│N4 │     │       │       │
│      │    │    └─┬─┘  └─┬─┘  └─┬─┘  └─┬─┘  └─┬─┘     │       │       │
│      │    │      │      │      │      │      │        │       │       │
│      │    │      └──────┴──────┴──────┴──────┘        │       │       │
│      │    │              组内全互联                    │       │       │
│      │    └────────────────────────────────────────────┘       │       │
│      └───────────────────────┬──────────────────────────────────┘       │
│                              │                                          │
│              ┌───────────────┼───────────────┐                         │
│              │               │               │ 组间链路                 │
│              ▼               ▼               ▼                         │
│      ┌───────────┐   ┌───────────┐   ┌───────────┐                    │
│      │  Group 1  │   │  Group 2  │   │  Group 3  │                    │
│      │           │   │           │   │           │                    │
│      │  [nodes]  │   │  [nodes]  │   │  [nodes]  │                    │
│      └───────────┘   └───────────┘   └───────────┘                    │
│                                                                          │
│  路由策略:                                                               │
│  • 组内: 直接通信 (1跳)                                                  │
│  • 组间: 最多3跳 (源组 → 中间组 → 目标组)                                │
│                                                                          │
│  适用场景:                                                               │
│  • 超大规模HPC集群                                                       │
│  • 需要极高扩展性                                                        │
│  • 可接受一定的延迟增加                                                  │
│                                                                          │
└─────────────────────────────────────────────────────────────────────────┘

NCCL 拓扑发现

拓扑检测机制

// NCCL 拓扑发现流程
// 文件: nccl/src/graph/topo.cc

// ============================================================
// 步骤1: 检测 GPU 信息
// ============================================================

ncclResult_t ncclTopoGetSystem(struct ncclTopoSystem** topoSystem) {
    struct ncclTopoSystem* system;

    // 分配系统拓扑结构
    NCCLCHECK(ncclCalloc(&system, 1));

    // 检测CPU信息
    NCCLCHECK(ncclTopoGetCpuInfo(system));

    // 检测GPU信息
    int nGpus;
    cudaGetDeviceCount(&nGpus);

    for (int g = 0; g < nGpus; g++) {
        struct ncclTopoNode* gpu;
        NCCLCHECK(ncclTopoAddGpu(system, g, &gpu));

        // 获取GPU的PCIe路径
        char busId[NVML_DEVICE_PCI_BUS_ID_BUFFER_SIZE];
        cudaDeviceGetPCIBusId(busId, sizeof(busId), g);

        // 解析PCIe拓扑
        NCCLCHECK(ncclTopoConnectPcie(system, gpu, busId));
    }

    // 检测NIC信息
    NCCLCHECK(ncclTopoGetNetInfo(system));

    // 检测NVLink连接
    NCCLCHECK(ncclTopoGetNvLinks(system));

    *topoSystem = system;
    return ncclSuccess;
}

// ============================================================
// 步骤2: 检测 NVLink 连接
// ============================================================

ncclResult_t ncclTopoGetNvLinks(struct ncclTopoSystem* system) {
    for (int g = 0; g < system->nGpus; g++) {
        cudaSetDevice(g);

        // 检查与其他GPU的NVLink连接
        for (int p = 0; p < system->nGpus; p++) {
            if (g == p) continue;

            int canAccessPeer;
            cudaDeviceCanAccessPeer(&canAccessPeer, g, p);

            if (canAccessPeer) {
                // 获取NVLink数量
                int nvlinkCount = 0;

                // 使用NVML获取详细NVLink信息
                nvmlDevice_t device;
                nvmlDeviceGetHandleByIndex(g, &device);

                for (int link = 0; link < NVML_NVLINK_MAX_LINKS; link++) {
                    nvmlPciInfo_t pciInfo;
                    nvmlReturn_t ret = nvmlDeviceGetNvLinkRemotePciInfo(
                        device, link, &pciInfo);

                    if (ret == NVML_SUCCESS) {
                        // 检查是否连接到目标GPU
                        if (isPeerGpu(pciInfo, p)) {
                            nvlinkCount++;
                        }
                    }
                }

                // 记录NVLink连接
                struct ncclTopoLink* link;
                NCCLCHECK(ncclTopoConnectGpus(system, g, p, nvlinkCount, &link));
                link->type = LINK_NVL;
                link->bw = nvlinkCount * NVLINK_BW;  // 每条NVLink ~50GB/s
            }
        }
    }
    return ncclSuccess;
}

// ============================================================
// 步骤3: 检测 PCIe 拓扑
// ============================================================

ncclResult_t ncclTopoConnectPcie(struct ncclTopoSystem* system,
                                 struct ncclTopoNode* node,
                                 const char* busId) {
    // 解析PCIe BDF (Bus:Device.Function)
    int domain, bus, dev, func;
    sscanf(busId, "%x:%x:%x.%x", &domain, &bus, &dev, &func);

    // 遍历sysfs获取PCIe拓扑
    char path[PATH_MAX];
    snprintf(path, sizeof(path),
             "/sys/bus/pci/devices/%s", busId);

    // 找到PCIe switch (通过symbolic link)
    char link[PATH_MAX];
    readlink(path, link, sizeof(link));

    // 解析拓扑层次
    // 典型路径: /sys/devices/pci0000:00/0000:00:1f.0/0000:3b:00.0/...
    //           root complex      switch         device

    // 构建拓扑树
    struct ncclTopoNode* parent = system->root;
    char* token = strtok(link, "/");

    while (token != NULL) {
        if (strncmp(token, "pci", 3) == 0 ||
            strncmp(token, "0000:", 5) == 0) {
            // 找到或创建PCIe节点
            struct ncclTopoNode* pcie;
            NCCLCHECK(ncclTopoGetPcieNode(system, token, &pcie));
            ncclTopoConnect(parent, pcie);
            parent = pcie;
        }
        token = strtok(NULL, "/");
    }

    ncclTopoConnect(parent, node);
    return ncclSuccess;
}

// ============================================================
// 步骤4: 检测 NIC 与 GPU 亲和性
// ============================================================

ncclResult_t ncclTopoGetNetInfo(struct ncclTopoSystem* system) {
    // 获取所有IB设备
    struct ibv_device** devList = ibv_get_device_list(&nDevs);

    for (int d = 0; d < nDevs; d++) {
        struct ncclTopoNode* nic;
        NCCLCHECK(ncclTopoAddNic(system, devList[d], &nic));

        // 获取NIC的PCIe位置
        const char* name = ibv_get_device_name(devList[d]);
        char busId[32];
        getIbDevicePcieBusId(name, busId);

        // 连接到PCIe拓扑
        NCCLCHECK(ncclTopoConnectPcie(system, nic, busId));

        // 计算与每个GPU的亲和性
        for (int g = 0; g < system->nGpus; g++) {
            int distance = ncclTopoDistance(system, nic, system->gpus[g]);
            nic->gpuAffinity[g] = distance;
        }
    }

    return ncclSuccess;
}

拓扑可视化

# 查看NCCL检测到的拓扑
export NCCL_DEBUG=INFO
export NCCL_DEBUG_SUBSYS=GRAPH

# 运行后输出示例:
# NCCL INFO Topology detection:
#   GPU 0: busId 0000:3b:00.0 nvlinks 12 p2p 8
#   GPU 1: busId 0000:86:00.0 nvlinks 12 p2p 8
#   ...
#   NET 0: ib0 port 1 pcieBusId 0000:3c:00.0 distance 1 (to GPU 0)
#   NET 1: ib1 port 1 pcieBusId 0000:87:00.0 distance 1 (to GPU 1)

# nvidia-smi 拓扑矩阵
nvidia-smi topo -m

# NVML API 获取详细信息
nvidia-smi nvlink -s
nvidia-smi nvlink -c

NCCL 图搜索算法

Channel 分配策略

// NCCL 图搜索和 Channel 分配
// 文件: nccl/src/graph/search.cc

// ============================================================
// Ring 图搜索
// ============================================================

ncclResult_t ncclTopoSearchRing(
    struct ncclTopoSystem* system,
    struct ncclTopoGraph* graph,
    int nChannels
) {
    int nGpus = system->nGpus;

    // 目标: 找到 nChannels 条不重叠的 Ring
    // 每条 Ring 经过所有 GPU 一次

    for (int c = 0; c < nChannels; c++) {
        struct ncclTopoRing* ring = &graph->rings[c];

        // 贪心搜索最优 Ring
        float bestScore = 0;
        int bestOrder[MAX_GPUS];

        // 尝试不同的起始点和方向
        for (int start = 0; start < nGpus; start++) {
            for (int dir = 0; dir < 2; dir++) {
                int order[MAX_GPUS];
                float score = evaluateRing(system, start, dir, order);

                if (score > bestScore) {
                    bestScore = score;
                    memcpy(bestOrder, order, nGpus * sizeof(int));
                }
            }
        }

        // 保存最优 Ring
        for (int i = 0; i < nGpus; i++) {
            ring->gpus[i] = bestOrder[i];
        }
        ring->nGpus = nGpus;
    }

    return ncclSuccess;
}

// Ring 评分函数
float evaluateRing(struct ncclTopoSystem* system,
                   int start, int dir, int* order) {
    float totalBw = 0;
    int visited[MAX_GPUS] = {0};

    int current = start;
    order[0] = current;
    visited[current] = 1;

    for (int i = 1; i < system->nGpus; i++) {
        // 找到下一个GPU (优先NVLink)
        int next = -1;
        float maxBw = 0;

        for (int g = 0; g < system->nGpus; g++) {
            if (visited[g]) continue;

            float bw = getGpuLinkBw(system, current, g);
            if (bw > maxBw) {
                maxBw = bw;
                next = g;
            }
        }

        if (next == -1) return 0;  // 无法形成Ring

        order[i] = next;
        visited[next] = 1;
        totalBw += maxBw;
        current = next;
    }

    // 加上最后一跳回到起点
    totalBw += getGpuLinkBw(system, current, start);

    return totalBw;
}

// ============================================================
// Tree 图搜索
// ============================================================

ncclResult_t ncclTopoSearchTree(
    struct ncclTopoSystem* system,
    struct ncclTopoGraph* graph,
    int nChannels
) {
    int nGpus = system->nGpus;

    // 构建二叉树
    // 目标: 最小化树高度, 最大化链路带宽

    for (int c = 0; c < nChannels; c++) {
        struct ncclTopoTree* tree = &graph->trees[c];

        // 选择root (通常是有最多NVLink的GPU)
        int root = selectTreeRoot(system, c);
        tree->root = root;

        // BFS构建树
        int parent[MAX_GPUS];
        int depth[MAX_GPUS];
        memset(parent, -1, sizeof(parent));
        memset(depth, 0, sizeof(depth));

        int queue[MAX_GPUS];
        int head = 0, tail = 0;

        queue[tail++] = root;
        parent[root] = root;
        depth[root] = 0;

        while (head < tail) {
            int current = queue[head++];
            int childCount = 0;

            // 最多2个子节点 (二叉树)
            for (int g = 0; g < nGpus && childCount < 2; g++) {
                if (parent[g] != -1) continue;

                // 优先选择NVLink连接的GPU
                if (hasNvLink(system, current, g)) {
                    parent[g] = current;
                    depth[g] = depth[current] + 1;
                    queue[tail++] = g;
                    childCount++;
                }
            }
        }

        // 保存树结构
        for (int g = 0; g < nGpus; g++) {
            tree->parent[g] = parent[g];
            tree->depth[g] = depth[g];
        }
    }

    return ncclSuccess;
}

// ============================================================
// Channel 复用和负载均衡
// ============================================================

ncclResult_t ncclTopoBalanceChannels(
    struct ncclTopoSystem* system,
    struct ncclTopoGraph* graph
) {
    // 确保每条链路在不同Channel中使用均衡

    int linkUsage[MAX_GPUS][MAX_GPUS] = {0};

    for (int c = 0; c < graph->nChannels; c++) {
        // 统计每条链路的使用次数
        for (int i = 0; i < system->nGpus; i++) {
            int from = graph->rings[c].gpus[i];
            int to = graph->rings[c].gpus[(i+1) % system->nGpus];
            linkUsage[from][to]++;
        }
    }

    // 如果某条链路过载,重新调整Channel顺序
    // ... 重新搜索或调整

    return ncclSuccess;
}

NIC 选择策略

// NCCL NIC 选择策略
// 文件: nccl/src/graph/connect.cc

ncclResult_t ncclTopoSelectNic(
    struct ncclTopoSystem* system,
    int gpu,
    int* selectedNic
) {
    // 策略1: 选择距离最近的NIC
    int bestNic = -1;
    int minDistance = INT_MAX;

    for (int n = 0; n < system->nNics; n++) {
        int distance = system->nics[n].gpuAffinity[gpu];

        if (distance < minDistance) {
            minDistance = distance;
            bestNic = n;
        }
    }

    // 策略2: 负载均衡 (如果有多个等距NIC)
    if (ncclParamNetNicBalance()) {
        int equalDistNics[MAX_NICS];
        int nEqual = 0;

        for (int n = 0; n < system->nNics; n++) {
            if (system->nics[n].gpuAffinity[gpu] == minDistance) {
                equalDistNics[nEqual++] = n;
            }
        }

        // Round-robin分配
        static int rrIndex = 0;
        bestNic = equalDistNics[rrIndex % nEqual];
        rrIndex++;
    }

    *selectedNic = bestNic;
    return ncclSuccess;
}

// 多NIC聚合配置
// export NCCL_IB_HCA=mlx5_0,mlx5_1,mlx5_2,mlx5_3

ncclResult_t ncclTopoSetupMultiNic(
    struct ncclComm* comm,
    struct ncclTopoSystem* system
) {
    // 解析环境变量指定的NIC列表
    char* env = getenv("NCCL_IB_HCA");
    if (env == NULL) {
        // 自动检测: 每个GPU使用亲和性最好的NIC
        for (int g = 0; g < comm->nGpus; g++) {
            ncclTopoSelectNic(system, g, &comm->nicPerGpu[g]);
        }
    } else {
        // 使用指定的NIC列表
        char* token = strtok(env, ",");
        int nicIdx = 0;

        while (token != NULL && nicIdx < comm->nGpus) {
            int nic = findNicByName(system, token);
            comm->nicPerGpu[nicIdx++] = nic;
            token = strtok(NULL, ",");
        }
    }

    return ncclSuccess;
}

通信模式优化

Hierarchical AllReduce

┌─────────────────────────────────────────────────────────────────────────┐
│                    Hierarchical AllReduce 优化                           │
├─────────────────────────────────────────────────────────────────────────┤
│                                                                          │
│  场景: 多节点训练,每节点8卡                                               │
│  问题: 节点间带宽远低于节点内 (IB: 200Gbps vs NVLink: 600GB/s)           │
│                                                                          │
│  策略: 分层AllReduce                                                     │
│  1. 节点内: 使用NVLink快速归约                                           │
│  2. 节点间: 只传输归约后的数据                                           │
│  3. 节点内: 广播最终结果                                                 │
│                                                                          │
│                         ┌─────────────┐                                 │
│                         │   Step 1    │                                 │
│                         │ 节点内Reduce│                                 │
│                         └──────┬──────┘                                 │
│                                │                                         │
│      Node 0                    │                    Node 1               │
│   ┌───────────────┐           │               ┌───────────────┐        │
│   │ G0 G1 G2 G3   │           │               │ G0 G1 G2 G3   │        │
│   │ G4 G5 G6 G7   │           │               │ G4 G5 G6 G7   │        │
│   │       │       │           │               │       │       │        │
│   │       ▼       │           │               │       ▼       │        │
│   │  Local Sum    │           │               │  Local Sum    │        │
│   │   (GPU0)      │           │               │   (GPU0)      │        │
│   └───────┬───────┘           │               └───────┬───────┘        │
│           │                   │                       │                 │
│           │                   │                       │                 │
│           │         ┌─────────▼─────────┐             │                 │
│           │         │      Step 2       │             │                 │
│           │         │  节点间AllReduce  │             │                 │
│           │         │   (仅GPU0参与)    │             │                 │
│           │         └─────────┬─────────┘             │                 │
│           │                   │                       │                 │
│           ▼                   │                       ▼                 │
│   ┌───────────────┐           │               ┌───────────────┐        │
│   │  Global Sum   │◄──────────┴───────────────│  Global Sum   │        │
│   │   (GPU0)      │         IB 网络           │   (GPU0)      │        │
│   └───────┬───────┘                           └───────┬───────┘        │
│           │                                           │                 │
│           │         ┌─────────────────┐               │                 │
│           │         │     Step 3      │               │                 │
│           │         │  节点内Broadcast│               │                 │
│           │         └─────────────────┘               │                 │
│           │                                           │                 │
│           ▼                                           ▼                 │
│   ┌───────────────┐                           ┌───────────────┐        │
│   │ G0 G1 G2 G3   │                           │ G0 G1 G2 G3   │        │
│   │ G4 G5 G6 G7   │                           │ G4 G5 G6 G7   │        │
│   │  All have     │                           │  All have     │        │
│   │  global sum   │                           │  global sum   │        │
│   └───────────────┘                           └───────────────┘        │
│                                                                          │
│  通信量分析 (假设每GPU数据量为D):                                        │
│  ────────────────────────────                                            │
│  传统Ring AllReduce:                                                     │
│    节点间通信量 = 2 * (N-1)/N * D * 8 ≈ 16D (8卡, 2节点)                 │
│                                                                          │
│  Hierarchical AllReduce:                                                 │
│    Step 1 (节点内): NVLink, 几乎免费                                     │
│    Step 2 (节点间): 2 * (N-1)/N * D ≈ D (仅1卡参与)                      │
│    Step 3 (节点内): NVLink, 几乎免费                                     │
│    节点间通信量 = D (减少16倍!)                                          │
│                                                                          │
└─────────────────────────────────────────────────────────────────────────┘

通信与计算重叠

# PyTorch DDP 通信与计算重叠

import torch
import torch.distributed as dist
from torch.nn.parallel import DistributedDataParallel as DDP

# ============================================================
# 梯度分桶 (Gradient Bucketing)
# ============================================================
"""
DDP 将梯度分成多个桶(bucket), 实现:
1. 减少通信次数 (小梯度合并)
2. 通信与计算重叠 (一个桶ready就开始AllReduce)
"""

model = DDP(
    model,
    device_ids=[local_rank],
    bucket_cap_mb=25,        # 每个桶大小 25MB
    gradient_as_bucket_view=True,  # 优化内存
)

# ============================================================
# 通信重叠时序
# ============================================================
"""
Forward:   [==========]
Backward:  [----Layer N----][----Layer N-1----][----Layer 1----]
AllReduce:      [Bucket K]      [Bucket K-1]       [Bucket 1]

关键: 反向传播从后往前, 后面层的梯度先ready
     一旦一个bucket满了,立即开始AllReduce
     与剩余反向传播并行执行
"""

# ============================================================
# NCCL 流水线
# ============================================================
"""
NCCL 内部也有流水线:

GPU 0: [Reduce-Scatter chunk 0][chunk 1][chunk 2]...
       [                AllGather                ]

多个chunk并行处理, 隐藏网络延迟
"""

# ============================================================
# 手动控制通信重叠 (高级用法)
# ============================================================
import torch.cuda.nccl as nccl

class OverlappedAllReduce:
    def __init__(self, model):
        self.model = model
        self.stream = torch.cuda.Stream()
        self.handles = []

    def backward_hook(self, grad):
        # 在单独stream中启动AllReduce
        with torch.cuda.stream(self.stream):
            handle = dist.all_reduce(grad, async_op=True)
            self.handles.append(handle)
        return grad

    def register_hooks(self):
        for param in self.model.parameters():
            param.register_hook(self.backward_hook)

    def sync(self):
        # 等待所有AllReduce完成
        for handle in self.handles:
            handle.wait()
        self.handles.clear()

# 使用
optimizer.zero_grad()
output = model(input)
loss = criterion(output, target)
loss.backward()  # AllReduce在后台执行
overlapped.sync()  # 同步
optimizer.step()

混合并行通信优化

# 混合并行 (DP + TP + PP) 的通信优化

"""
┌─────────────────────────────────────────────────────────────┐
│               混合并行通信模式                               │
├─────────────────────────────────────────────────────────────┤
│                                                              │
│  TP (Tensor Parallel):                                       │
│  • 通信类型: AllReduce (forward), AllReduce (backward)      │
│  • 通信频率: 每层每次forward/backward                        │
│  • 数据量: 小 (激活值)                                       │
│  • 要求: 超低延迟, 放在NVLink连接的GPU                       │
│                                                              │
│  PP (Pipeline Parallel):                                     │
│  • 通信类型: P2P Send/Recv                                   │
│  • 通信频率: 每个micro-batch的stage边界                      │
│  • 数据量: 中 (激活值)                                       │
│  • 要求: 中等延迟, 可跨节点                                  │
│                                                              │
│  DP (Data Parallel):                                         │
│  • 通信类型: AllReduce (梯度)                                │
│  • 通信频率: 每个step一次                                    │
│  • 数据量: 大 (所有参数的梯度)                               │
│  • 要求: 高带宽, 延迟不敏感                                  │
│                                                              │
└─────────────────────────────────────────────────────────────┘
"""

# ============================================================
# 通信组划分
# ============================================================

def setup_parallel_groups(
    world_size,
    tensor_parallel_size,
    pipeline_parallel_size,
    data_parallel_size
):
    """
    假设: world_size = 64
          tensor_parallel_size = 8
          pipeline_parallel_size = 4
          data_parallel_size = 2

    布局:
    - 64 GPUs 分成 2 个 DP 组
    - 每个 DP 组有 4 个 PP stage
    - 每个 PP stage 有 8 个 TP rank
    """

    rank = dist.get_rank()

    # TP组: 同一节点内的GPU (使用NVLink)
    tp_ranks = []
    for i in range(0, world_size, tensor_parallel_size):
        tp_ranks.append(list(range(i, i + tensor_parallel_size)))

    tp_group_idx = rank // tensor_parallel_size
    tp_group = dist.new_group(tp_ranks[tp_group_idx])

    # PP组: 不同stage之间
    pp_ranks = []
    num_pp_groups = world_size // pipeline_parallel_size
    for i in range(num_pp_groups):
        pp_rank_list = [i + j * num_pp_groups
                        for j in range(pipeline_parallel_size)]
        pp_ranks.append(pp_rank_list)

    pp_group_idx = rank % num_pp_groups
    pp_group = dist.new_group(pp_ranks[pp_group_idx])

    # DP组: 相同模型副本之间
    dp_ranks = []
    for i in range(0, world_size, world_size // data_parallel_size):
        dp_ranks.append(list(range(i, i + world_size // data_parallel_size)))

    dp_group = dist.new_group(dp_ranks[rank // (world_size // data_parallel_size)])

    return tp_group, pp_group, dp_group

# ============================================================
# 通信优先级
# ============================================================

"""
优先级排序 (根据对性能的影响):

1. TP 通信 - 在关键路径上, 最高优先级
   - 使用 NVLink
   - 最小化数据量 (只传必要的激活)

2. PP 通信 - 影响流水线效率
   - 使用 P2P, 可跨节点
   - 1F1B 调度最小化 bubble

3. DP 通信 - 可以与计算重叠
   - 使用 AllReduce, 跨节点
   - 梯度累积减少频率
   - 与backward重叠
"""

class HybridParallelModel:
    def __init__(self, model, tp_group, pp_group, dp_group):
        self.tp_group = tp_group
        self.pp_group = pp_group
        self.dp_group = dp_group

        # TP通信使用高优先级stream
        self.tp_stream = torch.cuda.Stream(priority=-1)  # 高优先级

        # DP通信使用低优先级stream, 与计算重叠
        self.dp_stream = torch.cuda.Stream(priority=0)   # 低优先级

    def tp_all_reduce(self, tensor):
        """Tensor Parallel AllReduce - 同步, 高优先级"""
        with torch.cuda.stream(self.tp_stream):
            dist.all_reduce(tensor, group=self.tp_group)
        self.tp_stream.synchronize()  # 必须等待完成
        return tensor

    def dp_all_reduce_async(self, tensor):
        """Data Parallel AllReduce - 异步, 可重叠"""
        with torch.cuda.stream(self.dp_stream):
            handle = dist.all_reduce(tensor, group=self.dp_group, async_op=True)
        return handle

    def pp_send_recv(self, tensor, peer_rank, is_send):
        """Pipeline Parallel P2P - 点对点通信"""
        if is_send:
            dist.send(tensor, peer_rank, group=self.pp_group)
        else:
            dist.recv(tensor, peer_rank, group=self.pp_group)

性能分析与调优

带宽利用率分析

# 网络带宽利用率分析工具

import torch
import time
import numpy as np

class BandwidthAnalyzer:
    def __init__(self, theoretical_bw_gbps):
        """
        theoretical_bw_gbps: 理论带宽 (Gbps)
        例如: 200 Gbps IB = 25 GB/s
        """
        self.theoretical_bw = theoretical_bw_gbps * 1e9 / 8  # 转换为 bytes/s

    def measure_allreduce_bw(self, tensor_size_mb, num_iters=100):
        """测量AllReduce实际带宽"""
        tensor = torch.randn(tensor_size_mb * 1024 * 1024 // 4).cuda()

        # 预热
        for _ in range(10):
            torch.distributed.all_reduce(tensor)
        torch.cuda.synchronize()

        # 计时
        start = time.time()
        for _ in range(num_iters):
            torch.distributed.all_reduce(tensor)
        torch.cuda.synchronize()
        elapsed = time.time() - start

        # 计算带宽
        # AllReduce通信量 = 2 * (n-1) / n * size ≈ 2 * size (n很大时)
        world_size = torch.distributed.get_world_size()
        comm_bytes = 2 * (world_size - 1) / world_size * tensor.numel() * 4
        total_bytes = comm_bytes * num_iters

        actual_bw = total_bytes / elapsed
        efficiency = actual_bw / self.theoretical_bw * 100

        return {
            'tensor_size_mb': tensor_size_mb,
            'actual_bw_gbps': actual_bw * 8 / 1e9,
            'theoretical_bw_gbps': self.theoretical_bw * 8 / 1e9,
            'efficiency': efficiency,
            'latency_ms': elapsed / num_iters * 1000,
        }

    def sweep_sizes(self, sizes_mb):
        """扫描不同大小的性能"""
        results = []
        for size in sizes_mb:
            result = self.measure_allreduce_bw(size)
            results.append(result)
            print(f"Size: {size}MB, BW: {result['actual_bw_gbps']:.2f} Gbps, "
                  f"Efficiency: {result['efficiency']:.1f}%")
        return results

# 使用示例
analyzer = BandwidthAnalyzer(theoretical_bw_gbps=200)
sizes = [1, 4, 16, 64, 256, 1024]
results = analyzer.sweep_sizes(sizes)

"""
典型结果:
Size: 1MB,    BW: 50 Gbps,  Efficiency: 25%   # 小消息效率低
Size: 4MB,    BW: 120 Gbps, Efficiency: 60%
Size: 16MB,   BW: 160 Gbps, Efficiency: 80%
Size: 64MB,   BW: 180 Gbps, Efficiency: 90%
Size: 256MB,  BW: 190 Gbps, Efficiency: 95%   # 大消息接近理论值
Size: 1024MB, BW: 195 Gbps, Efficiency: 97%
"""

NCCL 环境变量调优

# ============================================================
# NCCL 性能调优环境变量
# ============================================================

# 1. 算法选择
export NCCL_ALGO=Ring           # Ring, Tree, CollnetDirect, CollnetChain
export NCCL_PROTO=Simple        # Simple, LL, LL128

# 2. 网络配置
export NCCL_IB_HCA=mlx5_0,mlx5_1,mlx5_2,mlx5_3  # 指定IB设备
export NCCL_IB_GID_INDEX=3      # RoCE GID索引
export NCCL_IB_QPS_PER_CONNECTION=4  # 每连接QP数
export NCCL_IB_TC=106           # Traffic Class
export NCCL_IB_SL=0             # Service Level

# 3. 缓冲区大小
export NCCL_BUFFSIZE=8388608    # 8MB默认, 可增大
export NCCL_NTHREADS=512        # 线程数

# 4. 调试
export NCCL_DEBUG=INFO          # WARN, INFO, TRACE
export NCCL_DEBUG_SUBSYS=ALL    # INIT, COLL, P2P, NET, GRAPH

# 5. 拓扑优化
export NCCL_TOPO_FILE=/path/to/topo.xml  # 自定义拓扑
export NCCL_GRAPH_FILE=/path/to/graph.xml  # 自定义图

# 6. 其他
export NCCL_P2P_LEVEL=NVL       # 强制使用NVLink
export NCCL_SHM_DISABLE=0       # 启用共享内存
export NCCL_NET_GDR_LEVEL=5     # GPUDirect RDMA级别

常见性能问题排查

# ============================================================
# 性能问题排查清单
# ============================================================

# 1. 检查网络状态
ibstatus                        # IB端口状态
ibdiagnet -r                    # IB诊断

# 2. 检查PCIe拓扑
nvidia-smi topo -m              # GPU拓扑
lspci -tv                       # PCIe树

# 3. 检查NUMA亲和性
numactl -H                      # NUMA拓扑
cat /proc/self/numa_maps        # 内存分布

# 4. 运行NCCL测试
cd nccl-tests
./all_reduce_perf -b 1M -e 1G -f 2 -g 8

# 典型输出分析:
# #       size      time   algbw   busbw
# 1048576 (1M)   0.12ms   8.7GB  16.3GB    # 小消息
# 16777216 (16M)  0.9ms  18.6GB  34.9GB    # 中等消息
# 268435456(256M) 12ms   22.4GB  42.0GB    # 大消息 (应接近理论值)
#
# 如果大消息busbw远低于理论值 (如 <40GB/s for 200Gbps IB)
# 检查: IB配置, PCIe带宽, NIC数量

# 5. 检查潜在瓶颈
# PCIe瓶颈:
nvidia-smi dmon -s ut           # GPU PCIe利用率

# NIC瓶颈:
perfquery -x                    # IB统计

# CPU瓶颈:
top -H                          # 线程CPU使用
perf top                        # 热点函数

总结

网络拓扑选型

┌─────────────────────────────────────────────────────────────────────────┐
│                       网络拓扑选型指南                                   │
├─────────────────────────────────────────────────────────────────────────┤
│                                                                          │
│  集群规模         推荐拓扑              关键考量                         │
│  ─────────────────────────────────────────────────────────────          │
│  < 32 GPU        单层 Leaf             简单, 全速互联                    │
│  32-256 GPU      Fat-Tree 2层          标准选择, 1:1收敛比               │
│  256-4K GPU      Fat-Tree 3层 + Rail   Rail优化, 减少跨机通信            │
│  > 4K GPU        Dragonfly            超大规模, 成本效益                 │
│                                                                          │
│  单机GPU互联                                                             │
│  ─────────                                                               │
│  NVLink + NVSwitch:  最高性能, DGX/HGX系统标配                           │
│  PCIe P2P:           成本较低, 性能受限                                  │
│                                                                          │
│  节点间互联                                                              │
│  ────────                                                                │
│  InfiniBand HDR/NDR: 最高性能, AI训练首选                                │
│  RoCE v2:            成本较低, 需要仔细配置无损网络                       │
│  以太网:             不推荐用于大规模训练                                 │
│                                                                          │
└─────────────────────────────────────────────────────────────────────────┘

通信优化最佳实践

  1. 拓扑感知: 利用NCCL自动拓扑检测, 必要时手动配置
  2. NIC亲和性: 确保GPU和NIC在同一PCIe switch
  3. 分层AllReduce: 多节点场景下显著减少跨机通信
  4. 通信计算重叠: DDP bucket策略, 异步AllReduce
  5. 混合并行通信组: 合理划分TP/PP/DP通信组

面试高频问题

  1. Fat-Tree和Rail-Optimized拓扑的区别和适用场景?
  2. NCCL如何进行拓扑发现?
  3. 如何优化跨节点AllReduce通信?
  4. Tensor Parallel和Data Parallel对网络的要求有何不同?
  5. 如何排查分布式训练的通信瓶颈?
Prev
03-RDMA与InfiniBand原理
Next
05-大规模集群网络架构