InfraDev:测试通过了,任务真的完成了吗?

笔记日期: 2026-11-02 · 作者: Zhongzhu Zhou
论文: InfraDev: Can Coding Agents Develop AI Infrastructure, and How Can We Tell?
论文作者: Yangshen Deng、Jiaqi Ruan、Yeqi Huang、Nick Lau、Guangming Sheng、Luo Mai
arXiv: 2610.36589 · 版本: v1,2026-10-27

1. 这篇论文首先改变的是裁判

假设我们让一个编码 agent 优化训练端到推理端的权重同步:只发送发生变化的参数。它交回补丁,最终权重也正确,仓库附带的测试全部通过。但仔细观察通信,发现它每次仍然发送完整参数。这个任务算完成了吗?如果减少通信就是需求本身,答案显然是否定的。

类似问题也会出现在缓存和 CUDA graph 中。第一次调用得到正确结果,不代表第二次调用还能正确更新状态;eager 模式运行正常,不代表把 GPU 工作捕获成图以后,重放时仍能执行需要变化的逻辑。基础设施软件的正确性包含数值、状态、执行模式和资源消耗,不能只看输出张量的形状或者一次运行有没有报错。

InfraDev 围绕这个问题构建了 36 个大型代码改动任务,来源是 Megatron-LM、verl 和 vLLM。它最值得读的地方并不是又做了一张难度更高的榜单,而是把“怎么出题”和“怎么判题”放在同一个流程里:先补上原有测试没有覆盖的隐藏探针,再改写题目,明确探针要求的接口和行为,避免更强的测试变成让 agent 猜函数名的游戏。

最有解释力的结果是:六个模型总计提交 216 份补丁,其中 102 份通过原有测试,加入隐藏探针以后只剩 69 份。这里减少的是同一批补丁在不同裁判下获得的成功数,直接说明评测方法会改变我们对能力的判断。它不等于“剩下 69 份已经被证明完全正确”,也不等于“被淘汰的补丁毫无价值”。

最好的被测配置解决 14/36 个任务,即 38.9%。读这个数时,需要同时记住任务选择、运行预算、模型使用的 harness,以及评分口径。它不是任意真实需求都能套用的成功概率。本笔记基于完整 20 页 v1 正文与附录 A–D;下面的公式推演、解释性算例和后续实验建议,会与作者实际报告的结果分开。

图 1:根据论文图 1 与第 3.1–3.2 节重新绘制。构造阶段生成题目和裁判;被测 agent 在另一个阶段提交自己的补丁。

2. 前置知识:程序的输出不只有一个张量

2.1 数值、状态和资源是不同的观察对象

把一次基础设施操作写成状态转移,会更容易理解评测为什么漏掉问题。令 xtx_t 为输入,sts_t 为持久状态,mm 为执行模式,ee 为硬件及软件环境,可以用下面的记号表示:

(yt,st+1,rt)=F(xt,st;m,e),rt=(time,peak memory,traffic).(1)(y_t,s_{t+1},r_t)=F(x_t,s_t;m,e), \qquad r_t=(\text{time},\text{peak memory},\text{traffic}). \tag{1}

这是为了讲解而引入的模型,并非论文提出的新公式。普通单元测试可能只检查 yty_t;状态测试还要检查 st+1s_{t+1},或者继续运行,观察后续输出;资源测试检查 rtr_t;模式测试则改变 mm,例如从 eager 切换为图捕获和重放。

这也解释了为什么不能总把“正确性”和“速度”看成两件互不相干的事。如果任务明确要求减少通信,那么通信没有减少就是需求没完成。如果任务根本没承诺性能,裁判又不能事后给它加上一个隐藏的速度门槛。资源是否属于正确性约束,取决于题目,而不是取决于评测者更喜欢哪种实现。

环境同样进入判断。GPU 类型、编译组件、通信库和显存容量都会影响可运行的测试及其耗时。InfraDev 让参考补丁的校准和候选补丁的评分使用同一任务环境、同一 GPU 类型,这能减少一类不公平,但不能把分数变成脱离硬件条件的常数。

2.2 多卡梯度:单卡正确为什么还不够

考虑有 RR 个 rank 的数据并行训练。假设每个 rank 对全局目标的权重相同,本地损失是 LrL_r,则全局损失和梯度应该是:

L=1R∑r=1RLr,g=∇L=1R∑r=1R∇Lr.(2)L=\frac{1}{R}\sum_{r=1}^{R}L_r, \qquad g=\nabla L=\frac{1}{R}\sum_{r=1}^{R}\nabla L_r. \tag{2}

all-reduce 的求和结果只给出分子;如果后续没有除以 RR,实际使用的就是 RgRg。单卡时 R=1R=1,求和和平均完全一样,因而无法区分两种实现。形状检查也没有用,因为两种结果的形状相同。

用一个手算例子看得更清楚:两个 rank 的标量梯度分别是 2 和 6,正确平均是 4,直接求和却得到 8。这个例子只解释数学,不是 InfraDev 的新增实验。论文附录 D 确实将“对数据并行梯度求和而不是平均”列为算法错误。

在最简单的更新里,这可能表现得像学习率放大;但加入梯度裁剪、优化器状态、混合精度或者不同参数组以后,未必还能用一个学习率倍率解释。反过来,如果各 rank 的本地批量不同,正确权重也未必是简单的 1/R1/R。所以修复的起点应当是目标函数和约定,而不是看到求和就机械地加除法。

