
此研究是由三位各自独立的研究者开展完成的, 其于2026年7月22日以预印本的形式予以发布, 论文所具有的编号是arXiv:2607.19712, 那些存有兴趣想要深入去了解一番的读者能够借助该编号去查询完整的论文。**故事从一个被忽视的角落开始**在人工智能范畴当中, 存在着一种技术名为RLHF, 其全称为“基于人类反馈的强化学习” , 你能够将它理解成训练AI的一种途径 , 先是让AI去生成诸多候选回答 , 紧接着借助一个“裁判员”奖励模型给每个回答进行打分 , 最终依据分数去改进AI , 当下几乎所有主流的对话AI , 涵盖你所熟知的各类聊天机器人 , 背后都曾运用过或者正在运用这套机制。需注意, 这个“裁判员”, 得是在每一轮具体的训练当中, 给所有那些候选回答, 一一打出分数来, 才能够开展下一步的行动。要是裁判打分的速度慢下来诶, 那整个训练状况, 就得停下来等着。这情形, 就如同一场接力赛跑, 即便奔跑得最为迅速的参赛选手, 只要是交棒这个环节生发出问题来了, 那整体之下所体现出来的成绩就会受到拖累。甚至更为讽刺的是, 数量极为庞大的AI研究团队, 压根就未曾严谨认真地去测试过这个所谓“裁判打分”的速度。大家是默认采用一种处于主流地位的深度学习框架的默认模式来运行的, 至多也就开启一档名为pile的加速选项, 而后便不再作进一步深入探究了。这三位从事研究工作的人, 决定去打破掉这个常规的做法, 他们依靠自身力量打造了一套借助C语言编写而成的推理引擎, 其底层方面是依托于一个称作ONNX的工业级推理框架, 之后同现有的各类方案展开了一回严谨的速度方面的对比, 他们所检测得到的结果, 其中一部分印证了直观的感受, 而更多的部分则是使人十分意外。---**一、先搞清楚裁判员在整场比赛里占多大份量**在深入结果之前有一件事必须说清楚否则容易被数字带着走。在 RLHF 的一整个训练步骤进程当中, 奖励模型进行打分仅仅是其中的一项环节。实际上, 真正耗费时间占比大的部分, 乃是促使 AI 生成候选回答的那个阶段。源自 Chat 体系的相关研究数据表明, 生成候选回答这一举措占据了整套训练步骤超过 85%的时间, 而模型参数进行更新大概占 10%, 奖励模型打分蜷缩于剩余的极少部分时间里。这究竟意味着什么意味着就算将打分速度提高两倍, 整体训练时间所减少的幅度也是比较有限的, 因为那占据85%比例的大部分因素你未有变动。研究者们对这个背景呈现得十分清晰, 并非是要否定优化打分速度的价值, 而是期望读者去明白: 这项研究给出的是“在这个特定环节能够达到多快速度”的工程方面的数据, 而并非是“采用了这个方案整个训练就能快多少”的绝对肯定答复。能够释放资源, 这正是打分速度的实在价值所在, 更快的打分引擎虽不会直接让训练时长缩短, 然而它所占用的CPU资源以及GPU资源更少, 而这空出来的那部分计算能力, 能够使生成回答的过程得以更充分地运用。带着这个认知再去看具体数字感觉就不同了。---**二、怎么测才算测得准独立重复启动的方法论**有一个执念贯穿这次研究的方法, 这个执念是, 绝对不相信单次测量得出的结果。很多看不见的因素, 会对计算机的运行速度产生影响。操作系统或许会随时将CPU分配给其他程序, CPU的时钟频率在动态变化, 内存的物理排布方式同样会对性能造成影响。这些因素共同作用, 能够使一个本身更慢的方案, 在某次测量中看上去比更快的方案还要快。卡内基梅隆大学的研究者, 曾专门证实过这点: 使用同样的代码与硬件, 仅因某些环境变量存在差异, 所测出来的性能结论便可能完全相反。该研究团队, 所采用的解决方案为, 每次进行测试时, 均以独立启动, 全新进程的方式来运行, 其中, C引擎需运行五次, 至于系列基准方案, 则要在GPU上跑五次, 且同时还要在CPU上跑三次, 需注意, 这是由于在CPU上, pile每当碰到新的输入长度时, 都得重新编译, 要是跑五次的话, 实在是太过耗时。而且, 每次启动这些测试时, 都要针对60条测试数据, 分别给出分数。在此基础上, 取每次启动时的中位延迟, 也就是p50, 还有95百分位延迟, 即p95, 将其作为那次启动对应的代表值。之后, 再针对多次启动的这些代表值, 去求取均值以及95%置信区间。这种采取“均值的均值”的做法, 看上去麻烦异常, 可它将运行环境的随机波动, 转化成了在统计范畴内能够被量化的事物。对于此, 研究团队作出规定: 唯有在两个方案的置信区间全然不存在重叠状况的时候, 才能够算得上是具备真正意义的性能差异。公司的hh - rlhf数据集提供了测试数据, 这一数据集是真实的人类偏好对话数据集, 恰好契合RLHF的使用场景。主测试集是借助固定随机种子采样出的60条数据, 此外还运用不同种子又采样了两份60条数据, 以及一份150条数据, 将其用于确认结论并非由那60条特定数据导致的偶然结果。---三、自己制作的C引擎, 与四大对手进行比拼, 在CPU方面, 赢得一点悬念都不存在。来进行测试的, 是研究团队, 其有两个真实的奖励模型以供选用, 用来作为主力的, 是属于开源的v3 large奖励模型, 而被当作备用的, 则是large判别器奖励模型, 两种模型采用的并非相同的分词方式, 这样一来, 就算结论在两个模型之上都能够成立, 其说服力也会变得更强。对手阵营存在三位, 其一为Face的默认eager模式, 此乃绝大多数RLHF代码库开箱即用的途径, 其二是pile, 其可在不导出模型的状况下将操作融合成更高效的内核, 其三是借助封装模型的HTTP服务, 这对诸多实际工程里“通过网络接口调用奖励模型”的部署方式予以模拟。以“摧枯拉朽”来形容的是, 在CPU之上所呈现出来的结果。其中, 自制C引擎的p50延迟为335.9毫秒, 而其置信区间是。297.7, 374.0毫秒三个进行基准检测获取的方案成绩各是, HF eager模式呈现出602.4毫秒, 581.6毫秒, pile为628.8毫秒。C引擎所对应的置信区间上限是374毫秒, 这个数值远远低于任何一则基准方案里提及的置信区间下限551毫秒。运用统计学所采用的Welch t检验以用于验证它, 每一组相互比较得出的p值均小于0.001, 这种状况下单方面的差异显著性是不用怀疑的。C引擎到底快了多少数值? 将其与最接近的对手相比较, 在点估计方面, 它快了大概是1.73倍之多。哪怕是采用最为保守的形式来进行计算, 也就是用C引擎置信区间的上限去对比置信区间的下限, 结果也依旧存在着大约1.4倍的差距。---**四、GPU上的意外反转pile反过来赢了**GPU上的故事就没那么简单了。首先来看一下结果, C引擎在GPU p50环境下延迟为27.4毫秒, HF的eager模式为57.2毫秒, 还有一个未知方式下是62.8毫秒, 而pile的延迟是19.0毫秒。C引擎明确清晰地战胜打败了eager模式, 并且两者的置信区间不存在重合重叠情况。不过呢, pile却又反过来将C引擎击败胜利了——19.0毫秒对比27.4毫秒, 这两者之间的置信区间同样也是不存在重合重叠的情况。这个结果致使研究者略微存有些许意外之感, 然而研究者选取如实予以呈现, 并非尝试将其解释消除掉, 而是如实呈现它。更加让人意想不到的是, 当把观察的角度从中位数拓展到尾部延迟p95, 也就是在最差情形下的表现, 两者之间的差距反倒增大了。而pile仅具有25.6毫秒的p95。也就是说, 在碰到偶发性程度的坏情况的时刻, C引擎的表现甚至会更加糟糕。C引擎的GPU p95是116.2毫秒。这把一个看上去挺直觉的推断给打破了, 导出成为固定的 ONNX 图, 难道不应该是相较于动态编译而言更稳定, 更不容易出现极端的值吗, 经过实测得到的结果表明, 至少在这台硬件以及这个工作负载的情形下, 并非是这样的。固然, pile存在其自身的代价, 每当碰到新的输入形状即不同长度的文本, 其都得重新编译, 这会引发一次极大的延迟峰值。倘若在训练过程中, 文本长度频繁变动, 并且恰巧碰到缓存里所没有的长度, 代价就会颇为显著。此次研究的60条固定测试数据并未专门涵盖这个极端场景, 所以pile在shape cache未命中时究竟会有多慢, 依旧是个未解决的问题。---**五、C语言本身没有功劳真正的英雄是执行引擎**发现CPU上面存在的大幅优势之时, 当下最为自然而然的一种解释便是, C语言其自身运行起来是比较快速的, 可要是太慢了的话。可是, 研究那个团队专门特意去做了一回隔离着的实验, 最终结果却把这个解释给推翻掉了。他们采用同样的一个ONNX 会话, 同样的一个模型, 相同的同一套库, 换用正常普通的脚本来进行调用, 其他所有条件均保持完全不变, 之后再重新去计时。其结果为349毫秒, C引擎则是335.9毫秒, 若将置信区间叠加起来的话会怎, 这两个数字在统计层面呈现出的状是好比“打平”般的情形, 实在系完完全全不存在能够被信赖的差异情况切实决定快慢实质的, 乃是ONNX这个执行引擎自身, 并非运用何种语言对其加以调用。存在这样一种情形, ONNX与pile都在施行类同之事, 即针对神经网络的计算图预先做好改进、融合, 以规避在eager模式里每一步操作均需解析指令所产生的额外耗费, 这种情况恰似驾驶车辆, 是电动车的电机决定着加速性能状况, 并非方向盘究竟是以木头所制还是用皮革包覆的。那C究竟是在何处确实体现出快的水准呢? 是分词器。研究团队所进行更换的, 乃是C原生的分词器, 其速度于变换后, 从原本的64.3微秒改变成了245.8微秒, 变慢的幅度大约为3.8倍。然而, 分词所耗费的时间, 与一次全部完全的前向传播相比较, 恰似一滴水跟一桶水的状况, 对于总的延迟所产生的影响, 几乎能够被忽略不计。还有一项优化, 有两个研究者原本觉得会产生效果, 然而其结果却是完全没有效果, 这项优化是去掉额外的内存拷贝, 也就是zero - copy传输, 以及预先分配好每次调用所需的内存缓冲区。存在一个约1KB的数据拷贝, 还存在一两次堆内存分配, 将它们与几百毫秒的计算相比较, 在量级方面相差了三到五个数量级, 所以当然测不出差距。有意思的是, 研究者表示他们最早进行zero - copy实验的时候, 确实看到了约10%的“改善”, 但是重跑相同的基准代码, 且未对其进行任何修改, 同样的波动又再度出现了。这正是单次测量不可靠的典型例证。---错误填充致使速度急剧下降, 而批处理策略恰恰是最为常被低估的变量, 这是第六强调的内容。截至此处, 从事研究的人员起始去检测另外一个于工程实践当中极为平常的情景, 即批处理, 换句话说就是一回录入多条数据的分类操作。在实际进行布署时, 奖励模型常常需要同时去处理一批候选回答, 并非逐一来处理。面临的问题在于, 一批之中各条数据的文本长度常常是不一样的。神经网络所进行的矩阵运算要求同一批数据一定得等长, 故而标准做法是将短的数据“填充”至和最长的那条相同的长度。这便是“朴素填充”naive。听起来合情合理但研究结果显示这是一个代价巨大的默认行为。于CPU之上, 先是批大小为1, 此乃不进行批处理而是逐条打分, 而后至批大小为2, 此时朴素填充方案之吞吐量, 从原本的3.10条/秒, 一下子直接跌落至0.61条/秒, 当批大小变为8时, 更是又下跌至0.40条/秒。这并非所谓的“多一些开销”, 简直就是跌落悬崖呀。批量处理非但没有使速度提升, 反倒让速度化为了原来的八分之一。当一批数据之中存在一条很长的文本时, 整批数据都务必要被填充到那个长度, 原因就在于此。矩阵运算所需付出的代价基本上是与序列长度呈现出成正比的状态。所以一条长文所带来的填充开销会依照比例同等程度地放大整批数据的计算量。批的规模越大, 冗长文本混入其中的概率就越发高, 平均填充开销也就越大, 速度反而会变得越来越慢。与之相对应的解决方案被称作“长度感知分组” -, 即将那些长度彼此相近的文本划分到同一批次当中, 如此一来, 填充所造成的浪费便能够被降至最小程度。运用此种方法, 当批大小为4的时候, CPU的吞吐量返回到2.83条/秒, 这一数据接近于批大小为1时的基准水平3.10条/秒, 然而却依旧没办法超越它。这是由于, 在这台机器的CPU环境里头, ONNX处理一批数据时, 其方式乃是将所有行合并成一个更大的矩阵, 之后进行串行计算, 并非真正地并行处理多行, 故而, 总计算量依旧与总token数成正比, 并未因批处理而获得并行红利。GPU所处状况截然相反, 契合GPU擅长并行之直觉。朴素填充于批大小为2时, 吞吐量由39.8条/秒降至11.1条/秒, 跌幅同样具震撼性。长度感知分组处批大小为2时, 将吞吐量径直提升至51.5条/秒, 较批大小1时快约30%, 且随批大小增大, 吞吐量持续攀升批大小8时达53.7条/秒。GPU并行计算核心可使同一批中长度相近数据真正同步处理, 于是此处批处理之优势才切实得以实现。此发现, 被于三个各异之系统展开分别验证, 这三个系统为C引擎、HF eager模式、ONNX , 又于另一模型之上进行重复验证, 同时还在拥有150条数据的更大测试集里重新测量, 最终结论全然一致。研究者表达的看法为: 朴素填充并非处于中性状态, 它是那种具有主动性质的有害情形。并且, 这种害处压根是完完整整隐晦于默认配置当中的, 要是不主动去进行测量的话, 那是根本不会知晓的。---**七、并发访问的幻想加多少线程都没用**第三个让研究者感到意外的结果来自并发测试。一种平常的工程直觉为: 要是有一个引擎去服务多个同时发生的请求, 理应能够更充分地运用计算资源, 进而提升总吞吐量。研究者对两种方式做了测试: 其一为多个同时发生的请求共同使用同一个引擎实例, 其二是每个同时发生的请求拥有自身专属的引擎实例。共享实例得出的结论是, 吞吐量在并发从2增长到并发8时, 几乎未曾出现增长的情况, 即便增长幅度最多也仅仅为11%, 远远达不到翻倍以及翻四倍那种幅度。延迟呈现出大致随着并发数呈线性增长的态势, 这可是请求在排队而非并行执行的典型信号。简单来讲, 请求是接踵而至地在引擎前方排队, 并发情况出现也无法促使处理速度加快。进行了HTTP接口的测试, 测试结果相同, 从并发数量为1开始, 一直到并发数量为8, 吞吐量始终处于0.53条每秒至0.65条每秒的范围之内, 几乎一点儿抖动都没有。独立实例的结论, 那可是更糟糕的。在CPU上面, 当并发弄到4的时候, 独立实例的吞吐量, 相比共享实例来说, 下降的幅度大, 都已经低了43%到59%这么多的, 要是并发增至8的时候, 那就更是急剧下降, 下降到差不多40%哪里去了。这里其原因在于, 就是每个ONNX会话, 都会启动属于自己的线程池子, N个独立的会话存在的话, 那就会有N个线程池在那儿, 去竞争同样一些物理CPU核心, 结果就互相拖累起来了。GPU之上的情形显得更为极端, 模型于并发为2的时候, 独立实例相较于共享实例慢了大概19倍, 待到并发达到8时, 两个模型全都因“显存不足”即OOM而崩溃, 并且进行五次启动但没有一次能够成功, 研究者在之后单独对并发5、6、7的状况予以测试, 结果发现同样全部出现OOM, 这台配备有显存的GPU, 是8个独立的ONNX CUDA会话将它的显存给用完了, 实际能够承载的独立会话上限大致是在4到5个之间。所得出的结论清晰明确, 于这一特定硬件之上, 能够提升吞吐量的唯一具备实效的办法乃是长度感知的批处理行为, 增添并发性举动, 不管是采用共享实例方式还是独立实例方式, 均无法产生作用效果, 而独立实例的运用还会致使情况向着更为糟糕的方向发展。---**八、诚实的科学那条没能重现的数据**这篇论文存在一处颇能给人留下深刻印象的地方, 其并非是某个看上去颇为漂亮的数字, 而是研究者在这篇论文当中, 坦然而诚实地承认了这样一个结论, 即“没能重现”。在对两个模型展开对比之际, 早期得到的数据表明, 于HF eager模式下, 其中一个模型的p50延迟为1351毫秒, 然而另一个仅有602.4毫秒, 二者相差约2.25倍。研究者撰写称, 此数字后来在一次全新的单独验证里未被复现, 再次运行得出的结果是725.5毫秒 、468.1毫秒, 且两个模型的排名彻底颠倒了。研究者不会悄悄去删除原始数据, 而是将其留在了表格当中, 并且在附近添加了注释, 明确向读者告知这条数据乃是“3次启动的测量结果, 后续在独立重跑里未获验证, 对于两个模型之间的比率需谨慎对待”。他们承认这属于整篇论文里唯一那个未得到多种方式交叉验证的结论, 并且还表示这恰恰就是单次测量亦或少量测量究竟有多不可靠的切实例子。在学术论文当中, 这种自我揭示的诚实并不常见, 它在某种程度上, 是对全文方法论精神的最好注解。---**九、实际使用建议根据你的硬件和容忍度做决定**经受了上面所说的这些测试之后, 研究者所给出的工程方面的建议, 十分具体, 然而却有着很强的条件性, 并非是那种像用C 就算全部搞定这样不顾多种情况一概而论的讲法。要是你的奖励模型在CPU上运作, 那最具价值之处并非编写C引擎, 而是将模型导出为ONNX格式, 之后借助调用ONNX去运行。仅这一步就能获取近乎全部的速度提升, 原因在于速度源于执行引擎, 并非源于语言。C引擎于CPU上额外所能带来的成果, 仅仅是稍快一些的分词速度, 对于整体延迟的贡献极小。诸如零拷贝传输、预分配缓冲区这类底层优化根本不值得耗费时间。假设你的奖励模型运行于GPU之上, 且你乐意承受pile的初始编译时长, 以及在偶尔碰到新输入长度之际所产生的重新编译开支, 这样的情况下, pile属于更为简单并且更加快速的选项——它无需经历导出环节, 也不需要独立引擎, 其中位延迟以及尾部延迟均更低。要是输入长度分布极为不稳定, 重新编译的代价让人无法接受, 那ONNX方案依旧是相较于HF eager模式要好得多的备选方案。不管是何种硬件, 批处理策略都得认真予以对待。将长度差不多接近的请求划分到一组去进行批处理, 此项操作本身在计算方面几乎不会耗费什么时间, 然而其效果在于, 在CPU上能够避免吞吐量出现崩塌的情况, 在GPU上能够达成吞吐量真正实现翻倍。这种优化被埋藏在默认配置当中, 从来都没有人去进行检查, 可它却是影响最为巨大的单一变量。并发这方面, 增添更多线程, 或者为每个请求配备专属引擎, 在这样的硬件规格情形下, 乃是无效并且甚至有害的策略, 倒不如将精力投放于批处理之上。---结语: 皆是源于一次测量带来的欺骗, 才会有每一个使你感到意外的发现。实质上, 该篇研究要传达的并非仅仅是, “运用ONNX要远比eager模式来得快速”, 以及“不要去进行朴素填充”此两条研究结论。其更为核心关键的所传达的信息乃是: 在这领域范围当中, 依据直觉以及单次测量做出而来的各项决定, 是存在极为可观的概率会是错误不正确的。pile于CPU之上运行时比C引擎要慢, 然而在GPU之上运行时反倒更快, 零拷贝优化初次看到时有10%增长, 再次跑基准代码, 并未篡改任何内容之时, 相同的波动再次出现, 与哪种于eager模式下较慢, 三次测量及再度单次测量给出的结论完全相反。这些并非是研究者无意间所犯的错误, 而是测量自身的噪声在肆意作祟。这同样是为何, 那“将所有结果汇报成多次独立启动的均值以及置信区间”这般的方法论原则, 被研究团队视作和随便哪一条具体数字同等重要的缘故所在, 他们觉得呀, 这种测量习惯是值得被整个RLHF基础设施社区予以采纳的。将那些正在搭建甚至维护RLHF训练流水线的工程师而言, 这篇研究的价值并非在于给出一个能够直接复制粘贴的“最优方案”, 而是在于供给了一组可信赖的一组, 可以信赖, 方法论另外, 以及一组于受控, 于受控是要注意的条件下得出的参考数据点。针对更广泛一众读者来说, 它是一个生动的案例: 在计算机性能这件事情上, 你所认为的不一定是真实的, 然而找出真相所需的并非是较好的, 较好的这种直觉, 而是更具耐心的测量, 测量是找出这个真相的必要条件。为有意愿深度探究全部实验细节, 进而查看完整表格数据或者拿取代码的读者而言, 能够借由论文编号arXiv:2607.19712寻觅到完整论文, 研究团队还把C引擎、测试框架以及分析脚本通通开源了, 代码仓库地址于论文末尾是有提供的。---QA问题一: 基于ONNX进行推理的RLHF奖励模型, 相较于采用eager模式所呈现出的速度, 具体快出了多少呢?A: 在CPU之上, 对于ONNX推理, 不管是采用C方式还是进行调用, 其p50延迟大概在335至349毫秒的范围, 然而eager模式下大约为602毫秒, 速度快了大致1.7到1.8倍之多, 并且置信区间完全不存在 。不过呢, 在GPU上面的情况则是, pile耗费19毫秒, 反而要比ONNX C引擎那种方式所花费的27.4毫秒更快, 而且这种差异同样在统计方面呈现出显著的状态。Q2奖励模型推理中朴素批量填充到底会慢多少A: 影响是相当严重的, 在CPU上, 从批大小为1的时候每秒3.10条, 当用朴素填充让批大小变为8时, 吞吐量一下子就跌到了每秒0.40条, 两者相差大概7到8倍, GPU这边也是出现了类似的跌幅。在改用长度感知分组批处理之后, GPU的吞吐量能够恢复并且超过单条处理的水平, 然而CPU, 由于缺乏并行计算能力, 批处理本身没办法带来提速。Q3给奖励模型服务加更多并发线程能提高吞吐量吗在论文测试的硬件方面, 不行。当共享单个引擎实例的时候, 并发从二提升到八, 吞吐量增涨最多仅仅百分之十一, 延迟还近乎呈现线性增长, 这表明请求处于排队状态而非并行执行状态。要是每个请求采用独立引擎实例, 情况更糟糕, 在CPU上会因线程池竞争致使吞吐量降低, 在GPU上到并发八的时候, 两个测试模型都因显存不足而崩溃。