scatter-reduce 这一步完成之后,每个 GPU 有一个值的数组,其中这些值(每个 GPU 一个块)中的一些是包含来自所有 GPU 贡献的最后值。为了完成 allreduce,GPU 必须交换这些块,从而所有的 GPU 获得所有的必需值。 该环路的 allgather 的执行等同于 scatter-reduce(通过 N-1 次发送和接收的迭代),除了不是累加 GPU 接收的值,而是简单地重写块。第 n 个 GPU 通过发送第 n+1 个块和接收第 n 个块开始,并在未来的迭代中一直发送它刚接收的块。 例如,在我们的 5 个 GPU 设置中的第一次迭代,GPU 会发送和接收以下的块: GPU 发送 接收 0 Chunk 1 Chunk 0 1 Chunk 2 Chunk 1 2 Chunk 3 Chunk 2 3 Chunk 4 Chunk 3 4 Chunk 0 Chunk 4
allgather 的第一次迭代中的数据传输 在首次迭代完成之后,每个 GPU 将有最终数组(final array) 的两个块。 在接下来的迭代中,该进程会继续运行,一直到最后每个 GPU 都会有整个数组的全部累计值。下面的图像演示了从第一次迭代到 allgather 完成的所有数据传输和中间结果。
Allgather 数据传输(第 1 次迭代)
Allgather 数据传输(第 2 次迭代)
Allgather 数据传输(第 3 次迭代)
Allgather 数据传输(第 4 次迭代)
所有 allgather 完成后的最终状态 Allreduce 通信成本 回到引言中描述的简单的通信算法,通信成本(communication cost)会随 GPU 的数量而线性增长。allreduce 效果良好的主要原因是情况已经发生了变化。 在我们描述的系统中,每 N 个 GPU 都会因为 scatter-reduce 而接收 N-1 次值,还为 allgather 接收 N-1 次值。每一次,GPU 都会发送 K/N 个值,其中 K 是指数组中值的总数量,这是在不同 GPU 上相加得到的。因此,每个 GPU 的传入和传出数据总量为: 被传输的数据=2(N?1)N?K 其独立于 GPU 的数量,这是很关键的。 因为在离散的迭代中,所有的传输都是同时发生的,所以 allreduce 的速度受限于该环路中相邻 GPU 之间的最慢(最低带宽)的连接。为每个 GPU 选择合适的邻居,该算法能在所有 allreduce 上做到带宽最优并且可能是最快的算法(假设相比于带宽,其延迟成本可以忽略不计)[4]。总的来说,如果在一个节点上的所有 GPU 都临近该环路中的其它 GPU,那么该算法可以得到最好的效果;这能最小化网络连接的数量,从而显著增加这种 GPU-GPU 连接的有效带宽。 将该 Allreduce 应用于深度学习 ring allreduce 是高性能计算领域内一个众所周知的算法,但在深度学习领域内的应用相对较少。在我们的实验室中,我们已经成功地将这种工具用作我们所有的数据并行训练的基础,让我们可以将训练有效地扩展到十余个 GPU。 (责任编辑:本港台直播) |