最近thinkingmachines的一篇博文在内外网引起了无数的关注和转载,这篇文章的核心内容先是解释了一下为什么LLM推理会有不确定性,随后文章还给出了具体的解决方案。
在详细介绍文章的内容之前,我们先来说一下thinkingmachines这家公司。它是由前OpenAI首席技术官Mira Murati与多位前OpenAI高管联合创立。Murati 这个人经历也比较神奇,首先她并不是AI科班出身,最早是在Tesla担任model X的产品经理。然后在2016年加入openAI,并一路升到了openai的CTO,你不得不佩服在牛人面前行业或者说专业门槛似乎根本不存在。
说完上面的八卦之后,我们开始进入正题,先来聊一下LLM推理过程当中的不确定性是如何产生的。
在这篇文章出现之前,大多数人认为之所以产生不确定性主要是以下两个原因导致的:
- 浮点数不满足结合律:以加法运算为例,咱们平时觉得(a+b)+c 和 a+(b+c)结果肯定一样,但用电脑里的 “浮点数”(比如表示 0.1、1e20 这种数的格式)算,还真不一样!
其实,这个很好理解,因为因为浮点数只能存有限位数的精度,加超大数再减,小数的 “精度” 就被丢掉了。这就导致了如果一堆浮点数加的顺序不一样,最后结果可能就不一样。
2. GPU并行计算:很多人会觉得GPU 是多核心并行计算,谁先算完不一定,所以结果不一样。
针对上面的两个误解,文章也一一给了回应。首先,浮点数由于计算顺序不同而导致丢精度确实不假,但是这个不是导致推理不确定性的直接原因;其次,GPU并行计算的这个说法压根就是错误的,因为现在的 GPU kernel早就能避免 “谁先算完影响结果” 了。只有一种情况会让 GPU 算得不一样 —— 用 “原子加法”(多个核心往同一个数上加,谁先加不确定)。但 LLM 推理时,根本不用 “原子加法”!所以 GPU 并行不是罪魁。
文章中为了更好的解释这个问题,提出了一个叫“batch-invariance”中文可以译为“批次不变性”。而之所以LLM在推理时会产生不确性主要是因为很多的计算内核(kernel)不满足“批次不变性”。简单来说就是,用户提交的同一个推理请求单独算和跟别人一起打包算,结果可能不一样。文章当中举了一个具体的实际例子
复制上述例子当中,用 GPU 算矩阵乘法,先取第一个请求的矩阵单独算(out1),再把所有请求打包算完后取第一个结果(out2),两者差了 1669 多 —— 这可不是小误差!文章还提到一个叫运行间确定性,意思是说同一批次运算结果是一样的。
但是现在很多时候,为了提高LLM推理时GPU的利用率,一都使用动态批次调度的算法。也就是说,会根据当时服务器的繁忙程度来动态调整批次的大小。
既然问题已经找到了,那如何解决呢?文章提到,要让 LLM 推理稳定,就得让每个计算步骤(主要是 3 个关键步骤)不管批次大小多少,算出来都一样。这三个步骤按难度从低到高排序依次是:
- 1. 归一化(RMSNorm):给每个请求 “专属核心”
RMSNorm 是给数据做归一化的步骤,计算时需要 “求和取平均”。原来的问题:批次小的时候,GPU 核心用不完,就会让多个请求共享一个核心,算的时候求和顺序变了,结果也就不一样了。解决办法:不管批次大小,每个请求分配一个核心,让每个请求的求和顺序固定。就算批次小、有些核心空闲,也不共享 —— 大不了慢一点,换结果稳定。
- 2. 矩阵乘法:固定 “计算瓷砖大小”
矩阵乘法是 LLM 的核心计算,快的关键是把大矩阵切成小 tile(比如 128x128),让 GPU 高效算。原来的问题:批次小的时候,tile切得不一样(比如批次 1 时不用大tile,批次 10 时用大tile),乘法顺序变了,结果差了。解决办法:不管批次大小,都用同一种 “tile大小” 算。哪怕批次小的时候有点浪费算力,也不换tile —— 性能会降一点(比如比最快的情况慢 20%),但结果稳定。
- 3. 注意力机制(Attention):固定 “拆分大小”
注意力是 LLM 理解上下文的关键,计算时要处理 “查询(Q)” 和 “键值(KV)” 的匹配,需要求和。原来的问题:处理长文本时,KV 会存在缓存里,批次不同时,缓存里的 KV 和新算的 KV 结合方式不一样(比如批次 1 时拆成 3 段算,批次 5 时拆成 2 段算),求和顺序变了。解决办法:不管批次和缓存里有多少 KV,都按 “固定大小拆分”(比如每次拆 256 个元素),哪怕最后一段不够 256 个,也按这个规则拆 —— 确保求和顺序永远一样。
文章中基于上述的方法实现了相应的batch-invariant 相关实现,具体结果如下:
- 用 Qwen3-235B 在温度 0、同一提示词采 1000 次,默认内核得到 80 种不同结尾;换成 batch-invariant 内核后,1000 次完全一致。
- 性能上,在单 GPU、Qwen-3-8B 的例子里:vLLM 默认 26s,未经深度优化的“确定性模式” 55s,改进注意力后 42s。可见“可用、不至于灾难”。
当然,上面主要是从我自己的视角对这篇博文的提炼,我强烈建议大家去读一下原文。具体地址见引用。