All2All Communication Cost
在 All2All 通信中,每个设备给其他设备发送大小为 m 的不同的消息。此操作相当于使用一维数组分区对分布在 p 个进程中的二维数据数组进行转置,因此也被称作全交换 (total exchange)
Ring / Bidirectional Linear Array
线性数组拓扑结构的 All2All 通信中,每个设备需要发送 p-1 份大小为 m 的数据。用 {i,j} 表示消息需要从设备 i 发送到设备 j. 首先,每个节点将所有要发送的数据作为一个大小为 m(p-1) 的合并消息发送给它邻居 (假设所有设备通信方向相同)。当邻居收到这个消息后提取他所需要的那一部分,发送剩下的大小为 m(p-2). 每个设备一共发送 p-1 次,每次要发送的消息大小减少 m.
由此可以得出在 p 个设备组成的线性数组拓扑上进行 All2All 每个设备需要向相邻设备通信 p-1 次,第 i 次通信的消息大小为 m(p-i). 如果向两个方向都进行发送,那么每个方向都只用发送原先一半的数据。
环状网络中每份消息的平均传输跳数是
跳数为 d 的消息数量对应于相距 d 的节点对 (i, j),其中 |i-j|=d
- (0, d),(1, d+1), \ldots,(p-1-d, p-1),即 i 从 0 到 p-1-d, j=i+d ,共有 p-d 对。
- (d, 0),(d+1,1), \ldots,(p-1, p-1-d),即 i 从 d 到 p-1, ~ j=i-d ,也有 p-d 对。
总共有 2(p-d) 条消息的跳数为 d
总跳数
因此平均跳数
Mesh
若 p 个设备组成大小为
首先同时分别在每一行中进行 All2All 通信,每一份数据大小为
我们只需要将 Linear Array 拓扑结构中的公式的 p 换成
Hypercube
超立方体拓扑在每个维度上都有两个节点,一共有
在 All2All 通信的任何阶段,每个节点都持有 $p$ 个大小为 $m$ 的数据包。当在特定维度上通信时,每个节点发送 p/2 个数据包 (合并为一条消息)。这些数据包的目的地是由当前维度的链路连接的另一个子立方体包含的节点。在上述过程中,节点必须在每个
在
值得注意的是与 ring 和 mesh 算法不同,超立方体算法不是最优的。每个设备发送和接收大小为 m(p- 1) 的数据,超立方体上任意两个节点之间的平均距离为
Optimal Algorithm in Hypercube
在超立方体上,执行 All2All 的最佳方法是让每一对节点彼此直接通信。因此,每个节点只需执行 p-1 次通信,每次与不同设备交换大小为 m 的数据。设备必须在每次通信中选择不会出现拥塞的通信对象。在第 j 次通信中,节点 i 与节点
- 将当前节点地址 C 与目标节点地址 D 进行 XOR 操作,得到
. - 找到 R 的最低有效非零位,决定下一步跳转的维度。
- 沿选定维度跳转到下一个节点,更新当前节点地址。
- 重复上述步骤,直到 R=0, 即到达目标节点。
对于节点i和节点j之间的消息传输,该算法保证每一步的通信时间为 t_s + t_wm,因为在节点 i 和节点 j 之间的链路上沿着同一方向传播的任何其他消息都不存在竞争,切每一步只切换一个维度,通信距离为 1. 整个 All2All 的总通信时间为
Bruck Algorithm in Full-connected Network
Bruck是一种存储-转发 (store-and-forward) 算法,需要 log(P) 次通信步骤。这意味着发送缓冲区 S 和接收缓冲区 R 都用于在中间通信轮次中发送、接收和存储数据。因为某些接收到的数据块必须在后续通信步骤中使用。这种存储-转发的特性对通信轮次的顺序提出了约束。与线性步骤实现不同,Bruck 必须保持明确的通信顺序,其中第 i+1 次迭代必须在第 i 次迭代之后物理时间上发生。
1 |
|
- line(2-4): 将每个设备发送缓冲区 S 中的数据按照 rank 偏移重新排列拷贝到接收缓冲区 R 中。
- line(5): 为通信阶段准备一个临时缓冲区 T
- line(6): 通信步开始 k 以指数方式增长 (1, 2, 4, …),总共执行 logP 次迭代
- line(7-14): 用索引数组 SB,记录需要发送的数据块位置。遍历 k~P-1 同通过对 i&k 判断哪些数据块需要在此轮发送. (若 P 是 2 的指数幂,因为 k 是 2 的指数幂,因此只有一位为 1,那么就是每轮发送 p/2 个数据块) 将接收缓冲区 R 中满足条件的数据拷贝到临时缓冲区 T,并记录索引。
- line(15-16): 确定要接收和发送的目标。
- line(17-20): 进行通信操作,将数据发送到目标的发送缓冲区。
- line(21-23): 更新接收缓冲区。
- line(25-27): 反向调整接收缓冲区数据的位置。
总共 log(p) 步骤每步发送 m 消息。
Tree-based
采用先在行上进行 All-gather, 再在列上进行 Scatter. 也需要 log(p) 步,其中 gather 阶段第一步通信量为 m(p-1),一共进行 0.5log(p) 步每一步通信量翻倍,跳数也翻倍;scatter阶段则是相反,因此两步的通信时间相同总共 t_s*log(p) + m(p-1)^2/3