2.3 三种补丁是三种对照

参考补丁(golden patch) 来自真实合并的改动,提供校准对象。对抗补丁(adversarial patch) 故意违反某个承诺,却能通过原有测试,用来证明旧裁判存在盲区。空壳补丁(hollow patch) 保留新增接口,但让新增函数一调用就抛异常,用来排除“只检查名字存在”这种伪验证。

这几种对照都不是完整正确性的证明。参考实现也可能有未发现的缺陷;对抗补丁只能覆盖有限错误;空壳补丁可以揭穿只检查导入的探针,却不能揭穿所有语义捷径。它们的作用,是让测试本身接受正、负对照的挑战,而不是因为测试文件存在,就默认裁判已经可靠。

3. 36 个任务到底代表什么工作

作者从 2025 年 1 月到 2026 年 9 月三个仓库的 21,389 个合并 PR 中筛选任务。规则包括已合并且未回滚、至少改动 1,000 行、加入新测试,再由领域专家挑出涉及核心功能的改动。最后平均每个任务触及 17.4 个文件、1,818 行代码;36 个任务中有 20 个需要多 GPU。

这个选择有明确倾向:它考察的是跨模块的大改动,而不主要是小型缺陷修复。任务包括 19 个功能新增、15 个性能优化、1 个重构和 1 个 bug fix。按仓库划分,Megatron-LM 的训练任务有 19 个,verl 的 RL 任务有 7 个,vLLM 的推理任务有 10 个。

图 2:按论文表 1 重绘任务构成。数字表示任务数,不表示文件数、测试数或模型运行次数。

这样的筛选有利于得到明确的前后版本和真实工程终点,也会排除一些同样困难的工作。例如,一个只改几十行却很微妙的数值修复,可能进不了集合;人工挑选也可能偏向更容易装进稳定评测环境的任务。所以这些分数适合描述相近范围的基础设施开发,不宜推广成所有编码工作的总体成功率。

论文指出,所选 36 个任务里,有 24 个的原有测试没有数值结果断言;15 个性能优化任务中,有 13 个没有检查承诺的节省。这是所选任务及其评分测试的观察,不应扩写成“这些项目整体不做数值和性能验证”。真实项目还可能有更大的集成测试、发布前测量或人工审查,它们未必被当前任务评分套件纳入。

与单个 GPU kernel 的生成相比,这组任务把数学、分布式执行、状态和仓库集成放在一起。与使用训练框架完成科研任务相比,它要求 agent 改动框架本身。这个工作单元的变化很重要:一个函数单独运行得快,并不能保证接到调度、缓存和通信链路里仍然成立。

4. 隐藏探针和题目为什么要一起生成

4.1 先找到旧测试接受的错误解

构造流程先总结 PR 的承诺,再生成能够通过原测试但违反承诺的补丁,随后针对缺失要求写探针,循环修订。附录 A 对正文简短算法作了关键补充:每个探针必须在参考补丁上连续运行三次都通过,而且不能跳过;它还必须拒绝改动前快照、空壳补丁和对抗补丁。对抗补丁在原测试上的成绩则不能低于参考补丁。

用 GG 表示参考补丁,SS 表示改动前状态,HH 表示空壳补丁,AiA_i 表示各个对抗补丁,目标可概括为:

Tprobe(G)=pass,Tprobe(S)=Tprobe(H)=Tprobe(Ai)=fail.(3)T_{\mathrm{probe}}(G)=\mathrm{pass}, \qquad T_{\mathrm{probe}}(S)=T_{\mathrm{probe}}(H) =T_{\mathrm{probe}}(A_i)=\mathrm{fail}. \tag{3}

三次通过主要是在筛掉明显不稳定的测试。它不等于证明误拒率很低。假设一个测试每次独立地以概率 qq 偶发失败,那么连续三次通过的概率是 (1−q)3(1-q)^3。仅作说明,若 q=0.1q=0.1,这个概率仍有 0.729。实际资源噪声还可能相关,独立假设也未必成立。增加重复次数和报告波动,是与“有正负对照”不同的另一个维度。

算法 1:构造并验收隐藏探针

以下编号伪代码整理自正文算法 1、附录算法 2,并补入附录说明的轮次上限行为。

1. 读取 PR 承诺、参考补丁、改动前快照与原有测试。
2. 生成违反承诺但能通过原测试的对抗补丁。
3. 针对缺失的数值要求和行为要求编写隐藏探针。
4. 构造接口相同、函数体执行即失败的空壳补丁。
5. 每个探针在参考补丁上连续运行三次,全部通过且无跳过。
6. 要求探针拒绝改动前状态、空壳补丁与各个对抗补丁。
7. 要求对抗补丁在原测试上的成绩不少于参考补丁。
8. 如验收失败,修订探针和对抗补丁,重新检查。
9. 达到轮次上限仍不通过,则该 PR 不附加探针。
10. 验收通过后保留探针,并记录它检查的行为要求。

图 3:根据附录 A 重绘探针验收的正负对照。它证明对已选样例有区分能力,不证明能识别所有错误程序。

第 9 步容易被忽略。论文说清了生成失败时怎么办,但没有给出一个简明的逐任务覆盖表,列明每个承诺对应多少探针、尝试过哪些错误补丁、哪些任务没有得到探针。没有这张表,就不应默认 36 个任务都得到了强度完全一致的增强裁判。未来若补上这样的覆盖记录,会有助于区分任务本身困难和裁判特别严格这两种因素。

