cp

cp
gogongxtcp分成了prefill和decode
cp核心来说,就是分成几个不同的思路点:
- rank持有部分q和部分kv,节约容量,节约激活,得用ring attention计算
- rank持有部分q和全量kv,节约不了容量,节约激活,加速(更适用于mla)
- rank持有全量q和部分kv,节约容量,不节约激活,加速
cp是需要每个rank都持有完整的qkv_proj权重的,所以开启cp扩充不了总容量,但是可以扩充单个请求的最长上下文
pcp
pcp分成两种,一种是megatron提出的ring attention,一种是DeepSpeed Ulysses cp
ring attention
每张卡上存储完整的权重
qkv_proj也是切序列,然后每张卡上存储一部分序列的kv,然后在attention计算时做ring attention通信,也就是每张卡上的部分q每轮和传来的kv做计算
这样计算n轮传递n-1轮,每个q就和历史的全量kv做完了计算,再做o_proj,就得到了输出
然后ring attention的计算本身是不平衡的,因为q对历史的长度不一样,由此引出一个zig-zag的分配q的方式
然序列末尾和开头放到一个rank上,大概就这个意思,就可以让整体的每个rank计算量平衡
理解:
ring attention 每次要通信n-1轮,每次通信都是all to all
由于kvcache容量进行了分散,所以这个方法是可以扩展上下文的,对于deepseek的mla也是有效的
DeepSpeed Ulysses cp
这种也是每张卡上存储完整的权重
先把序列切分成[S/n,emb]
然后做qkv_proj计算,计算完成后就是[S/n,H,d]
通过一次alltoall,让每张卡上拿到完整的数据[S,H,d]
然后做一次转换,每张卡上只保留自己那部分头的
[S,H/n,d]
然后就可以计算attention了,计算后拿到的依然是
[S,H/n,d]
然后再做一次alltoall,每张卡拿到完整数据 [S,H,d]
并转化只保留自己的那部分序列 [S/n,H,d]
再去做o_proj,拿到最终的输出
理解:
可以看到上面的整个过程,其实核心的softmax attention就是采用TP的切分方式,然后qkv和o的proj是采用cp的切分方式
中间通过两次alltoall进行转换,这个操作并没有节约计算量,不过节约了激活值,每张卡上只需要保留部分序列的隐藏层张量
然后每张卡上也是需要保留完整的权重的,不过因为核心attention是tp,所以依然是扩充了上下文
对于deepseek的mla这种架构,因为核心的头tp无法切分原因,没法做到扩展上下文,但是那些proj操作依然可以通过cp切序列去实现加速,这个是采用cp比纯tp更有优势的地方
dcp
dcp 分成了普通的decode cp和适用于dsa稀疏attention架构的dsa-cp
普通decode cp
其实和megatron的prefill cp类似,也是kvcache是分布在不同rank上
不过区别是q是每个rank持有相同的,ring attention是持有不同的q
所以dcp会先计算一次q_proj,然后做all gather/reduce,然后让每个rank都拿到全量的q
然后q和rank持有的kvcache做计算,后面就和ring attention也是一样的了
理解:
和ring attention是比较像的,区别是每个rank都有相同的q,就不需要ring attention了,就普通attention直接算就行了




