workload的区别

推理的类型是非常多的,RL rollout,在线服务,推荐……这些workload都不一样,虽然说推理框架这一层原则上是一个runtime的workload调度层,但是随着不断的发展,每个推理框架也并不能做到对任意的workload都有一套好的runtime策略,最终这几个框架的优化还是固化到了某几个场景,比如高贵的RL后训练,比如最主流的Serving,然后一些类似于广告推荐的边缘场景就被一脚踢死了(笑。

这他吗就很尴尬呀,现状就是典型场景已经穷尽了可能性,没东西做了,非典型的场景又没好的实现,导致必须从头开始吃屎,不过这里不吐槽这种极度的不均衡,只谈谈为什么知名的v和s两家推理框架换个场景就不行了,本质上是在讨论workload。

v和s两家框架面向的是在线序列的批处理,也就是一下QPS来了很多,然后以一个很高效的调度方式让这些任务都能被调度起来。框架层只是下发,实际的工作都在算子队列里面。而GR显然不一样,作为推荐输入的embedding是共享的,推理出来的东西是一个多级索引,这个多级索引被硬编码为token,输出token只能从这里挑选,一般叫Sematic ID(所以也得小小扩充一下词表)。然后一般的GR还会做beam search,类似于给非top的输出一次参与后续自回归生成机会,以增加结果的diversity。这个操作对于传统llm来说是很少见的。

做beam的时候虽然kvcache解决了重计算的问题,prefix sharing或copyonwrite解决了重复存储的问题,但是beam阶段load同一kv的操作依然是问题。算子上这是很多次重复没必要的G2S。如果要改这个算子的话,会更麻烦。

beam导致的kv重排

beam因为在自回归这一层做了分叉,原先设计的那种纯顺序化的kvcache就很容易出问题了,beam会主动更新自己候选的beam,也就是说他的batch来自于beam主动的而不是外界来的很多共同前缀的请求。beam能主动产生batch也能修改他们的顺序关系(熵之源说是),一旦修改了,就和顺序化的自回归假设不一样了,就得重新换block/radix treenode顺序。beam的候选+淘汰对传统自回归的范式设计影响太大了,必须得侵入式修改算子+框架。

其他调度

gr还会有很多奇奇怪怪的前处理后处理,这些都没被v和s优化过,所以自然性能也不行。