4.2 数值裁判可以从哪里来

附录列出四种来源:已有实现路径、某个不变性、手算参考值,以及总应成立的数学性质。四者并不等价。旧路径适合检查优化前后等价,却可能共享旧缺陷;不变性可以发现不一致,但未必确定唯一正确结果;高精度的小规模计算能定位数学问题,却不覆盖长生命周期;单个数学性质便宜清楚,但可能被过于简单的错误函数满足。

例如,对支持集上概率为正的同一个分布,KL 散度为零:

DKL(p∥p)=∑i:pi>0pilog⁡pipi=∑i:pi>0pilog⁡1=0.(4)D_{\mathrm{KL}}(p\|p) =\sum_{i:p_i>0}p_i\log\frac{p_i}{p_i} =\sum_{i:p_i>0}p_i\log1=0. \tag{4}

这里第一步代入相同分布,第二步利用比值为 1,最后利用 log⁡1=0\log1=0。它说明论文提到的一个不变量为何成立,也立刻暴露局限:如果函数对任意两分布都返回零,它照样通过这个例子。因此,一个好的数值探针集合应把不变量与非平凡输入的参考结果组合起来,而不是用更多重复检查制造覆盖率的错觉。

4.3 隐藏测试不能要求题目没说的东西

加强测试以后,如果测试导入某个新类名,而题目从未说明名字,那么 agent 即便写出同等功能,也可能得零分。InfraDev 因而抽取接口契约,并把被检查的行为和符号交给题目生成阶段。交接记录不包含探针代码;出题 agent 还会看到参考改动等构造资料,被测 agent 则只收到最终题目和改动前仓库。

题目明确模块路径、函数签名、类型、张量形状、配置开关、行为与执行要求;算法、公式、数值常量、容差和验证策略则归入需要隐藏的解法。一个 linter 检查是否漏掉接口,另一个 checker 检查是否泄露解法。作者把模棱两可的项目省略掉。

这个划分有道理,却不是天然清晰的边界。某些接口本身就会明显限制算法;某个数值常量也可能是合法需求的一部分。省略它未必更公平。真正需要回答的是:它是外部调用者要求的行为,还是参考实现恰好采用的手段?这个问题不能单靠“隐藏更多内容”解决。

算法 2:生成足够明确且不直接给出解法的任务契约

下面是对第 3.1.2 节流程的组织性改写,不是作者另行测量的一套新算法。

1. 抽取原测试和隐藏探针会调用的全部接口。
2. 记录每项行为、适用范围及需要支持的执行模式。
3. 区分外部必须满足的要求与实现者可以选择的做法。
4. 根据 PR、参考改动、测试和交接记录起草题目。
5. 写明名字、签名、类型、形状和配置入口。
6. 不提供隐藏探针代码,也不直接给出解题步骤。
7. 用 linter 检查遗漏的契约符号。
8. 用 checker 检查泄露的解法信息,修订直到通过。
9. 把最终规格与改动前代码状态交给被测编码 agent。

附录 B 的题目模板属于论文的被测设计,不是对读者下达的执行指令。它还要求自主完成、导入与收集检查、真实运行、多 rank 验证和回归保护。这能减少过早停止、忘记运行等流程错误,但也意味着题目改写不只增加接口名,还增加了工作方式指导。理解提示词消融时,必须把这点算进去。

5. 评分口径:分母和完成条件都不能省略

5.1 测试通过率先按任务计算,再做平均

对任务 pp,论文把参考补丁运行时收集到的测试数记作 NpN_p,其中包括参考补丁在该硬件上失败或跳过的用例。若候选补丁通过 apa_p 个用例,单任务分数与最终平均为:

sp=apNp,Passed=100P∑p=1Psp.(5)s_p=\frac{a_p}{N_p}, \qquad \mathrm{Passed}=\frac{100}{P}\sum_{p=1}^{P}s_p. \tag{5}

这里每个任务权重相同,不是把所有用例混到一个大分母里。举个说明性例子:任务甲有 10 个用例,全过;任务乙有 100 个用例,过 50 个。按任务平均是 (1+0.5)/2=75%(1+0.5)/2=75\%;按所有用例混合统计则是 60/110≈54.5%60/110\approx54.5\%。两者回答的问题不同。InfraDev 选前者,可以避免某个参数化测试特别多的任务支配榜单。

空补丁、缺失补丁和无法应用的补丁计零分,不从分母中消失;评测系统本身的故障则排除并单独统计。这样既不奖励放弃,也不把环境故障错误归因给模型。但完整报告仍应给出排除数量及其任务分布,因为若系统故障集中出现在某些配置上,比较仍然可能受到影响。

5.2 “解决任务”并不总能简写成全部用例通过

正文第 3.2 节的精确定义是:候选补丁通过的用例数不少于参考补丁。若参考补丁通过 gpg_p 个用例,文字对应的规则是:

Rp=1[ap≥gp],Resolved=100P∑p=1PRp.(6)R_p=\mathbf1[a_p\geq g_p], \qquad \mathrm{Resolved}=\frac{100}{P}\sum_{p=1}^{P}R_p. \tag{6}

