CUDA Agent: Large-Scale Agentic RL for High-Performance CUDA Kernel Generation
Paper: arXiv:2602.24286 Code: BytedTsinghua-SIA/CUDA-Agent Code reference:
main@473025c8(2026-03-02)
1. Motivation (研究动机)
CUDA kernel 优化是深度学习系统的底层瓶颈:同一个 PyTorch operator 或 operator sequence,能否被融合、是否避免中间 tensor 落到 global memory、线程块/共享内存/向量化访问如何安排,都会直接决定训练与推理吞吐。传统上这类优化依赖 CUDA 专家、profiling 工具和反复调参;而通用 LLM 虽然在普通软件工程任务上很强,但在 KernelBench 这类高性能 CUDA 生成任务上仍经常只能写出“能跑但不快”的 kernel,甚至无法稳定超过 torch.compile。
Figure 0 解读:这张图给出论文的核心动机证据:通用模型在 Pass Rate 上可以接近可用,但 Faster Rate vs. torch.compile 明显不足;CUDA Agent 的目标不是只提高 correctness,而是把“生成可编译 kernel”推进到“稳定生成比 compiler baseline 更快的 kernel”。
现有方向主要有两类不足。第一类是 test-time search / refinement,例如多 agent 调试、evolutionary editing、retrieval-augmented search,它们依赖基础模型已有 CUDA 能力,主要在推理时搜索更好的 patch;如果模型本身不懂 memory coalescing、shared-memory tiling、kernel fusion,搜索空间会被强烈限制。第二类是固定执行反馈循环上的微调,它能让模型适应“写代码—运行—修复”的交互格式,但未必真正提升模型的内在 CUDA 优化策略,尤其对长上下文、多轮工具调用、稀有 CUDA token 的 RL 稳定性没有系统处理。
本文要解决的具体问题是:如何把 CUDA kernel generation 变成一个可大规模训练的 agentic RL 问题,使模型在一个受控的 CUDA 开发环境里反复编译、验证、profiling,并从可靠 reward 中学习到可迁移的 CUDA 优化能力。这个问题值得研究,因为一旦模型能稳定超过 torch.compile,LLM-based system agent 就可以从“辅助写代码”进一步进入底层系统优化:自动融合 operator、自动写 custom extension、在复杂模型子图上发现 compiler 规则覆盖不到的硬件特定实现。
2. Idea (核心思想)
核心 insight 是:CUDA 优化不是单轮 code generation,而是一个带验证器、profiling、错误反馈和性能目标的工程闭环;因此模型需要在“真实 CUDA 开发环境”中通过 agentic RL 学会迭代调试和性能优化,而不是只在静态答案上做 SFT。
CUDA Agent 的创新可以压缩为三点:先构造 6,000 个可执行、去污染、难度适中的 PyTorch reference operator 作为 RL 任务;再把 CUDA 开发规则、工具和 anti-hacking 约束封装成 skill-integrated agent loop;最后用 robust reward、RFT actor warm-up 和 value pretraining 解决长上下文 agentic PPO 的训练崩溃问题。与 STARK、CudaForge、EvoEngineer 这类 training-free 系统相比,CUDA Agent 的本质差异是把 execution feedback 从推理时启发式搜索信号变成训练时 reward 信号,直接改变模型参数和 CUDA prior。
一个直观理解是:普通模型像“临时查资料写 CUDA 的程序员”,遇到编译错误和 profiler 结果时只能在当前任务内修补;CUDA Agent 试图把大量这样的修补轨迹压缩进模型权重,使下一次遇到类似 operator fusion、memory layout 或 binding 问题时,它一开始就更像有经验的 CUDA 工程师。
更具体地说,本文把“agent 能使用工具”与“模型能从工具反馈中学习”区分开来:前者只是推理时能力,后者才是训练后的内在能力。CUDA Agent 的 novelty 在于把可执行任务、不可篡改评测、profiling latency 和多阶段 RL 串成一个闭环,使 reward 不是人工偏好或单元测试通过率,而是同时包含 correctness 与硬件速度目标的工程信号。
它与普通代码 RL 的差别还在于 reward 的粒度和任务结构:普通代码题往往只看测试是否通过,CUDA kernel 任务则必须同时通过数值正确性、编译、性能 profiling 和 baseline-relative speedup。本文把这些工程约束做成训练环境后,模型学习到的不只是某个 kernel 模板,而是“先定位瓶颈、再选择融合/tiling/vectorization/binding 策略、最后用 profiler 反馈迭代”的过程性策略。这个过程性策略正是 Code & SWE Agent 方向的关键:agent 的价值来自能在真实工具链里闭环优化,而不仅是一次性生成文本。 这也是本文区别于纯 benchmark leaderboard paper 的地方。
3. Method (方法)
3.1 Overall framework:数据、环境、RL 三段式闭环
CUDA Agent 的整体框架由三部分组成:数据合成管线提供可执行 PyTorch reference operators;agent loop 提供 CUDA 开发工作区、工具、verification/profiling 和 reward;稳定 RL 训练管线先 warm up,再用 PPO 做 long-context agentic RL。
Figure 1 解读:Figure 1 展示三阶段数据管线:从 torch / transformers 抓取 seed operators;用 LLM 把多个 torch operator 顺序组合成 fused task;再用执行过滤去掉不可运行、随机、退化输出、过易或过重的样本。这里的关键不是“合成更多题”,而是让训练任务逼迫 agent 学会跨 operator 的融合与内存布局决策。
Figure 2 解读:Figure 2 对应 skill-integrated agent loop:模型在 ReAct-style 循环中读写文件、运行 shell、编译 extension、查看错误和 profiler 结果。环境把 model.py 作为 PyTorch reference,把 model_new.py 与 kernels/ 作为 agent 的工作区,并通过 verification/profiling 脚本把 correctness 和 latency 转成可训练 reward。
Figure 3 解读:Figure 3 展示训练顺序:先做 single-turn RL warm-up,让模型具备基础 CUDA 生成能力;再收集 agent trajectories 并用 RFT 初始化 actor;同时用 trajectory state 和 outcome reward 预训练 critic;最后进入 agentic PPO。这个顺序针对的是 long-context tool-use RL 的分布错配问题,而不是普通 PPO 的超参数微调。
3.2 Scalable Training Data Synthesis Pipeline
每个训练样本是一个自包含 PyTorch operator task:一个 torch.nn.Module 子类、__init__、forward,以及 get_init_inputs() 和 get_inputs()。这种格式的优点是 execution-based RL 可以直接实例化模型、生成输入、跑 eager/compile/reference 对照,并给 agent 一个清晰的目标:在不改 reference 的前提下写出更快的 custom CUDA extension。
数据合成有三个阶段:
- Seed problem crawling:从
torch和transformers中挖掘高质量 reference operators。论文避免从零散个人 repo 抓代码,因为这些实现质量和维护状态不稳定,会污染 reward 与训练任务。 - Combinatorial construction:LLM 从
torchoperator classes 中采样最多 5 个,并顺序堆叠成一个 computational layer。组合后的任务不等价于逐个 kernel 优化后串联,因为融合会改变中间内存 materialization、register/shared-memory 约束、occupancy 和 downstream layout。 - Execution filtering:样本必须在 eager 与
torch.compile下都能执行;排除随机 operator;排除不同输入输出几乎不变的退化任务;eager runtime 限制在 1 ms 到 100 ms;再用 AST 相似度去掉与 KernelBench evaluation 过近的样本。
Figure 6 解读:Figure 6 展示两类训练 operator:transformers 模块代表高层语义 operator,组合 torch operator 代表可控的 operator fusion 任务。前者提供真实模型结构感,后者提供可扩展的复杂度梯度。
Figure 7 解读:Figure 7 是 decontamination 的证据:训练样本与 evaluation programs 的最大 AST similarity 分布被压在阈值以下,论文使用 0.9 作为移除阈值,避免模型靠记忆 KernelBench 测试样本获得高分。
最终数据集为 CUDA-Agent-Ops-6K,共 6,000 个训练样本。附录 Table 3 给出的组成是:torch operators ×1 为 3.40%,×2 为 83.77%,×3 为 7.62%,×4 为 2.80%,×5 为 1.23%,transformers operator 为 1.18%。这说明主体不是单 operator,而是二元组合任务;它们足够常见以稳定训练,又能覆盖 fusion 的主要收益来源。
3.3 Skill-Integrated Agent Loop 与 anti-hacking 环境
Agent loop 对齐 OpenHands 风格:提供 Bash、Read/Write、Edit/MultiEdit、Glob、Grep、NotebookEdit、BashOutput、KillBash 等工具,让策略在本地开发环境中执行“读代码—改代码—编译—验证—profiling—再改”的循环。CUDA-specific 部分以 SKILL.md 形式给出,要求 agent 先用 profiling 分析 native PyTorch baseline,再在 model_new.py 和 kernels/ 中实现 custom ops,最后通过 GPU sandbox 编译、验证并比较 torch.compile。
论文的 anti-hacking 设计很重要,因为 RL 如果直接奖励速度,很容易学会破坏评测脚本或绕过计算。CUDA Agent 做了五类约束:verification/profiling 脚本用权限保护;禁止在执行时 fallback 到 torch.nn.functional;每题用 5 个随机输入做 correctness check;profiling 有 device synchronization、warm-up 和重复测量平均;不给 agent web search 或外部检索工具。这样 reward 更接近“真实 kernel 更快”,而不是“评测被绕过”。
Released code 在 main@473025c8 中没有公开完整 RL trainer,但公开了 agent workdir 的核心环境。utils/verification.py 初始化 Model 与 ModelNew,复制 state_dict,把输入搬到 CUDA,并在 block_torch_functional() context 下运行 ModelNew,对 5 次随机输入做 torch.testing.assert_close(atol=1e-2, rtol=1e-2)。utils/profiling.py 分别 benchmark PyTorch baseline、torch.compile 和 CUDA extension,默认 warm-up 5 次、benchmark 10 次,用 CUDA profiler event 的 device_time 求平均。
import torch
import torch.nn.functional as F
from contextlib import contextmanager
@contextmanager
def block_torch_functional(excludes=None):
excludes = excludes or set()
originals = {}
for name in dir(F):
fn = getattr(F, name)
if callable(fn) and not name.startswith("_") and name not in excludes:
originals[name] = fn
setattr(F, name, lambda *a, __name=name, **kw: (_ for _ in ()).throw(
RuntimeError(f"torch.nn.functional.{__name} is not allowed")
))
try:
yield
finally:
for name, fn in originals.items():
setattr(F, name, fn)
def verify_cuda_extension(Model, ModelNew, get_init_inputs, get_inputs, checks=5):
torch_model = Model(*get_init_inputs()).eval().cuda()
cuda_model = ModelNew(*get_init_inputs()).eval().cuda()
cuda_model.load_state_dict(torch_model.state_dict())
with torch.no_grad():
for _ in range(checks):
inputs = [x.cuda() for x in get_inputs()]
expected = torch_model(*inputs)
with block_torch_functional():
actual = cuda_model(*[x.clone() for x in inputs])
torch.testing.assert_close(actual, expected, atol=1e-2, rtol=1e-2)
torch.cuda.synchronize()3.4 Robust Reward Scheduling
论文没有直接用 raw speedup ratio 作为 reward,因为不同 operator 的优化难度差异很大,raw ratio 会偏向容易题,也容易被 outlier latency 放大。CUDA Agent 使用离散 milestone reward:先要求 correctness,再看是否显著快于 eager 和 compile。
其中 是生成 kernel 的运行时间, 与 分别是 PyTorch eager 与 torch.compile runtime, 表示相对 baseline 至少快 5%。注意论文正文把解释文字中的 baseline 写成 与 ,而公式里是 ;这里按上下文统一理解为 PyTorch eager baseline。
import torch
def benchmark_model(model, inputs, warmup_iters=5, run_iters=10):
with torch.no_grad():
for _ in range(warmup_iters):
_ = model(*inputs)
with torch.profiler.profile(
activities=[torch.profiler.ProfilerActivity.CUDA],
record_shapes=False,
with_stack=False,
) as prof:
torch.cuda.synchronize()
for _ in range(run_iters):
_ = model(*inputs)
torch.cuda.synchronize()
return sum(e.device_time for e in prof.events() if e.device_type.name == "CUDA") / run_iters
def cuda_agent_reward(correct, t_agent, t_eager, t_compile):
if not correct:
return -1
faster_eager = (t_eager - t_agent) / t_eager > 0.05
faster_compile = (t_compile - t_agent) / t_compile > 0.05
if faster_eager and faster_compile:
return 3
if faster_eager:
return 2
return 13.5 Stable Agentic RL:为什么需要 RFT 与 Value Pretraining
论文报告初始 RL trial 只能稳定训练 17 steps 就崩溃。根因被归结为 domain distribution mismatch:CUDA code token 在通用预训练数据中占比低于 0.01%,长达 150 turns 的 tool-call / code trajectory 会产生大量低概率 token;如果 rollout/inference 与 training engine 的数值精度不同,例如 FP16/BF16,接近概率下限的 token 会让 importance ratio 波动甚至爆炸。
因此训练管线先做 single-turn PPO warm-up,再在 agent loop 中采样 trajectories,用 RFT 过滤并初始化 actor。过滤标准有两条:outcome filtering 只保留 的轨迹;pattern filtering 删除冗余多轮循环、违反 tool-call schema 的幻觉等无效行为。RFT 目标是标准行为克隆: Critic 也不能冷启动。论文用采样 trajectory 的 state sequence 与 outcome reward 做 Value Pretraining。令 ,最终 token 得到 outcome reward ,前面 token reward 为 0;用 GAE 计算 target: 实验中 ,。随后用 PPO clipped objective 优化 actor: 其中 ,,并且只在 agent 生成 token 上计算 loss,mask 掉环境反馈 token。
import torch
import torch.nn.functional as F
def rft_actor_update(policy, trajectories):
kept = []
for traj in trajectories:
if traj.reward > 0 and not traj.has_redundant_loop and traj.tool_schema_valid:
kept.append(traj)
loss = 0.0
for traj in kept:
logp = policy.log_prob(actions=traj.agent_tokens, states=traj.states)
loss = loss - logp.sum()
return loss / max(len(kept), 1)
def value_pretrain_loss(value_fn, states, final_reward, gamma=1.0, lam=0.95):
values = value_fn(states)
rewards = torch.zeros_like(values)
rewards[-1] = final_reward
next_values = torch.cat([values[1:], values.new_zeros(1)])
deltas = rewards + gamma * next_values - values
adv = torch.zeros_like(values)
running = 0.0
for t in reversed(range(len(states))):
running = deltas[t] + gamma * lam * running
adv[t] = running
target = values.detach() + adv
return 0.5 * F.mse_loss(values, target)
def ppo_clip_loss(policy, old_policy, states, actions, advantages, mask,
eps_lower=0.2, eps_higher=0.28):
ratio = torch.exp(policy.log_prob(actions, states) - old_policy.log_prob(actions, states))
unclipped = ratio * advantages
clipped = torch.clamp(ratio, 1 - eps_lower, 1 + eps_higher) * advantages
token_loss = -torch.minimum(unclipped, clipped)
return (token_loss * mask).sum() / mask.sum().clamp_min(1)Figure 4 解读:Figure 4a–4b 显示去掉 RFT 后 reward 快速 collapse,同时 actor entropy 上升。作者的解释是:没有 RFT 的行为先验,policy 在 tool-call / CUDA code 空间中变得发散,输出越来越不结构化,PPO 更新会强化错误分布。
Figure 5 解读:Figure 5a–5b 显示去掉 Value Pretraining 后 critic explained variance 长期接近 0,且 response length clipped ratio 更高。也就是说,critic 冷启动会给 actor 提供噪声 advantage,长 trajectory 训练更容易把更新推向不稳定区域。
3.6 Released code 与 paper-to-code mapping
论文公式与 released code 实现差异:公开 repo main@473025c8 没有包含完整 RL 训练 launcher、PPO trainer、RFT 数据过滤脚本或训练配置;公开内容是 CUDA-Agent-Ops-6K 说明、agent workdir、CUDA skill、verification/profiling/compile utilities 和一个 AXPBY custom kernel 示例。因此上面的 RL pseudocode 是按论文公式整理;环境 pseudocode 与 mapping 则来自 released repo。训练超参数也只能从论文 §4.1 读取,不能从公开 repo 的 launch config 复核。
Code reference:
main@473025c8(2026-03-02) — pseudocode and mapping based on this commit
| Paper Concept | Source File | Key Class/Function |
|---|---|---|
| Dataset / project release | README.md | CUDA-Agent-Ops-6K, agent workdir overview |
| CUDA coding skill constraints | agent_workdir/SKILL.md | forbidden torch fallback, allowed CUDA/cuBLAS/cuDNN workflow |
| Reference operator task format | agent_workdir/model.py | Model, get_inputs, get_init_inputs |
| Optimized model interface | agent_workdir/model_new.py | ModelNew.forward calling cuda_extension.axpby_forward |
| Binding infrastructure | agent_workdir/binding.cpp, binding_registry.h | PYBIND11_MODULE, REGISTER_BINDING |
| Example custom CUDA kernel | agent_workdir/kernels/axpby.cu, agent_workdir/kernels/axpby_binding.cpp | axpby_kernel, axpby_launcher, axpby_forward |
| Compilation | agent_workdir/utils/compile.py, compile.sh | source discovery, torch.utils.cpp_extension.load |
| Correctness verification | agent_workdir/utils/verification.py | block_torch_functional, check_equal, 5 checks |
| Performance profiling | agent_workdir/utils/profiling.py | benchmark_model, PyTorch vs torch.compile vs extension |
| RFT / PPO / value pretraining | not released in repo | paper §3.3 formulas; no public training config at this ref |
4. Experimental Setup (实验设置)
Training data and evaluation data. 训练数据是 CUDA-Agent-Ops-6K,包含 6,000 个合成 operator tasks;其构成见 §3.2。评估使用 KernelBench Level 1–3,总计 250 个 tasks,其中 Level 1 为 100 个 single operator tasks,Level 2 为 100 个 operator-sequence tasks,Level 3 为 50 个更复杂的 module-level tasks。训练数据还用 AST similarity 与 evaluation set 去污染,超过 0.9 的相似样本会被移除。
Baselines. 论文比较 Seed1.6 base model、GLM 4.6、Kimi K2、Gemini 3 Pro、Claude Opus 4.5,以及 PyTorch eager / torch.compile 作为 runtime baselines。所有模型在同一个 agent loop 下评估,以减少交互环境差异。
Metrics. Pass Rate 表示生成 kernel 能编译并通过 correctness check 的 task 比例;Faster Rate 分别统计正确 kernel 中快于 PyTorch eager 和 torch.compile 的 task 比例;Speed-up 是相对 eager / compile 的 geometric mean speed-up,只在正确解上计算。每个 task 取 agent trajectory 中相对 torch.compile speed-up 最大的解作为最终结果。
Training config. Base model 是 Seed1.6 MoE,23B active / 230B total parameters。RL global batch size 为 1024,online PPO mini-batch size 也为 1024;actor learning rate 为 ,critic learning rate 为 ;single-turn RL context window 为 32,768,agentic RL context window 为 131,072;training rollout 最多 150 agent turns,evaluation 放宽到 200 turns;训练 150 steps。Sandbox 是 CPU–GPU decoupled 架构:Docker terminal sandbox 处理编译等 CPU 任务,verification/profiling 分发到 128 NVIDIA H20 96GB GPUs(即 128 张 NVIDIA H20 96GB GPU) 的 sandbox pool,并做 process-level isolation / exclusive resource allocation。注意:这些训练配置来自论文 §4.1;released GitHub main@473025c8 未公开对应训练 launch script 或 experiment config。
5. Experimental Results (实验结果)
Main KernelBench results. Table 1 的 Overall 结果显示 CUDA Agent 达到 98.8% Pass Rate、98.4% Faster Rate vs. eager、96.8% Faster Rate vs. compile、2.60× geomean speed-up vs. eager、2.11× speed-up vs. compile。最强 proprietary baselines 仍有明显差距:Claude Opus 4.5 Overall 为 95.2% Pass Rate、66.4% Faster Rate vs. compile、1.46× speed-up vs. compile;Gemini 3 Pro 为 91.2%、69.6%、1.42×。
| Subset | Model | Pass Rate | Faster vs. Eager | Faster vs. Compile | Speed-up vs. Eager | Speed-up vs. Compile |
|---|---|---|---|---|---|---|
| Overall | CUDA Agent | 98.8% | 98.4% | 96.8% | 2.60× | 2.11× |
| Level 1 | CUDA Agent | 100.0% | 99.0% | 97.0% | 2.48× | 1.87× |
| Level 2 | CUDA Agent | 100.0% | 100.0% | 100.0% | 3.27× | 2.80× |
| Level 3 | CUDA Agent | 94.0% | 94.0% | 90.0% | 1.80× | 1.52× |
Level-wise 结果说明:Level 2 的 operator sequence 最受益于 learned fusion policy,CUDA Agent 相对 torch.compile 达到 100.0% Faster Rate 和 2.80× speed-up;Level 3 最难,但仍达到 90.0% Faster Rate vs. compile,约比 Claude Opus 4.5 / Gemini 3 Pro 的 50.0% / 52.0% 高约 38–40 个百分点。
Ablations. Table 2 证明每个核心模块都必要。去掉 agent loop 后 Overall Pass Rate 降到 77.1%,Faster Rate vs. compile 只有 14.1%,Speed-up vs. compile 只有 0.69×,说明单轮输出很容易退化成不快甚至更慢的 kernel。去掉 robust reward 时 Pass Rate 仍有 96.8%,但 Faster Rate vs. compile 降到 60.4%,说明 raw speed-up reward 没有正确对齐“稳定超过两个 baseline”的目标。去掉 RFT 时 Faster Rate vs. compile 为 49.8%、Speed-up vs. compile 为 1.05×;去掉 Value Pretraining 为 50.9% 与 1.00×,并且这些数值来自 collapse 前的最后 validation step。
| Variant | Pass Rate | Faster vs. Eager | Faster vs. Compile | Speed-up vs. Eager | Speed-up vs. Compile |
|---|---|---|---|---|---|
| w/o Agent Loop | 77.1% | 43.5% | 14.1% | 0.89× | 0.69× |
| w/o Robust Reward | 96.8% | 90.4% | 60.4% | 1.70× | 1.25× |
| w/o RFT | 95.6% | 82.0% | 49.8% | 1.56× | 1.05× |
| w/o Value Pretraining | 98.6% | 85.0% | 50.9% | 1.49× | 1.00× |
| CUDA Agent | 98.8% | 98.4% | 96.8% | 2.60× | 2.11× |
Limitations. 作者明确承认两点限制:第一,没有与 TVM 等更复杂 compiler framework 比较,因为这些系统的调参和部署成本很难嵌入数千 rollout 的大规模 RL loop;第二,训练依赖大规模隔离 GPU pool,工程和算力成本很高,限制了社区复现和扩展,后续需要更高效的训练策略。
Overall conclusion. CUDA Agent 的结果说明,LLM 生成 CUDA kernel 的瓶颈不只是“缺少更多 test-time search”,而是缺少可训练、可验证、可稳定优化的 CUDA agent 环境。数据合成解决任务规模,skill-integrated loop 解决真实反馈,robust reward/RFT/value pretraining 解决 RL 稳定性;三者合起来才把 correctness、performance 和 long-horizon tool-use 训练同时推上去。