CUDA Kernel Agent自动调优:闭环反馈与性能优化实践
1. 从手写Kernel到Agent自动调优这个方向为什么突然火了如果你在GPU高性能计算这个圈子里待过几年会发现一个很有意思的转折点。大概在2023年之前聊到CUDA Kernel优化大家默认的路径是人肉读PTX/SASS、翻Nsight Compute的指标、一行行调shared memory的bank conflict、反复试tile size。一个成熟的Kernel工程师调一个GEMM或者Attention Kernel花上几天甚至几周是家常便饭。但从2024年下半年开始越来越多的团队开始尝试让大模型Agent来接管这个流程——不是简单地生成一段CUDA代码而是让Agent具备写代码→编译→跑benchmark→读profiling→改代码的闭环能力。这就是CUDA Kernel Agent这个方向的核心。它要解决的不是能不能生成CUDA代码这种初级问题而是能不能让一个自动化系统在无人干预的情况下把一个Kernel的性能推到接近甚至超过资深工程师手调的水平。关键词里的CUDA Kernel、Agent、自动调优、LLM for HPC、性能可移植性基本勾勒出了这个领域的全貌。我关注这个方向大概有一年多从最早看到一些用GPT-4直接生成CUDA的尝试效果说实话很一般到后来出现专门做Kernel生成的微调模型再到最近一批把编译反馈、profiling数据、搜索策略整合进Agent loop的工作整个演进脉络其实非常清晰。这篇综述我打算按自己的理解把2026年这个时间点上CUDA Kernel Agent的研究格局梳理一遍——包括它到底分几个技术流派、每个流派的核心方法是什么、实测中哪些环节最容易翻车、以及如果你现在想入局应该从哪个切入点下手。需要先说明的是这个领域变化极快我写下的很多判断可能半年后就需要修正。但底层的技术逻辑——比如为什么编译反馈比单纯的代码生成更重要、为什么搜索空间的设计比模型本身更关键——这些是不太会变的。文章适合两类人看一类是做HPC/GPU优化的工程师想了解Agent能帮自己省多少事另一类是做AI for Code的研究者想找一个有明确评测标准的落地场景。两类人关注的点不一样我会尽量都照顾到。2. CUDA Kernel Agent的技术版图四条主流路线在展开细节之前先给一个全局的分类框架。我观察下来目前这个领域大致可以分成四条技术路线它们不是互斥的很多工作会交叉使用但每条路线的核心假设和瓶颈是不一样的。2.1 路线一纯生成式——LLM直接写Kernel这是最早也最直观的思路给模型一个Kernel的功能描述比如实现一个fp16的flash attention forward让它直接输出CUDA C代码。早期的工作基本都在这条线上代表思路包括用大量CUDA代码做继续预训练、用Kernel相关的指令数据做SFT、以及用单元测试做RLHF。这条路线最大的问题是正确率天花板低。CUDA Kernel不像普通的Python函数它对内存对齐、线程束分歧、同步语义极其敏感模型生成的代码经常看起来对、跑起来错。我实测过几个开源的CUDA生成模型在简单element-wise Kernel上能到70%以上的编译通过率但一旦涉及shared memory的复杂tiling通过率会掉到30%以下性能能超过PyTorch baseline的更是凤毛麟角。不过纯生成式路线并没有死。它的价值在于作为其他路线的初始化器——先让模型生成一个大致能跑的版本再交给后续的优化环节。现在很少有工作把它当作端到端方案了。2.2 路线二搜索增强——把Kernel优化变成参数搜索问题这条路线继承了传统auto-tuning比如TVM的Ansor、Halide的autoscheduler的思想但用LLM来指导搜索空间的设计和剪枝。核心逻辑是Kernel的性能主要由一组参数决定tile size、unroll factor、thread block维度、是否用vectorized load等与其让模型直接写代码不如让它输出这些参数然后由一个模板引擎生成实际代码。这条路线的好处是正确性有保障——因为代码是从经过验证的模板生成的不会出现语法或语义错误。瓶颈转移到了搜索效率上参数空间可能大到10^6量级暴力搜索不现实需要LLM根据历史profiling数据做智能剪枝。我比较看好这条路线在工程落地上的前景因为它可控、可解释、可复现。缺点是它只能优化模板能覆盖的Kernel结构遇到全新的算法模式就无能为力了。2.3 路线三闭环迭代——编译反馈驱动的Agent Loop这是目前最热、也是我认为最有前途的方向。核心思想是让Agent进入一个生成→编译→运行→profiling→修改的循环每一轮迭代都基于真实的编译错误和性能数据来修正。这个loop的关键组件包括一个能解析nvcc编译错误的模块把错误信息转成模型能理解的prompt、一个能跑benchmark并采集profiling数据的执行环境、以及一个能根据profiling结果定位瓶颈的诊断器。三者缺一不可。我见过的最有效的实现是把Nsight Compute的关键指标achieved occupancy、memory throughput、compute throughput、stall reasons结构化后喂给模型让模型针对性地改。比如如果stall reason显示是long scoreboard那大概率是global memory访问延迟没被隐藏模型就会去尝试增加并行度或者用prefetch。2.4 路线四多Agent协作——分工模拟人类优化团队最新的一批工作开始引入多Agent架构一个Agent负责生成初版一个负责review代码找bug一个负责分析性能瓶颈还有一个负责决定下一步优化方向。这种分工模拟了人类优化团队的工作方式。多Agent的好处是每个Agent的prompt可以更专注上下文不用塞太多东西。坏处是通信开销大、容易陷入互相甩锅的死循环比如review Agent一直说有问题生成Agent一直改不对。目前这类工作的实测效果方差很大调得好的能超过单Agent调不好的还不如单Agent。下面这张表是我对这四条路线的横向对比基于我读过的论文和复现过的几个开源实现路线核心方法正确率性能上限工程落地难度代表场景纯生成式LLM直接输出CUDA低中低简单element-wise Kernel搜索增强LLM指导参数搜索高中高中GEMM、Conv等模板化Kernel闭环迭代编译profiling反馈中高高高Attention、融合Kernel多Agent协作分工协作中高很高复杂多阶段Kernel需要强调的是这个表格里的性能上限是相对概念。闭环迭代之所以上限高是因为它能处理模板覆盖不到的结构创新但它的方差也大同样的Agent在不同Kernel上的表现可能差好几倍。3. 闭环Agent的核心机制拆解反馈信号到底怎么用既然闭环迭代是当前最主流的方向我单独拿一章来拆它的内部机制。很多人以为闭环Agent就是把编译错误丢回给模型让它改实际上远不止这么简单。一个设计良好的闭环系统需要处理好几类不同性质的反馈信号每类的处理方式都不一样。3.1 编译错误的分类处理语法错、语义错、资源错nvcc的报错信息其实可以分成三大类Agent对它们的处理策略应该完全不同。第一类是纯语法错误比如少了个分号、括号不匹配、类型不匹配。这类错误模型基本能自己修把原始报错贴回去就行。但要注意CUDA的模板报错信息极其冗长一个简单的类型错误可能产生几百行报错。我的经验是只截取报错的前20行和最后10行中间用省略号代替这样既保留了关键信息又不会把上下文撑爆。第二类是语义错误代码能编译但结果不对。这类错误最麻烦因为编译器不会告诉你哪里错了。处理方式是让Agent自己生成测试用例对比CPU参考实现和GPU输出的差异。我见过一个很巧妙的做法让Agent在Kernel里插入assert逐元素检查定位到第一个出错的index然后反推是哪一步计算逻辑有问题。第三类是资源错误比如register溢出、shared memory超限、occupancy过低。这类错误编译能过但性能极差或者直接launch失败。处理方式是解析ptxas的verbose输出-Xptxas -v拿到register和shared memory的使用量然后让Agent据此调整。提示ptxas的verbose输出是闭环Agent最重要的反馈源之一但很多实现忽略了它。我强烈建议在编译环节固定加上-Xptxas -v把register/spill信息结构化后喂给模型。3.2 Profiling数据的结构化别把原始指标直接丢给模型Nsight Compute能采集几百个指标但你不能把这几百个数字全塞给模型——一是上下文放不下二是模型会被噪声淹没。关键是把原始指标转化成瓶颈诊断结论。我的做法是定义一个简单的规则引擎把指标映射到几个高层结论上如果sm__throughput.avg.pct_of_peak_sustained_elapsed 80% 且dram__throughput 50%判定为compute bound如果dram__throughput 80%判定为memory bound如果smsp__warp_issue_stalled_long_scoreboard占比最高判定为global memory latency bound如果smsp__warp_issue_stalled_short_scoreboard占比最高判定为shared memory latency bound如果achieved occupancy 30% 且没有明显的memory瓶颈判定为occupancy limited然后把compute bound这样的结论加上几个关键数字比如实际occupancy、实际带宽利用率一起喂给模型。模型看到memory bound, DRAM throughput 85%, L2 hit rate 40%就知道该去优化memory access pattern了。这个规则引擎不需要很复杂我甚至见过用if-else硬编码的版本效果就很好。关键是要稳定、可解释而不是让模型自己去猜指标含义。3.3 迭代终止条件什么时候该停闭环Agent最容易失控的地方是迭代不收敛——模型改来改去性能在某个值附近震荡就是上不去。必须设计明确的终止条件。我一般用三个条件组合一是性能连续N轮N3没有提升就停二是总迭代次数超过上限比如15轮就停三是检测到循环修改——比如模型把A改成B下一轮又改回A——立即停。还有一个容易被忽略的点保留历史最优版本。Agent的迭代过程不是单调的经常出现改坏了又改回来的情况。所以系统必须记录每一轮的代码和性能最后返回历史最优的那个版本而不是最后一轮的版本。3.4 一个真实的迭代轨迹示例为了让大家有直观感受我描述一个我复现过的Attention Kernel优化轨迹具体数字做了模糊处理第1轮模型生成初版用了朴素的global memory访问性能是baseline的0.6倍第2轮profiling显示memory bound模型引入shared memory tiling性能到0.9倍第3轮编译报shared memory超限模型减小tile size性能到1.1倍第4轮profiling显示occupancy只有25%模型减少register使用性能到1.3倍第5轮模型尝试vectorized loadfloat4性能到1.5倍第6-8轮模型在unroll factor和tile size之间反复调整性能在1.5-1.6倍之间震荡第9轮触发终止条件返回第5轮之后的某个最优版本这个轨迹很典型前几轮提升快后面进入平台期。平台期的存在说明Agent的优化策略有上限要突破需要更激进的变换比如warp-level的primitive、异步拷贝等而这些往往是当前模型的盲区。4. 评测基准与真实性能别被论文里的数字骗了聊完机制必须聊聊评测。这个领域目前最大的问题之一就是评测标准不统一导致论文里的数字很难横向比较。我见过太多我们的方法比baseline快3倍的宣称仔细一看baseline选的是最朴素的实现而不是PyTorch或cuBLAS。4.1 现有基准的局限性目前常用的几个基准包括KernelBench、TritonBench的CUDA子集、以及一些从实际项目里抽出来的Kernel集合。它们各有问题KernelBench的题目偏简单大部分是element-wise或者reduction真正难的GEMM/Attention占比不高。TritonBench主要面向Triton而不是原生CUDA迁移过来有偏差。实际项目抽取的Kernel集合则往往不公开无法复现。更关键的是baseline的选择。一个公平的评测应该至少包含三个baselinePyTorch eager、torch.compile、以及手写的cuBLAS/cuDNN调用。很多论文只跟PyTorch eager比那当然容易快好几倍——因为PyTorch eager本身就没怎么优化。4.2 我建议的评测协议如果你要自己评测一个CUDA Kernel Agent我建议用这样的协议维度具体要求正确性与CPU参考实现对比相对误差 1e-3fp32/ 1e-2fp16性能baselinePyTorch eager torch.compile 手写最优实现三者取最快测量方式CUDA event计时warmup 25次测量100次取中位数硬件至少覆盖两代架构如Ampere和Hopper报告指标不仅要报speedup还要报绝对耗时和达到的TFLOPS特别强调跨架构这一点。很多Agent在A100上调出来的Kernel搬到H100上性能直接腰斩因为它过拟合了特定架构的cache大小和SM数量。真正鲁棒的Agent应该能在不同架构上都拿到不错的性能。4.3 论文数字的水分在哪里我总结了几种常见的数字注水手法读论文时要注意甄别第一种是只报最好的case。一个Agent在10个Kernel上有3个表现很好论文就只报这3个。要看它有没有报中位数和最差case。第二种是baseline没调优。前面说过了不赘述。第三种是忽略了编译时间。有些Agent为了找到一个好Kernel要跑几百次编译和benchmark耗时几小时。如果只报最终性能不报搜索成本那是不完整的。实际落地时搜索成本往往比性能更重要。第四种是测试集泄漏。如果Agent的训练数据里包含了测试Kernel的相似实现那性能好是理所当然的。要看论文有没有做严格的train/test split。注意读这个领域的论文时先翻到实验部分看baseline和测试集设置比看方法部分更重要。方法再漂亮评测不严谨也是白搭。5. 实操中绕不开的五个坑这一章是我自己踩过的坑也是我认为任何想入局这个方向的人都必须提前知道的。这些坑在论文里基本不会写但实际做的时候一个都躲不掉。5.1 坑一编译环境的不确定性CUDA编译对环境的敏感度超出想象。同一个Kernelnvcc版本差一个小版本生成的SASS可能完全不同性能差20%很正常。更麻烦的是很多Agent系统依赖特定的CUDA版本和GPU架构换个环境就跑不起来。我的建议是用容器固定整个工具链包括CUDA版本、nvcc、驱动、甚至GPU型号。所有benchmark都在同一个容器里跑保证可复现。如果要做跨架构评测就准备多个容器而不是在一个环境里换GPU。5.2 坑二benchmark的噪声GPU benchmark的噪声比CPU大得多。同一段代码连续跑耗时波动5%-10%是常事因为GPU有boost clock、有thermal throttling、有其他进程干扰。如果Agent基于单次测量做决策很容易被噪声带偏。解决办法是多次测量取中位数并且用CUDA event而不是CPU计时。另外测量前要充分warmup让GPU进入稳定状态。我一般warmup 25次测量100次。如果两次测量的中位数差异超过3%就重新测。5.3 坑三Agent的幻觉优化这是最隐蔽的坑。Agent有时候会声称自己做了某个优化比如我增加了shared memory的使用但实际生成的代码里根本没体现或者体现的方式是错的。更糟的是有时候代码确实变了性能也确实提升了但提升的原因和Agent声称的完全无关可能是碰巧改了某个无关紧要的地方。应对方式是不要相信Agent的自我描述只看代码diff和实测数据。每一轮迭代都要保存代码快照性能提升必须能对应到具体的代码变化上。如果对不上就要警惕。5.4 坑四搜索空间的维度灾难如果你走的是搜索增强路线很快会遇到搜索空间爆炸的问题。假设有8个参数每个参数5个取值那就是5^8≈39万种组合。每个组合编译benchmark要10秒全部跑完要45天。必须做分层搜索先粗粒度搜大参数tile size、block维度锁定大致范围后再细粒度搜小参数unroll factor、prefetch距离。另外要利用参数间的依赖关系剪枝——比如shared memory用量和tile size是强相关的不用独立搜索。5.5 坑五过拟合到特定Kernel形状Agent在训练时见过的Kernel形状上表现很好换个形状就崩。比如在batch32, seq_len512的Attention上调得很好换成batch1, seq_len4096就完全不行。这个坑的根源是Agent学到了针对特定形状的trick而不是通用的优化原则。缓解办法是在训练和评测时都覆盖多种形状并且显式地让Agent理解为什么这个优化在这个形状下有效而不是死记硬背。6. 如果你想入局从哪切入最划算最后聊聊落地。如果你现在想在这个方向做点东西不管是发论文还是做产品我建议根据自己的背景选切入点。6.1 有HPC背景的从闭环系统的工程实现切入如果你本来就懂CUDA优化最划算的是做闭环系统的工程实现。这个方向的门槛不在算法而在工程细节——怎么稳定地采集profiling、怎么结构化反馈、怎么管理迭代状态。这些恰恰是纯AI背景的人做不好的。具体可以从一个垂直场景做起比如只做Attention Kernel的自动优化把这一类Kernel做到极致。不要一上来就想着通用Kernel Agent那个太难而且评测都做不清楚。6.2 有AI背景的从反馈信号的理解切入如果你更懂模型建议从如何让模型更好地理解编译和profiling反馈切入。现在大部分工作是把反馈当纯文本处理但实际上编译错误和profiling数据都有很强的结构可以用更专门的方式编码。比如把profiling指标做成一个图结构让GNN来处理或者把编译错误解析成AST级别的diff。这个方向目前做的人还不多而且有明确的研究价值。6.3 资源有限的从复现和评测切入如果你既没有很强的HPC背景也没有很多算力那最务实的做法是做复现和评测。这个领域现在最缺的就是严谨的第三方评测。你可以选几个有代表性的开源Agent在统一的硬件和基准上跑一遍把真实数字公布出来。这种工作看起来不高大上但对社区的价值极大而且容易做出影响力。6.4 一个务实的起步路线不管选哪个方向我建议的起步路线是先搭一个最小的闭环能生成代码、能编译、能跑benchmark、能采集profiling先跑通一个最简单的Kernel比如vector add然后逐步增加Kernel复杂度reduction → GEMM → Attention每一步都记录Agent的迭代轨迹分析它在哪一步卡住针对卡住的环节做改进而不是一上来就换更大的模型这个路线看起来很笨但能帮你建立起对系统行为的直觉。我见过太多人一上来就堆模型规模结果连系统为什么不收敛都搞不清楚。我个人在这个方向摸索下来最大的体会是CUDA Kernel Agent的瓶颈从来不在模型能力而在反馈信号的质量和迭代策略的设计。一个用中等规模模型但反馈设计精良的系统往往能打败用大模型但反馈粗糙的系统。这个判断如果只让我说一句话那就是它了。后续这个方向肯定还会有很多新工作出来但反馈质量决定上限这个逻辑我预计在相当长时间内都不会变。