但若干表格图注和叙述又将它简称为“每个测试都通过”。当参考补丁本来就通过全部用例时,两者一致;当参考补丁有失败或跳过时,就不一定一致。由于方法部分明确允许后一种情况,本笔记按校准后的精确定义理解,同时保留这个文字口径差异,不把简写升级成更强保证。

还有一个更细的逻辑问题:通过数相同,不一定通过的是同一组用例。令 GpG_p 为参考补丁通过的集合,ApA_p 为候选补丁通过的集合,则更强的条件是:

Gp⊆Ap⟹∣Ap∣≥∣Gp∣,(7)G_p\subseteq A_p \quad\Longrightarrow\quad |A_p|\geq|G_p|, \tag{7}

但反方向不成立。比如参考补丁通过 1、2、3,候选通过 1、2、4,数量相同却丢掉了参考补丁本来通过的第 3 个用例。这是对论文书面评分定义的逻辑分析,不是说某个已报告结果实际利用了这个漏洞。只要说明评分是否还检查用例身份,就可以消除歧义。

5.3 “32%”究竟是哪一个分母

总共有 6×36=2166\times36=216 份提交;原测试接受 102 份,加入探针后接受 69 份。于是原测试成功者中被推翻的比例是:

102−69102=33102≈32.35%.(8)\frac{102-69}{102}=\frac{33}{102}\approx32.35\%. \tag{8}

这就是摘要中 32% 的来源。如果以所有提交为分母,接受率下降则是 33/216≈15.2833/216\approx15.28 个百分点。前者问“原来判成功的里面有多少被推翻”,后者问“总体接受率变了多少”。把两者笼统写成“准确率下降 32%”,既混淆条件概率,也把测试接受误写成独立真值下的准确率。

图 4:根据论文图 2 与表 4 重绘。条形表示 36 个任务的解决率,标注为从报告百分比还原的整数任务数。

以 GPT-6 Sol 为例,结果从 21 个成功降到 14 个,下降约 19.4 个百分点,也就是原成功数的三分之一;HY4 preview 从 17 个降到 13 个,下降约 11.1 个百分点。新探针对每个配置都产生影响,但影响不完全相同。它不是简单地统一压低分数,而是在改变“哪一种能力会被算进成功”。

6. 六个配置的结果应该怎样读

6.1 通过很多测试,仍然可能交不出完整任务

下表整理自论文表 2。时间与 API 费用是作者当次实验的每任务均值,不是今天的价格查询或长期采购建议。

被测配置任务解决率测试通过率分钟/任务估算美元/任务
GPT-6 Sol38.9%78.8%43.95.37
GPT-5.6 Sol30.6%78.6%73.917.98
GLM 5.325.0%76.7%136.913.89
HY4 preview36.1%83.3%118.12.09
DeepSeek V4 Pro30.6%74.3%94.11.89
Kimi K330.6%75.8%136.413.48

所有配置都通过了大部分测试,但没有一个解决超过四成任务。原因并不矛盾:很多基础用例和未受影响的路径可以通过,少数关键行为仍然错。HY4 的测试通过率最高,GPT-6 的完整任务数却多一个。对平均通过用例数的优化,与对完整交付的优化,不是同一件事。

这些也不是只改变模型权重、其他条件完全相同的比较。两个 GPT 配置使用 Codex,其余四个使用 OpenCode;推理强度设为 xhigh 或可比级别,每个任务只运行一次。工具接口、上下文处理、错误恢复和服务端速度都会进入结果。论文还提示,GPT-5.6 的测量窗口可能遇到服务模型退化。因此,能直接比较的是完整配置在这次协议下的表现,不能把全部差异归结为基础模型自身。

附录 C 的 token 表也需要小心。作者将非缓存输入、缓存读取、输出和 reasoning 分开,大数字主要来自缓存读取,不能理解成每次任务都新生成几千万回答 token。不同服务对缓存和非缓存计价不同,仅用 token 总量无法推出费用排序。表中还注明 parent-session 口径,不宜自动扩写成整场评测所有资源的总账。

6.2 推理、训练和 RL 的难点分布不同

图 5:根据论文表 3 重绘各方向的整数成功数与百分比。推理一列每个配置都是 1/10;这并不说明六个模型解决的是同一个任务。

六个配置在推理方向都只解决 1/10;训练方向从 5/19 到 10/19;RL 方向从 2/7 到 4/7。GPT-6 在训练方向领先,HY4 与 Kimi 在 RL 方向并列。对主要维护推理引擎的团队来说,总榜第一并不直接意味着它在相关任务上最可靠。

总分其实是按任务数量加权的方向分数:

R=1936Rtrain+736RRL+1036Rinfer.(9)R=\frac{19}{36}R_{\mathrm{train}} +\frac{7}{36}R_{\mathrm{RL}} +\frac{10}{36}R_{\mathrm{infer}}. \tag{9}

推导很直接:先将每个方向的成功率乘以该方向任务数,得到成功数,再除以总任务数 36。权重变了,即使任何一个补丁都没变,最终排序也可能变化。部署决策需要看相关方向、重复运行的不确定性,以及不同模型是否总在同一批任务上失败。

附录表 4 还能解释“新探针到底主要补了哪里”。GPT-6 在 verl 的原测试下是 7/7,加入探针后只剩 3/7;在 vLLM 下则前后都是 1/10。后一种零差距不证明原有推理测试已经完备,因为许多补丁可能早就在导入、接口或运行阶段失败,留给新探针进一步淘汰的成功样本很少。

