1. Weights在AllGather中的量化;(计算时间换网络通信延迟)
Zero3的Weights分片在各个rank中;在forward和backward中,用到整层weights时都要所有rank进行AllGather;
使用FP16-->INT8量化,减少一半通信量;
对整个矩阵进行量化,误差大;分成多个子矩阵,分别量化,误差小;
我认为:最左图不太准确;4.690可以作为127,-9.220可以作为-128,FP16的0值和INT8的0值不需要重合的;
2. weights的AllGather减少跨机器通信量(内存和访存换通信延迟)
基于事实:机器内部跨GPU通信,远比跨机器通信,要快;
Forward阶段,老样子AllGather通信,但把拿到的weights在本node(机器)上保存一份完整的副本;
Backward阶段,因为weights相比Forward并没有任何改变,因此复用本node上的weights副本,每个GPU只和本node上的所有GPU进行AllGather通信;
3. Gradients在AllReduce阶段的量化
FP16-->INT4, 减少通信量;
量化后的gradient,直接reduce加和的话,精度损失太大;只能先反量化后,再加和;
如果使用Ring-AllReduce实现版本,每一步都要量化、反量化,N个GPU需要N次量化、反量化,且延迟为N;
采用1步到位的All-to-All,量化、反量化都是1次,(理论上,取决于网络拓扑)1步延迟;
我:可以用Seide的方法(首轮都往+1节点发送,第2论都往+2节点发送,。。。)
但是这样会增加跨机器通信量。设定如下变量:
如果用Ring-AllReduce,则 每台机器的跨机器通信量,为M;(想象第1台机器的第N块卡,向第2台机器的第1块卡,发送的总数据量)
如果用All-to-All,则 每台机器的跨机器通信量,为N*(M/Z);(想象第1台机器,拥有N*(M/Z)的数据量,当机器数较大时,除了少量发给自己,其余绝大部分都发给其他机器)
解决方法:故伎重演,还用2层通信,先intra-node通信,再inter-node通信;一共2遍量化、反量化;
intra-node通信:每个GPU的通信量是M/Z;每台机器的跨机器通信量,是M/Z;