全部术语

GLOSSARY ENTRY

GPU 互联拓扑与通信成本

  • GPU Topology
  • NVLink
  • NVSwitch
  • PCIe
  • InfiniBand
  • RDMA
  • NUMA

把 rank placement 与实际 GPU、CPU socket、PCIe/NVLink/NVSwitch、NIC 和跨节点路径对应起来;collective payload 相同并不代表链路 hop、争用、带宽与延迟相同。

逻辑 collective 之下还有物理路径

集合通信定义 All-Reduce/All-Gather/All-to-All 的结果 shape 与所有权;拓扑决定 bytes 经过哪些 links、是否共享 root complex/NIC、能否并行和何处拥塞。

rank → process → GPU → PCIe switch/root complex → CPU NUMA node → NIC → fabric → remote host
                  ↘ NVLink/NVSwitch peer domain ↗
  • PCIe:通用主机/设备互联;GPU peer traffic 是否直达取决于拓扑、P2P/IOMMU/ACS 等配置。
  • NVLink:GPU 间高速 links;具体代际、link 数与 peer matrix 不同。
  • NVSwitch:交换 fabric,让一组 GPUs 形成更均匀的 NVLink 域;不是所有机器都有。
  • InfiniBand/RoCE/RDMA:跨节点网络与 remote DMA 能力;带宽/latency 还取决于 NIC、switch、routing、congestion 与 GPUDirect RDMA。
  • NUMA:CPU memory/NIC/GPU 分属 sockets;CPU staging 或 control thread 绑错 socket 会增加 host path 成本。

α-β 模型加上路径与争用

一条消息的简化成本:

Tnroundsα+epathBeBWe+Tcontention+TsyncT\approx n_{rounds}\alpha+\sum_{e\in path}\frac{B_e}{BW_e}+T_{contention}+T_{sync}

α\alpha 是每轮固定延迟,BeB_e 是经过 link ee 的 bytes,BWeBW_e 是该 link 可用带宽。不同 links 可流水/并行,所以上式是核对框架,不保证机械相加。Collective library 会按 topology/message size 选择 ring/tree/hierarchical/CollNet 等;API 名不固定算法。

Byte-hop:把每条消息 bytes 乘经过的 links 数后求和,可用于比较 placement 的物理流量放大,但不等于时间。一个慢共享 link 的拥塞通常比多个独立 link 的总 byte-hop 更关键。

Toy topology:同一 logical exchange,不同跨域负载

四个 GPUs 构成线性 toy fabric:

GPU0 — GPU1 === GPU2 — GPU3
             ^
       cross-domain link

每组两 rank 双向交换 64 MiB:

  • topology-aware groups (0,1),(2,3):只用域内 links;总 byte-hop 256 MiB,跨域 0。
  • bad groups (0,2),(1,3):两组都跨 (1,2);总 byte-hop 512 MiB,跨域 link 负载 256 MiB。

逻辑 payload/每组成员数相同,但坏 placement 让路径变长并共享 bottleneck。这不预测真实 NVLink/PCIe 时间,只说明为什么 TP/EP/CP groups 应优先放在高速域,并把较低通信强度的 PP/data parallel 放到较慢边界(仍需按 workload 验证)。

可运行的 byte-hop 计算

import platform
from collections import defaultdict,deque

GRAPH={0:[1],1:[0,2],2:[1,3],3:[2]}
CROSS_DOMAIN=frozenset((1,2))

def shortest_path(source,destination):
    queue=deque([(source,[source])]); visited={source}
    while queue:
        node,path=queue.popleft()
        if node==destination: return path
        for neighbor in GRAPH[node]:
            if neighbor not in visited:
                visited.add(neighbor); queue.append((neighbor,path+[neighbor]))
    raise ValueError("disconnected topology")

def route_bidirectional_pairs(groups,payload_mib):
    edge_load=defaultdict(float); routes=[]
    for source,destination in groups:
        path=shortest_path(source,destination); routes.append((source,destination,path))
        for left,right in zip(path,path[1:]):
            edge_load[frozenset((left,right))]+=2*payload_mib
    return routes,edge_load

def main():
    good=[(0,1),(2,3)]; bad=[(0,2),(1,3)]
    good_routes,good_load=route_bidirectional_pairs(good,64)
    bad_routes,bad_load=route_bidirectional_pairs(bad,64)
    assert good_load[CROSS_DOMAIN]==0 and bad_load[CROSS_DOMAIN]==256
    assert sum(good_load.values())==256 and sum(bad_load.values())==512
    edges=sorted({tuple(sorted((node,n))) for node,neighbors in GRAPH.items() for n in neighbors})
    print(f"python={platform.python_version()} topology_edges={edges}")
    print("logical_exchange_per_pair=64MiB_each_direction")
    print(f"good_groups={good} routes={good_routes} edge_load_MiB={dict(good_load)}")
    print(f"bad_groups={bad} routes={bad_routes} edge_load_MiB={dict(bad_load)}")
    print(f"cross_domain_good_MiB={good_load[CROSS_DOMAIN]:.0f} cross_domain_bad_MiB={bad_load[CROSS_DOMAIN]:.0f}")
    print(f"byte_hop_good_MiB={sum(good_load.values()):.0f} byte_hop_bad_MiB={sum(bad_load.values()):.0f}")

if __name__=="__main__": main()

完整文件位于 examples/topology_cost.py,只用标准库。输出验证好/坏 placement 的跨域流量为 0/256 MiB、总 byte-hop 为 256/512 MiB

不同并行模式为何偏好不同拓扑

  • TP:每层频繁 collective,latency/bandwidth 敏感,通常应在最紧密高速域内。
  • CP:长上下文 K/V/partials 通信较大,也偏好高速域;ring path 要与 causal/load balance 配合。
  • EP/MoE:All-to-All 流量随路由动态,跨域拥塞/straggler 明显;expert placement 可结合流量统计。
  • PP:主要在 stage boundary 传 activation,频率/bytes 与 microbatch 相关,可跨较慢域但会增加 bubble。
  • Model loading/CPU staging:磁盘/NIC→CPU→GPU path 受 NUMA affinity 和 pinned memory 影响。
  • KV Offload/P-D:GPU↔CPU/NIC/GPU 的 64 MiB 级状态 transfer 会与 collectives 争用 PCIe/NIC;独立页面给出 payload 下界与本机 pinned copy 实测。

并行模式总览定义逻辑切分,本页定义 rank coordinates 如何映射到设备图。Topology-aware placement 不能修复算法本身通信量过大,也不能保证 overlap;需要 profiler 确认 collective 是否在关键路径。

诊断清单与失败场景

至少收集:

  • nvidia-smi topo -m/vendor topology、GPU↔NIC/CPU affinity;
  • peer access、link generation/count、PCIe negotiated width;
  • NCCL debug/topology graph、实际 algorithm/protocol/channel;
  • per-message size、collective group、stream 与 wait position;
  • link/NIC counters、retransmit/congestion、NUMA CPU/memory binding;
  • 单 rank compute skew 与 MoE route imbalance,避免把等待误判成链路慢。

常见错误:

  • global ranks 连续就假定物理邻近;容器/launcher mapping 可能不同;
  • TP group 跨节点,而低通信 PP stages 留在同一 NVLink island;
  • CPU tokenizer/loading threads 在远端 NUMA node;
  • benchmark 单 pair P2P 带宽,推断多 collective 并发性能;
  • 只看峰值 link spec,不看消息大小下的 α、protocol 与 contention;
  • collective API 名称当作 ring/tree 实际算法证据。

参考资料