6.3 原始题目消融的范围比摘要听起来窄

真正做提示词消融的是 GPT-6 Sol 和 DeepSeek V4 Pro,任务范围是 19 个 Megatron-LM PR。使用原始 PR 描述时,两者在原测试下都只解决 5.3%,加入探针后都为零;使用合成题目后,增强裁判下分别达到 52.6% 和 42.1%。所以不能把摘要里较宽泛的句子理解成六个模型、三个仓库都做了同样的对照。

这个结果有力说明:题目欠规格,会让评测测到猜接口能力,而不是预期的工程能力。不过,它不能将全部提升都归因于“把名字补齐”。因为新模板还强调运行、收集、多卡和完成条件。若要进一步拆解因果,需要比较原描述、只补接口、只补行为、只补工作流程、全部合并这几种条件。论文没有报告这组细分实验,这里只是提出更有辨识力的后续设计。

7. 共享环境节省的是准备开销

每次运行独占一个含 8 张 H800 或 H20 的节点,agent 的时间上限为 2.5 小时,不含环境准备。评分时把候选补丁应用到另一个干净的改动前环境,并用改动后的测试目录替换测试,避免 agent 靠修改评分测试获得成功。参考补丁校准与候选评分使用相同 GPU 类型和任务环境。

传统做法通常是每个任务构建一个 Docker 镜像。Docker 按构建步骤的前缀复用缓存,一旦较早的依赖发生变化,后面的步骤就可能重新执行。InfraDev 把复用粒度改到依赖和数据本身:轻量基础镜像保留 CUDA、Python 等公共部分;任务依赖由 uv 安装在共享卷上的虚拟环境;锁定依赖哈希相同的任务直接共享环境;新环境通过硬链接复用包;权重和数据集也使用共享缓存。

可以用一个理想化的存储模型解释其收益。设 BB 为公共基础部分,DiD_i 为任务依赖,AiA_i 为任务数据和权重,则忽略文件系统元数据、也暂不计 Docker 原有层共享时:

Mseparate≈B+∑i∣Di∣+∑i∣Ai∣,Mshared≈B+∣⋃iDi∣+∣⋃iAi∣.(10)M_{\mathrm{separate}}\approx B+\sum_i|D_i|+\sum_i|A_i|, \qquad M_{\mathrm{shared}}\approx B+\left|\bigcup_iD_i\right| +\left|\bigcup_iA_i\right|. \tag{10}

从求和改成并集,重叠越多越省。如果每个任务都需要完全不同的包和数据,并集大小接近总和,收益就小。这是解释性预算模型,不是说作者的 Docker 基线完全不共享任何字节。特别大的共用权重文件,可以带来显著存储收益,却未必同比缩短编译或 agent 思考时间。

图 6:第 4.3 节的实测存储数据。对应环境构建时间分别下降 14% 和 13%,不能把存储柱形直接解读成 agent 加速比。

Megatron-LM 从 80.7 GB 降到 34.8 GB,vLLM 从 206.0 GB 降到 98.8 GB,按原数计算约节省 56.9% 和 52.0%。构建时间的下降则是 14% 和 13%。如果整个流程中准备环境占比为 ff,准备时间降低比例为 bb,理想总加速为:

Stotal=1(1−f)+f(1−b)=11−fb.(11)S_{\mathrm{total}} =\frac{1}{(1-f)+f(1-b)} =\frac{1}{1-fb}. \tag{11}

第一步保留不受影响的 1−f1-f,第二步把准备部分缩短到 f(1−b)f(1-b),最后取倒数。仅作算例,若 f=0.2f=0.2、b=0.14b=0.14,总加速约 1.029 倍,而不是 1.57 倍。论文没有测量这个特定端到端例子;它只是说明存储收益、构建收益和任务执行收益应当分账。

按最大预算算,单个模型的 36 个任务在 8 卡节点各用满 2.5 小时,就对应 36×8×2.5=72036\times8\times2.5=720 GPU 小时,还没算评分。实际任务会提前结束,所以这是协议推导出的 agent 运行预算上界,不是论文实测总耗卡时。共享依赖有用,但没有消除多卡评测的主要成本。

共享也带来隔离要求:缓存内容最好对被测任务保持不可变,工作目录应分开,不能让任务之间通过可变缓存泄露答案或污染测量。论文解释了复用设计,存储结果本身却不能证明所有隔离性质都成立。把工程收益限定在实际测到的范围,反而能更准确地评价它的价值。

8. 失败分析:先接得上系统,再谈算得快

8.1 这里的分母不是全部 216 份提交

失败分析使用的是除 GPT-6 Sol 之外五个模型的 36×5=18036\times5=180 份提交,共分析 1,754 个失败用例。失败用例的定义是参考补丁通过、候选补丁不通过。作者结合断言、题目和提交代码标注,再按任务与错误特征分组。1,754 是用例数,不是独立 agent 尝试数,也不能拿它与 216 份提交直接混算。

图 7:按附录表 7 的整数重绘错误类型。一次提交可同时出现多类错误,因此柱形相加不是一个互斥分布。

附录表 7 给出:85 份提交有结构错误,51 份有行为错误,24 份有数值错误。结构细分包括 48 份执行/API 错误、22 份形状/布局/dtype 错误、35 份状态/生命周期错误。由于存在重叠,48+22+3548+22+35 大于 85,并不矛盾;行为错误中资源类 17、条件类 35,相加为 52,而并集为 51,也是同样道理。

