More than code

More Than Code
The efficiency of your iteration of reading, practicing and thinking decides your understanding of the world.
  1. 首页
  2. 未分类
  3. 正文

nccl tests

2026年1月30日 10点热度 0人点赞 0条评论

https://github.com/NVIDIA/nccl-tests/blob/master/doc/PERFORMANCE.md

基本概念

time:

  • 小size的时候,用来衡量通信操作的overhead

  • 大size的时候,带宽项主导,所以应该看算法的带宽来预估性能

Bandwidth:

  • Algorithm bandwidth
    • 代表的是纯数据的bandwidth,不看具体的算法。

    • 就是输入的数据S 除以 花费的时间t

  • Bus bandwidth

    • P2P的通信,上面的algorithm bandwidth就是真正的通信量

    • 但是all gather这种,涉及到多个rank通信的,需要看具体的算法流程来计算通信量。

    • 代表的是硬件中真正的通信量

具体算子

ReduceScatter


输入数据量为S
rank数量为n
每个rank对外的带宽为B

对于RS来说,每个rank最终的输出为 S / n,要收集来自其他rank的对应的数据
每一个数据都涉及到n - 1次跨rank的通信。
单个rank的通信量就是 S / n * (n - 1)
总的通信量就是S * (n - 1)

n个rank,拥有的总带宽是n * B
总共的通信时间就是 t = S * (n - 1) / (B * n)
那么B = S / t * (n - 1) / n = algbw * (n - 1) / n

AllGather

同上,每个rank最终的输出为S,输入是S / n
每个rank需要把自己的数据发送给其他n - 1个rank。总共的通信量也是S * (n - 1)

其他推理过程同上,得到B = algbw * (n - 1) / n

AllReduce

AllReduce是RS + AG。所以通信量变成了2 * S * (n - 1)
B = algbw * 2 * (n - 1) / n

All2All


假设全局总的数据量是S
All2All的输入是S / n,输出也是S / n
每个rank包含S / n的数据,需要通信其中的(n - 1) / n份。
单个rank的通信量就是S / n * (n - 1) / n
总的通信量是S * (n - 1) / n
那么等式就变成了:
t = S * (n - 1) / n / (n * B)
B = (S / n) / t * (n - 1) / n
因为输入和输出都是S / n,所以algbw是(S / n) / t
那么factor就是(n - 1) / n

算法的选择

需要注意的是,上面在计算通信量的时候,都是按照最优的来计算的,并没有考虑具体的通信方式。
实际上常用的实现,比如RingAllReduce这种,通信量也是最小的。所以上面的结论是没问题的
不过这里要提的是具体的通信方式是有比较大的关联的。

比如AllReduce:

  • 如果使用的是上面提到的RingAllReduce,通信量是2 * (n - 1) * S

  • 但是如果是每个rank都收集来自其他rank的全量数据。相当于只有一跳。此时每个rank都会接收(n - 1) * S的数据,总共就是n * (n - 1) * S

  • 这里也有一些带宽/延迟的tradeoff的感觉,当然也要考虑网络的拓扑结构。

![[Pasted image 20260130100958.png]]
比如这种yy的all-reduce的方法,通信量就变成了S * (n - 1) * (n - 1)。和上面算的2 * S * (n - 1)就不一样

统计口径

上面在计算通信的时候,考虑的是单向的收发,即:
A 发数据给 B

  • A 在 TX(发送)

  • B 在 RX(接收)

  • 数据在物理链路上只沿一个方向流动

  • 此时占用的带宽认为是1

  • 而不是A发送,B接收,认为是2

比如上面的AllGather,每个shard都收(n - 1)个rank的数据。并没有考虑发送的情况。

参考这里https://zhuanlan.zhihu.com/p/1957457076080076392
以及nccl test的文档

现实硬件常见有两种“带宽口径”:

(A) 单向带宽(unidirectional bandwidth)

比如说:NVLink x 50 GB/s(举例)
意思是:

  • A→B 最多 50 GB/s

  • B→A 最多也 50 GB/s

但如果你只做 A→B,就是 50 GB/s。

(B) 双向带宽(bidirectional bandwidth)

硬件宣传里经常写 “100 GB/s bidirectional”
其实就是把两个方向加起来:

  • A→B 50

  • B→A 50

  • 双向合计 100

⚠️ 但注意:这 100 只有在 两个方向同时满速 才成立。
所以,如果你只传 A→B,而 B→A 没传,那你最多只能用到一半(单向那部分)。

从这里看的话,如果算法可以利用到双向的带宽,效果会比只能单向传输的算法效果会更好。
比如NCCL的一些算法(GPT说的,我没有研究过代码),会考虑用多个channel,让一部分数据顺时针通信,另一部分逆时针通信,这样在ring通信的场景,就可以利用到双向的带宽。
另一个点,All2All天然就是双向的:

  • 每个rank会发送(n - 1) * S / (n * n)的数据。同时也会接收这么多数据

CaseStudy

RingAllGather

我自己yy的,不一定是真的

  • 每个rank,每次发送S / n的数据

  • 需要n - 1次iteration,共n个rank

  • 总共发送的数据量为 S * (n - 1)

RingReduceScatter

  • 每个rank,每次发送S / n的数据

  • 需要n - 1次iteration,共n个rank

  • 总共发送的数据量为 S * (n - 1)

  • 最后再把多余的数据释放掉即可

上面这些的通信模式都是和邻居收发消息的,根据具体的拓扑结构,应该还有一些更加高效的算法(延迟高效,带宽应该上面分析的就是理论的最优质了)

标签: 暂无
最后更新:2026年1月30日

sheep

think again

点赞
< 上一篇

文章评论

取消回复

COPYRIGHT © 2021 heavensheep.xyz. ALL RIGHTS RESERVED.

THEME KRATOS MADE BY VTROIS