前几天晚上我又在调一个跑 agent 编程的部署。单纯想让它单用户响应快一点,就把 batch size 从 16 压到 4。烧起来,单流测试里 token 间隔从 170ms 降到 90ms 出头,看着确实快了。可同一张卡,一小时能喂饱的并发请求从两百多个掉到四十几个。我对着这两个数字发了会儿呆:花了半个晚上,我真的只是在这条曲线上滑来滑去?
我凭什么第一反应就是“在同一条曲线上滑”?后来想,因为脑子里那张效率图只有两个轴——延迟和吞吐。batch size 往左,延迟好,吞吐烂;往右,反着。大晚上调参,最顺手的扳手就是它。别的呢?张量并行度调高一点,是图上的一个点;专家并行在机架里缩窄一点,又是一个点。每个动作都像把你在这条折线上重新安置了一下。这条折线,行内管它叫效率前沿。但“前沿”这个词有欺骗性——它预设了其他一切全摁死了:质量、软件栈、并行策略的整体形状,只剩这两个轴能动。这个图不是世界,它是个截面。
那问题就来了:如果所有显式调参都只是让你在一个截面里迁移,那“优化”是不是全算这种滑动?
不是。有一类技术直接换掉这张图,而不是让你在图上选点。量化算里面最典型的。
我一开始也以为量化只是“降精度换速度”——听起来像延迟-吞吐图上一次普通位移,跟调 batch size 差不多。后来把 MXFP4 这类格式部署到几个主要模型上,才发现不对。量化把你踢出了原来那张二维图,因为质量不再是被固定的前提,它成了你必须主动管理的一根轴。原来那张图,只是质量轴上某一个水平处的切片。你在旧切片边上跑,跟你在新切片里跑,是两码事。
未量化系统的延迟-吞吐图,是质量=1.0 时的截面;量化之后那张新图,是质量=0.995 时的截面。你感觉“前沿被外推了”——延迟更低,吞吐更高——但没看见的是,你已经在第三根轴上挪了一格。
这一格要不要紧,是另一回事。MXFP4、NVFP4 这些微缩放格式在不少任务上质量损失小到基准测试里测不出来,这是事实。但“小到测不出来”和“没发生”不是一回事。尤其到生产系统里,你得先把“质量下移一格”这个代价标出来,再看能不能忽略。
写到这儿得回补一句:那晚的我可没这么清楚,什么“换图”——全是后来盯着监控复盘才慢慢想通的。那晚的我坚定地相信自己只是在做合理的延迟-吞吐调优。这种坚定通常就是出事的前兆。
再往下还有一层。这条“外推”的路也不是一片坦途,因为几乎所有这类技术都在付代价,而代价常常不在原来的二维图里——这是最坑的地方。
推测解码就是。它看起来在单用户速度上做文章,跳过主模型前向传播来加速,但它会跟主模型抢资源,并发一高反而把最大 batch size 压下去。也就是说,它根本没把你原来那条延迟-吞吐线整体外推,它只是把线上某几个片段弯了一下。你要是还用那张“延迟 vs 吞吐”的图看它,部署完只会看到一条被局部压扁的不规则曲线——原来你以为平滑的前沿,这下现了原形。
真实前沿根本不是平滑的。这是那晚我一度拒绝接受的事实。我以为延迟-吞吐的交换像条指数衰减曲线那样光滑。但真实测评里,从 batch 4 到 5 可能纹丝不动,到 7 突然跳一格。为什么?GPU 显存分配、通信模式、算子调度的台阶就摆在那儿,不是每个 batch size 都是一个真实可行的计算形态。这些拐点不靠推理,得靠扫。你只能一个点一个点去跑,找到那条折线实际拐在哪。我早该知道:扫描不出来,图上的线画得再漂亮也没用。
说回那晚。我不是 batch size 调得不好——4 在这条切片上算个合法落点。问题是我一坐下来就没意识到,自己站在一张已经被固定了 z 轴的截面上,调来调去都在平面上滑。这种盲区我怀疑很多聊“推理效率前沿”的人都有。我们急于把延迟、吞吐、成本摆成一个二维图,然后开始调参。这本身不坏,但值得问一句:你是在调图上那个点,还是已经动了某一根之前没标出来的轴,然后假装自己只是更聪明地在延迟和吞吐之间做了选择?后者比前者危险得多。前者至少知道自己放弃了什么;后者常常连放弃的是什么都没看见。
再往下就是质量那根轴怎么定义的问题了。现在大家爱拿基准分当代理,可真实系统里,一个代码补全请求允许多少质量损失,取决于用户在那一刻的容忍度——这个度量标准眼下根本没有统一的算盘。这层我还没想透,先放这儿。