正文图把三大类比例标成约 48%、14%、29%;但用附录明确计数除以 180,分别约为 47.2%、13.3%、28.3%,不能完全用普通四舍五入解释。本笔记据此采用可核对的整数重绘,并把图中百分比分母留作报告歧义。它不改变“结构错误很常见”这个定性结论,也没有必要为了让表面数字一致而擅自改原始计数。

8.2 状态问题往往躲过单次调用

35 份含状态错误的提交里,有 15 份只被新增探针发现。一个缓存可以初始化正确,却在重复使用、失效和重建时出错;一个计数器可以第一次正确,下一步被意外重置;张量形状可以始终正确,内存所有权却不对。只用全新对象执行一次,根本看不到这些路径。

CUDA graph 是很直观的例子。捕获记录的是 GPU 工作,重放不会重新执行当初发起工作时的整段 Python 控制流。如果 agent 把需要每次变化的判断或计数放在 Python 层,eager 下可能正常,图重放时却冻结了。论文报告四个 CUDA-graph 任务上的提交有 60% 出现条件特定错误,其他任务为 15%。这说明模式敏感测试很有价值,但不是严格控制其他因素后的单独因果估计。

8.3 数值不对,先别全部归咎于精度

24 份数值错误提交都包含算法错误,没有被标为纯精度错误的提交。附录 D 对“纯精度”的要求很严格:同一补丁必须先通过精确逻辑检查。若数值差异只在某个特定模式出现,则又会归到条件特定行为,而不进入数值类。

因此,零个 precision-only 不能推出“基础设施工程没有精度难题”,只能说明在这套任务、提交与分类规则下,观察到的数值失败主要体现为算法问题。论文举例,一份实现的 indexer loss 是 19.95,而应有结果是零。面对这种量级,先检查公式、归一化和约定,比先把问题解释成浮点噪声更合理。

8.4 自测很多,不等于测了需求最关键的部分

103 条可追踪运行中,94 条会自己写测试;这 94 条里的 5,532 个断言,56.3% 检查功能,27.9% 检查结构,12.0% 检查数值,2.0% 检查错误路径,只有 1.8% 检查资源。在 11 条最终没通过资源要求的轨迹里,仅有一条写过任何资源断言。

这是对可追踪样本和断言层面的统计,不是所有真实开发场景的随机抽样。它仍然传达一个清楚的问题:agent 倾向于验证代码能跑、有输出,却很少检查这次改动为何要存在——究竟有没有省显存、时间或通信。

图 8:左图按论文图 6 重绘自测断言构成;右图按图 7 和第 4.5 节重绘 skill 消融。提升是 19 个任务中多解决 2 个。

作者把这些发现写成 skill:检查调用方和持久状态;用朴素参考比较新计算;测量任务要求的资源,并测试 graph 模式。GPT-5.6 Sol 在 Megatron-LM 上从 8/19 提升到 10/19:

ΔR=10−819×100≈10.53 percentage points,10−88=25%.(12)\Delta R=\frac{10-8}{19}\times100 \approx10.53\text{ percentage points}, \qquad \frac{10-8}{8}=25\%. \tag{12}

所以绝对提升是约 10.5 个百分点,相对提升是 25%。这里改变的是运行指导,不是训练模型参数。这说明工作流和测试选择有改善空间,但只在一个模型、一个仓库、每任务一次运行上测量,还不足以证明广泛迁移。用于提炼 skill 的失败和用于评测 skill 的任务来自同一基准家族,独立任务集会提供更强证据。

9. 从一句需求到一个可测量的承诺

9.1 增量同步:正确权重不能证明通信正确

论文里的 verl 例子是:只变化 655 个条目,却可能仍发送全部 65,536 个条目。如果每个值占 bb 字节、稀疏索引占 ii 字节,忽略额外协议开销时,有:

Cdense=65,536b,Csparse=655(b+i),CdenseCsparse=65,536b655(b+i).(13)C_{\mathrm{dense}}=65{,}536b, \qquad C_{\mathrm{sparse}}=655(b+i), \qquad \frac{C_{\mathrm{dense}}}{C_{\mathrm{sparse}}} =\frac{65{,}536b}{655(b+i)}. \tag{13}

推导分三步:密集发送每个条目的值;稀疏发送只传变化条目,但每条通常还要带索引;两者相除得到理想载荷比。按条目数算,比例约 100.05;按字节算则可能明显较小。仅作说明,若值为两字节、索引为四字节,载荷比约为 33.35。这里的字节宽度是笔记选取的算例,不是该 PR 的实测配置。

再考虑消息头、打包、collective 组织和固定启动成本,传输时间也不一定按字节比例下降。所以“发送条目更少”“总字节更少”“端到端更快”是连续但不同的命题。探针应当测量需求真正承诺的那个量,而不是挑一个最容易变化的数字替代它。

最终权重一致无法区分全量与增量同步;但反过来,通信量小也不能证明实现正确,因为什么都不发同样很省。有效裁判要把通信观察与结果数值结合,并用连续多次更新检查持久状态。对一个优化任务,功能和资源两类证据必须同时存在。

9.2 激活卸载:发生了拷贝,不代表降低了峰值

激活卸载常以减少 GPU 峰值显存为目标。看到一次向主机拷贝,并不足以证明这个目标。一个解释性预算是:

Mpeak=max⁡t(Mweights+Moptimizer+Mlive activations(t)+Mbuffers(t)).(14)M_{\mathrm{peak}}= \max_t\bigl(M_{\mathrm{weights}}+M_{\mathrm{optimizer}} +M_{\mathrm{live\ activations}}(t)+M_{\mathrm{buffers}}(t)\bigr). \tag{14}

公式先把同一时刻仍然存活的部分相加,再在时间上取最大值。若卸载发生在原峰值之后,峰值未必下降;若引入额外暂存缓冲区,名义节省可能被抵消;若旧引用未释放,实际分配也可能不变。探针的测量窗口要与生命周期的改变对齐,而不是只统计是否调用过拷贝接口。

合理做法是用小规模数值测试检查内容,再用等价工作负载下的显存观察检查资源承诺。硬件预热、分配器缓存、同步位置和张量尺寸都会影响测量,因此不能随意把一个绝对阈值搬到所有设备上。应说明为什么采用某个相对或绝对门槛,以及噪声如何处理。InfraDev 展示了这种需求的必要性,没有给出适用于所有资源探针的万能阈值。

这里也能看到“测试越严越好”的局限。一个精度上合法、资源改善也成立的替代实现,可能使用不同缓冲区或时序。如果探针绑定了参考实现的内部操作顺序,而不是外部承诺,就会误拒有效解。严格程度必须服从规格,而不是反过来塑造规格。

9.3 状态探针应该覆盖一条序列

对于缓存或计数器,一个有解释力的概念序列是:初始化、执行、再次执行、重置、再次执行。重复调用能发现错误复用;重置测试失效逻辑;最后一步检查对象是否仍然可用。如果支持 CUDA graph,还应在符合捕获条件的输入序列上检查重放语义。

但比较方式仍需依据约定。若图模式要求固定张量地址,测试每次重新分配输入可能本身就违反契约;若优化允许一定数值误差,逐位相等可能过强。一个正确探针既要能找错,也要尊重方法的有效输入域。它的价值不在断言数量,而在每一次失败能否指向明确的需求违背。

因此,我理解这篇论文时,更看重“把一个承诺转换成可观察差异”这个过程。先问哪些错误方案仍会通过现有检查,再选择能区分它们的观测;如果观测成本太高,再设计小而有代表性的例子。这比先写一堆容易通过的测试、最后统计覆盖率,更接近基础设施开发的核心困难。

10. 局限:这套证据还不能覆盖什么

首先是任务选择与样本量。36 个任务来自三个仓库的大型改动,每个配置在每个任务上只跑一次,缺少运行间方差。整体多解一个任务就是约 2.78 个百分点;RL 方向多解一个就是约 14.29 个百分点。看起来很大的百分比变化,可能只对应一个样例。

其次是裁判仍然有限。附录 A 明确说,对抗补丁究竟破坏了哪个承诺,是由生成它的 agent 记录的,并没有通过执行额外验证这个语义声明。若探针因为另一个无关崩溃而拒绝补丁,正负对照也可能看起来通过,却没有真正测到目标行为。验收程序提高了区分能力,不代表裁判的解释完全独立。

第三是出题阶段看过答案。参考补丁帮助补全接口,也可能留下算法暗示。checker 会尝试排除泄露,但不能据此证明所有提示都已消除。另一方面,过度隐藏公式、常量或容差,也可能删掉合法需求所必需的信息。泄露与欠规格是两端的风险,不能以为压低一端就自动解决另一端。

第四是硬件成本。共享依赖和权重缓存降低了准备开销,多卡执行仍然昂贵。作者把模拟多 rank 和自动筛选 PR 列为未来方向。模拟有助于扩大可及性,却也可能改变任务:真实 collective、显存生命周期、graph 捕获和资源争用,正是需要测量的困难。在模拟替代硬件之前,仍需证明它对相关失败具有足够区分能力。

第五是比较条件的稳定性。费用受价格、缓存策略和服务速度影响;时间受 harness 行为影响;skill 增益也只在特定配置和方向上验证。论文表格适合解释当次实验,不能被当成长期模型排序,也不能被解读成已经解决自主基础设施研发。

最后,部分报告细节仍不充分:逐任务探针覆盖、生成失败次数、评分用例身份、排除的系统故障分布、以及 skill 带来的修复和回归分别有多少,都影响读者对分数的信任。这些缺口不否定方法动机,却限制了我们可以从总分推出的结论范围。

11. 独立批判性分析:怎样继续检验这个裁判

11.1 最强证据来自对同一补丁换裁判

我认为 InfraDev 最有价值的设计,是承认一个基准由题目和裁判共同组成。题目没写的接口,被测试强行要求,失败就不是纯粹能力不足;题目承诺的资源收益,没有测试检查,成功也不是完整交付。联合生成流程正面处理了这两个不对称。

同一批补丁从 102 个成功变成 69 个成功,是比“新榜单很难、分数很低”更有辨识力的证据。补丁不变,裁判改变,就能直接看到测量效果。这不要求新裁判完美,只要求新增探针对实际需求有合理解释,并能展示旧测试漏掉的行为差异。

但我会把“评分变得可靠”收窄为“评分对特定失败模式更有区分能力”。可靠性还包含重复测量稳定、oracle 正确、需求覆盖充分,以及对不同正确算法公平。接受一组对照只是其中一部分。区分这两个措辞,有助于保留贡献,也保留继续改进的空间。

11.2 与参考实现一致,不应变成唯一合法答案

一个任务应当接受与 golden patch 不同但满足要求的算法。参考实现可以提供例子和接口,却不应该把其内部设计偶然性全部转成义务。每个探针都需要回答:它拒绝补丁,是因为需求被违反,还是因为补丁没有采用作者当初的实现路线?

如果条件允许,未来可以加入多个设计不同的正确实现作为正对照。只有参考实现能通过,未必说明参考实现唯一正确,也可能说明探针过度绑定。负对照则尽量一次只违反一个承诺,让拒绝原因能被定位。独立专家审阅“需求到观测”的映射,也能补充自动生成与自动检查可能共享的偏差。

我还希望看到一张逐任务证据表:每个承诺对应什么观测量、oracle 来自哪里、支持哪些模式、依赖什么硬件条件、已知盲区是什么。这是对论文报告和评测产物的建议,不要求读者逐项检查作者仓库。它能让使用者从规格和结果理解证据边界,而不是只能相信一个汇总成功率。

11.3 小样本应报告不确定性和成对变化

仅作量级说明,若把 nn 个独立试验的成功率估计为 p^\widehat p,二项模型下标准误近似为:

SE(p^)≈p^(1−p^)n.(15)\mathrm{SE}(\widehat p)\approx \sqrt{\frac{\widehat p(1-\widehat p)}{n}}. \tag{15}

对 14/3614/36,代入后约为 0.081,也就是 8.1 个百分点。真实基准是人工挑选、任务异质的集合,不能把这个近似直接当成面向所有工程工作的置信区间。它的用途更朴素:提醒我们,领先一个任务、约 2.8 个百分点,不足以支持“普遍能力明确更强”的结论。

skill 实验尤其适合成对分析,因为前后是同一批任务。净增两个成功,可能是修复两个、没有回归;也可能修复了更多,同时弄坏了原来能解的任务。8/19 到 10/19 只给出净值,没有给出转移矩阵。公布每个任务前后的成败、加上重复运行,会帮助区分稳定改善与成功样本的重新排列。

此外,若 skill 是从当前任务的失败中提炼,再在相近任务上测试,它确实说明这些经验能被利用,却还没回答跨仓库、跨时间和跨模型是否有效。更强的设计可以先冻结 skill,再在未来 PR 或未参与分析的仓库上评估。这样才能把有用的任务经验与真正可迁移的开发原则分开。

11.4 agent 应当学会选择有辨识力的实验

一个 agent 收到很大任务,却没有便宜的方法观察关键行为时,可能把精力放在导入检查和容易写的单测上。InfraDev 已提供真实硬件,减少了“没条件测”的理由,agent 仍然很少检查资源。这提示能力瓶颈不仅是生成代码,还包括知道该测什么、如何用有限预算判断当前方案错在哪里。

合理的改进不一定是每次修改都运行最昂贵的全套性能评测。更有效的策略可能是分层推进:先做结构门槛,再做小型数值参考,然后最小多 rank 例子、状态转移序列,最后测量需求所要求的资源。每一步都应该能排除一类仍然可能存在的错误,而不是单纯累积“已跑过的命令”。

这条路线与论文的 skill 一致,但最优测试预算如何分配仍是开放问题。某个失败很可能由接口错误造成时,昂贵的吞吐测量没有诊断价值;接口与数学都稳定以后,继续堆同类单测又可能浪费时间。未来的 agent 需要根据当前不确定性主动选择观测,这比被动执行固定清单更值得研究。

从这个角度看,我最感兴趣的后续方向是“会质疑自己测试的 agent”:它在内部枚举哪些错误解仍能通过当前自测,再挑一个新测试把它们区分开。这是 InfraDev 在基准构造端所做工作的开发端对应物。它是由论文启发的研究假设,而不是本文已经验证的能力。

12. 结论

InfraDev 说明,在大型 AI 基础设施改动上,原有测试通过可能显著高估任务完成。隐藏探针和明确任务契约共同生成,使评测更能区分数值、状态、执行模式和资源承诺。真实多卡环境也让它更接近框架开发,而不是只检查一个函数能否运行。

可以稳妥带走的实证结论有三个:102 个原测试成功里,有 33 个被增强裁判推翻;最好配置解决 36 个精筛任务中的 14 个;基于失败分析的 skill,让一个模型在 19 个训练任务里多解决两个。更普遍的方法论是:成功的补丁,应当与它承诺改变的行为之间存在可观察、可解释的联系。增加测试、扩写题目和提高分数,都要围绕这条联系才有意义。

参考资料与阅读范围

  • Deng、Ruan、Huang、Lau、Sheng、Mai:InfraDev: Can Coding Agents Develop AI Infrastructure, and How Can We Tell?,v1,2026-10-27。完整 PDF,20 页。本文精读范围包括正文及附录 A–D。
  • 图 1–3 按论文流程、任务表和验收规则重新绘制;图 4–8 来自报告的计数和测量,图注给出位置。没有任何图宣称是新的模型实验。
  • 公式 5–6 整理论文评分规则,公式 8 重算接受差异,其余公式为理解原理而作的形式化、推导或说明性例子。涉及假设的算例与未来实验建议均已标明。