做GPU算子优化这行,真正让我觉得工作流被彻底重写的转折点,是2026年下半年开始,我们把LLM代理正式当成“一等优化手段”来用。以前提到优化kernel,大家脑子里是Nsight Compute、SASS汇编、occupancy分析这些传统套路,现在我的日常工作流里,最核心的步骤变成了:让LLM代理读一份完整的profile报告,自己定位瓶颈,生成候选kernel,然后跑验证闭环。这件事放在两年前我不敢想,放在半年前我觉得还不太成熟,但到了2026年下半年,它已经是我们在某个AI推理项目中实打实用起来的主力方案。这篇文章就围绕这个变化展开。我会把LLM代理为什么能在kernel优化里从“辅助工具”升级成“一等手段”讲清楚,然后拆解一套完整的优化流程,再给一个GQA算子优化的具体案例,最后聊聊正确性验证、工程化集成和踩过的坑。适合正在做GPU算子优化、AI编译优化、推理引擎开发,或者对LLM agent落地感兴趣的朋友。1. 变化从何而来:LLM代理凭什么成为“一等优化手段”1.1 什么叫做“一等优化手段”先解释一下我说的“一等优化手段”。它不是指你打开一个对话框,问一句“我这个kernel为什么慢”,然后让模型给一堆泛泛的建议。那只是辅助,连二等都算不上,顶多是个人工智障答疑。我理解的“一等优化手段”是:LLM代理被内嵌到优化闭环里,它有自己的输入管道,能读取性能分析器的原始输出、汇编代码、调度参数和源码;它有自己的工具调用能力,能编译、能跑测试、能收集反馈;它还能基于前一轮跑出来的结果自我迭代,直到性能或者正确性指标满足要求为止。换句话说,它从一个“问答机器人”变成了优化流水线里的一个“决策节点”。这个节点可以对优化动作负责,而且关键的是,它可以解释自己的决策依据。1.2 传统优化流程到底哪里卡脖子要理解这个变化,得先知道以前我们是怎么做kernel优化的。常规流程大概是:跑一个benchmark,拿到profile热点函数,然后用GPU性能分析工具去看这个kernel的occupancy、访存带宽、bank conflict、指令吞吐这些指标。很多时候一眼就能看出来是访存瓶颈还是计算瓶颈,但问题是,当你要深入优化的时候,你面对的是一个巨大的搜索空间。以一次典型优化为例:同样一个GEMM kernel,可能有十几种tiling策略、三五种子块尺寸、两种数据排布方式、若干共享内存padding方案。你怎么知道哪种组合最优?很多团队靠经验、靠文档、靠试错。传统auto-tuning也能做,但它是一个黑盒搜索,代价高、可解释性差,而且它不会告诉你“为什么这个方案好”。LLM代理的价值在于,它把“从profile数据里读取线索”“回忆历史优化案例”“生成候选代码”“判断瓶颈类型”这些能力整合到了一起。它改变了优化动作的产生方式:不再是一步步手查指标,而是基于完整上下文的一次性综合诊断。1.3 为什么是2026年下半年才爆发其实LLM代理能读代码、能生成代码这件事并不新鲜,但在2026年下半年,几个条件终于凑齐了。第一个是上下文窗口和处理能力。优化一个kernel往往需要同时看几千行源码、几百行SASS、一份几MB的profile JSON。过去这些数据根本塞不进上下文,现在可以了,而且在结构化摘要之后,重要信息不会丢。第二个是工具链的打通。GPU原厂分析器的输出格式越来越结构化,编译器的中间表示也开始面向工具开放,这让LLM代理都能直接解析原始数据,不再需要人手工转述。第三个是验证闭环的成熟。LLM代理生成代码之后,我们可以让它在沙箱里编译、跑数值校验、跑性能回归,然后把结果反馈给它进行下一轮迭代。没有这个闭环,代理的建议就永远是“建议”,而有了闭环,它就变成了一个真正能干活、能担责的优化执行者。我自己体会比较深的一点是:在这个时间点,劣化优化(也就是用LLM代理做“分析到改代码的最后一公里”)已经不是一个实验性玩法了,它在工程上稳定到可以进CI、支持回滚、做灰度验证。这就是我决定把它当作一等手段的根本原因。2. 全流程重构:LLM代理介入kernel优化的四个关键环节2.1 Profile数据预处理与瓶颈判定第一环,也是最基础的一环,是把原始的profile数据变成LLM代理能直接理解的结构化上下文。这个环节我以前做得非常痛苦。性能分析器导出的报告虽然很全,但信息密度极低,几千行指标只有几个是关键的。如果直接把原始报告全部塞给LLM代理,它很容易被噪音干扰,而且token消耗会很夸张。所以我们在前面加了一层预处理脚本,从分析器输出里抽取最核心的信号,包括:kernel执行时间占比warp占用率与理论占用率的比值全局内存/共享内存的访存指令占比主要stalall或wait原因计数指令issue rate说明计算单元还是没有喂饱这些信号组合成一个压缩后的“瓶颈快照”,和源码片段、编译选项一起交给LLM代理。代理拿到之后,会先输出一个瓶颈分类结论,比如“这是一个访存密集型瓶颈,主要卡在L2 miss和global load延迟上”或者“这是指令延迟型瓶颈,shared memory bank conflict导致stall”。这一步的输出质量直接决定后续优化方向对不对,所以我们用了不少心思在快照的生成规则上。实践中,我们还会让代理对“快照”给一个置信度。这个置信度不是它自己拍脑袋,而是通过一个历史案例库做相似度匹配得到的。如果当前这个kernel的特征和之前某个成功优化的案例高度相似,置信度就会高一些。有了这个机制,我们敢让代理直接给出优化动作,而不是只停留在分析层面。2.2 候选策略生成与kernel改写瓶颈判定完之后,重头戏就来了:让LLM代理基于诊断结果直接产生候选代码。这个环节和普通代码生成完全不是一回事。普通代码生成是“你给我一个描述,我写一个实现”,而kernel优化里的改写更像做一个高强度的代码迁移手术。它得读现有的SASS/PTX,判断哪些循环该展开,哪些内存访问可以合并,哪些延迟可以通过异步拷贝掩盖,然后把这些改动落到CUDA/Triton级别的源码上。举个例子,在某个reduce类kernel里,代理发现内核里有一段串行的原子操作,导致整个block的吞吐被拖死。它会建议把原子操作替换成先warp内reduce再原子写的方式,并且直接生成替换后的代码。这个建议放到以前,需要一个人熟读CUDA编程指南、理解硬件执行模型之后才能给出来,现在代理在几十秒内就能给出一版初稿。当然,初稿不一定能直接通过编译。我们在工作中经常遇到的情况是:代理改完的代码在语法上没问题,但在某个边界条件上处理错了,比如shared memory数组下标越界。这种情况我们不会直接弃用,而是会把编译错误信息喂回给代理,让它自己修复。多轮修复之后,代码质量基本能接近熟练工程师的水平。这个环节里,我们最看重的是“可解释的改动”。代理生成每一个改动时,都要附带一段理由说明,解释这个改动和瓶颈判定之间的因果关系。这段理由后面会成为优化记录的一部分,方便我们审计。2.3 编译选项与启动参数联合搜索kernel优化不只是改代码,很多时候启动配置比代码本身还重要。一个kernel最终的性能,同时取决于block大小、grid大小、shared memory动态分配量、编译选项里的优化级别、ptxas选项。传统的做法是写一个Python脚本,把这几个参数作为变量,跑一遍网格搜索或者贝叶斯搜索。这个方法的问题是会陷入局部最优,而且搜索次数上去了,成本很高。LLM代理在这个环节的作用,是把“内容特征”和“参数空间”连接起来。它会分析kernel访存模式和计算密度,给出一个更聪明的启动配置起点。举例来说,如果一个kernel的访存模式是连续广播式的,代理会优先考虑使用较小的block配合较大的grid;如果计算密度高,它可能倾向用更高的寄存器上限来压低spill。然后它不会只给一组参数,而是会生成一个参数矩阵,交给底层搜索器去做局部验证。这样搜索空间被大幅缩减,而且搜索方向有先验知识引导,收敛效率高很多。我在实际项目里测过,同样一个kernel、同样一个搜索预算,用LLM代理给出的起点比随机起点快3-5倍收敛。更重要的是,代理会在搜索过程中看中间结果,如果某组参数虽然慢但在profile里显示某个指标明显改善,它会把那组参数保留下来做进一步调查,而不是简单丢掉。2.4 验证与迭代闭环最后一个环节,也是让LLM代理真正“长跑”的关键:验证与迭代闭环。我们把代理生成的候选kernel放进一个统一的验证流水线里。这个流水线会做四件事:编译、数值校验、性能回归、细节指标收集。每一件事的结果都会被格式化成结构化的反馈,再送回给代理。代理看到反馈之后,会根据情况选择接受当前方案、继续微调某一处代码、或者完全推翻换一个思路。这套闭环机制让代理有了一种“干活”的感觉。它不是在一次性生成终极答案,而是在一个可控的循环里逐步逼近目标。我见过代理一轮优化不满意,第二轮加大了shared memory的复用粒度,第三轮发现导致bank conflict又做了一次padding,第四轮终于达到目标。整个过程大概两个多小时,换作人工操作,至少得一天。关于闭环,我特别想强调一个经验:反馈信息要分层。不要只把“性能提升了23%”这种笼统结果给代理,要把具体指标也放进去,比如“L2吞吐从XX提升到XX”“bank conflict计数从XX降到XX”“寄存器spill从XX降低到0”。代理只有看到这些细节,才能在下一次改写时做出有针对性的决策,而不是继续瞎试。3. 真实案例复盘:一个GQA kernel的完整优化过程3.1 案例背景与基线数据我拿一个实际做过的案例来复盘,这样看得更直观。项目背景是一个AI推理框架,里面某一段GQA(Grouped Query Attention)算子在特定序列长度和batch配置下,占据了端到端推理时间的19%左右。这个占比对注意力类算子来说偏高了,我们团队决定对它做一轮深度优化。先看基线profile数据。我们跑了一组测试,记录下来的关键指标如下表所示:指标项基线数值单次kernel平均耗时472usSMEff(流式多处理器实际利用率指标)31%全局load执行占比24.5%L2 hit rate62.1%SM busy wait占比18.7%寄存器spill量112 bytes/thread从这组数据里,基本能判断几个问题:首先,SM busy wait占比很高,说明warp在等数据,而不是在跑指令;其次,L2 hit rate不到65%,说明访存局部性很差;再加上全局load占比接近四分之一,这是一个典型的访存等待型瓶颈。如果是过去的流程,我会基于这些指标手工去翻源码找访存方式,然后试几种方案。这一次,我们把原始报告和源码直接交给了LLM代理。3.2 第一轮优化:从访存路径和指令排布动手代理拿到数据之后,第一轮给出来的诊断是:这个kernel的主要延迟来源是KV cache读取阶段。它发现当时的实现里,每个query会依次读取对应的多个KV头,这个读取过程没有做向量化,导致产生大量细粒度的非对齐load,L2请求次数被放大。代理给出的修改建议是:把KV读取的指针访问改成float4对齐路径,同时把读取KV数据的过程从query循环里拆出来,用异步拷贝指令把数据预取到shared memory,让计算和访存部分重叠。它还顺手帮我们调整了block内线程布局,让相邻线程读取连续地址,从而提升L2命中和DRAM burst效率。针对这一轮改动,我们做了复测,单次耗时从472us降到了331us,SMEff提升到了38%,L2 hit rate也提高到了71.4%。数字看起来不错,但还没有达到我们预期的性能目标,所以继续把它交给代理迭代。3.3 第二轮优化:根据occupancy和shared memory容量调整第二轮,代理没有直接改核心计算逻辑,而是让我们跑了一组occupancy实验,观察不同shared memory分配量下的实际占用率。跑完发现,当前kernel为了预取KV数据,把shared memory塞得很满,导致一个SM上同时驻留的block数量少了一半,warp级并行度不够,数据等待的时间盖过了异步拷贝带来的收益。代理根据这个现象给出一个新方案:不再为每个KV头分一块独立空间,而是把KV头按组共享同一块预取缓冲区,用索引标记区分不同组的位置。这样shared memory总量约下降了40%,occupancy从50%提升到了75%以上。这个改动对代码结构的影响不小,我们花了一些时间重构,测试之后单次耗时降到了282us。这个成绩已经达到了项目预期,我们决定就此收手,不再做激进优化。优化完成后的最终数据如下表:指标项基线数值优化后数值单次kernel平均耗时472us282usSMEff31%47%L2 hit rate62.1%79.3%SM busy wait占比18.7%9.2%寄存器spill量112 bytes/thread16 bytes/thread这个案例让我对LLM代理的实操价值有了更具体的认知。它两轮迭代分别解决了两个完全不同层次的问题:第一轮是访存路径不合理,第二轮是资源调配失衡。这两类问题在传统流程里,可能需要两个工程师分别排查,而且不一定能这么快给到可靠的修改方向。3.4 案例里我学到的取舍经验复盘这个案例,有一个点是很值得说的:代理第二轮建议重构shared memory分配策略时,它在输出里特别标注了“这个改动会引入索引计算开销,建议结合实测决定是否采用”。这个话术让我挺意外,因为它体现出了一种妥协意识:它知道自己推荐的方案不是免费的,需要权衡。我后来在别的项目里也遇到过类似情况,代理给出的最优方案A因为对代码侵入太大,被我们拒绝了,它随即生成了一个折中方案B,性能只比A差一点,但改动量小很多。这种“在约束条件下重新规划”的能力,对工程落地来说特别重要。同时也得说一句公道话,这个案例能顺利完成,前提是我们有比较严格的验证机制。代理每一轮给的代码,我们都跑了数值对比测试和单测,确认逻辑没有偏掉。LLM代理生成代码的想象力是够的,但约束性和边界条件依然是它的短板,需要人来兜底。4. 正确性验证与性能回归:让代理输出“可信”的工程保障4.1 正确性验证的三级围栏LLM代理再强,它在本质上还是一个概率模型,它可能给出结构漂亮但数值错误的代码。所以在所有流程里,我最重视的是正确性验证。我们的做法是设置三级围栏。第一级是静态检查。在编译阶段用编译器和代码扫描工具检查明显的数组越界、未初始化变量、类型不匹配问题。这一级能拦住大部分低级错误。第二级是数值校验。我们会对代理生成的kernel跑一组随机输入,和参考实现逐元素对比。对比时用相对误差和绝对误差双重判定。比如fp16的kernel我们一般设rtol=1e-2、atol=1e-2,fp32设rtol=1e-4。超过设定阈值就直接判失败,不会进入性能测试。第三级是场景回归。某些算子在小输入下正确,不代表在真实业务shape下也正确。所以我们会准备一组真实业务形状的测试样例,跑端到端对比,确保输出在可接受范围内。这套三级围栏跑一轮大概只需要几分钟,成本可控,但能极大减少代理代码引入线上问题的概率。4.2 性能回归看门狗正确性不是唯一的坑,性能回退同样要重视。我们在CI里挂了一个“性能看门狗”:每次代理提交新kernel版本,都必须和当前最优版本跑同一组benchmark,如果性能下降超过3%,这个版本会自动标记为失败,并附上详细对比数据。这个设计很关键,因为代理在优化过程中可能会在某一步“改回去”,导致性能倒挂;又或者它在局部优化某项指标,但整体性能变差了。比如有过一次,代理把某个访存密集kernel的global load全部改成了 더宽的向量类型,L2吞吐提升了不少,但因为指令issue宽度也被占满,计算效率反而下降了,整体耗时涨了5%。如果没有性能看门狗,我们很可能被L2吞吐这个“局部指标改善”误导。看门狗的逻辑我还想细化一下:它不只看固定基准,还会算一个“收益评估”。具体算法是,对于每个优化版本,记录它在不同shape下的耗时、带宽利用率和占用率,然后和一个线性插值得到的期望曲线对比。如果某个shape下性能大幅偏离期望,看门狗就会报警。这让我们能发现一些只有特定shape下才会暴露的问题。4.3 有效带宽与计算效率的计算逻辑验证性能时,除了跑一下看耗时的秒表,还要算两个硬指标:有效内存带宽和FLOPs利用率。这两个指标能告诉我们一个kernel到底在硬件能力方面发挥了几成。有效内存带宽的计算公式很简单:带宽 = 访存总量 / 实际耗时。比如一个kernel要读写的总数据量是8GB,实际耗时0.002秒,那有效带宽就是4000GB/s左右。把这个数值和硬件的理论峰值带宽做对比,就能快速判断是不是访存瓶颈。FLOPs利用率也类似:计算效率 = 实际计算量 /(耗时 × 硬件峰值算力)。举例来说,一个kernel的访存量是2GB,计算量是100TFLOPS,实际耗时0.0004秒,而硬件理论峰值是200TFLOPS,那么它的计算效率就是100 /(0.0004×200)约等于125%,说明有超额占用,大概率是和其他kernel在争抢资源。这些指标看似基础,但我发现很多团队在引入LLM代理之后反而容易忽略它们,原因是代理给出的报告里已经写了结论,大家懒得去验算。这绝对要不得。代理的结论只能作为参考,硬指标才是唯一可信的事实依据。4.4 人类与代理的分工边界工程保障做足之后,才到了人和代理怎么分工的问题。我的经验是:不要全自动,也不要完全人工,走“半自动”路线。代理负责出分析和代码,人负责审方案、卡准入、做最终决定。具体流程是:代理生成一批候选版本,每个版本附带详细说明;工程师快速浏览说明,挑出一个最合理的版本进入验证流水线;验证通过后,由工程师签字合并到主干。这里有一个容易被忽视的好处:代理给出的“附带说明”可以作为改动的审计日志。以前我们做kernel优化,经常出现“某天某个版本性能突变,但没人记得改了什么”的情况。现在代理每改一处都会生成一个简洁的第一性原理说明,长期积累下来,这是非常宝贵的技术文档。我自己在项目中,宁可让代理多花两分钟写清楚改动理由,也不接受它像一个黑盒一样直接把代码丢出来。因为黑盒的代码没法评审、没法维护,后面出了性能问题都无从查起。如果代理不解释,我就会把它当普通auto-tuning工具用,那就失去了“一等优化手段”的意义。5. 工程化集成:套件、流程与踩坑后的最佳实践5.1 一套可复用的工具链分层LLM代理作为一等优化手段,不是靠单个模型能力就能撑起来的,它需要一整套工程设施。我们内部总结了一个工具链的分层设计,大概分四层。数据层:负责收集和格式化基础数据,包括性能分析器的输出、SASS/PTX反汇编、源码、编译日志。这一层的核心工作是“把原始数据转化成结构化且易于检索的格式”。上下文组装层:负责从数据层中抽取和当前优化目标最相关的信息,组装成prompt。这个层是纯工程活,但非常重要。组装得好不好,直接决定代理分析质量。代理执行层:负责调用LLM、处理工具调用、管理多轮对话状态。这个层会记住前面分析过什么、改过什么,不需要每次从头讨论。验证层:负责编译、测试、性能对比,并把结果反馈回代理执行层。这个层充当了代理的“眼睛和手”,让它能做闭环推理。这套分层设计最大的好处是各层可以独立替换。比如性能分析器换了一款,只需要改数据层的解析逻辑,不影响其他层。LLM模型要升级,也只需要动代理执行层。5.2 离线优先与案例检索库说一个对落地影响巨大的经验:离线优先与案例检索库。我们最初直接把每次优化任务都发到在线大模型API上去处理,结果有几个问题:一是token开销不低,二是部分代码数据不适合频繁外传,三是模型经常没有往年案例记忆,每次遇到类似问题都要从零开始。后来我们改成了“离线优先”策略。本地维护一个轻量级代理环境,历史优化案例、profile快照、成功方案全部沉淀到本地向量库和结构化案例库里。新任务进来时,先做相似案例检索,把最相关的3-5个历史案例作为参照上下文,再让代理分析。这个改动带来的提升非常明显。以前代理第一次就给准方向的概率大概是40%到50%,加入案例检索之后,一次定位准的概率能到70%以上。尤其是同一个算子系列的优化,比如对GEMM、attention、layernorm这一类常见算子,历史案例的复用价值极高。我个人的观点是:到了2026年下半年,优化一个kernel的能力瓶颈,已经不在于模型服务本身强不强,而在于你的案例积累和检索工具有没有沉淀好。5.3 人工介入时机的判断还有一个经验是关于“什么时候该人工接管”。我们给代理设了一些触发条件:代理连续三轮没有产出有效迭代方案,或者连续两次在同一个问题上犯了同类型错误,或者验证流水线连续三次失败时,系统会自动向工程师发出求助信号。这个时候,工程师必须介入,而不是继续让代理自行尝试。为什么这么设计?因为LLM代理在明确了错误信号的场景下是能自我修正的,但在“方向错了但还没暴露”的情况下,它会沿着错误方向重复试探,浪费时间和计算资源。人工介入的临界点要设在“方向可疑”的时候,而不是“彻底失败”的时候。举例来说,有一次代理连续两轮都在调整block size,但每次调整之后性能都在原地打转。工程师介入后发现,它的优化方向完全被profile里的某个次要瓶颈带偏了,真正的瓶颈是shared memory的bank conflict。这个信息一输入,代理立刻切到了正确路径。如果没有人打断,它可能还要多浪费几轮。5.4 从“能用”到“好用”的工程细节最后补充几个从“能用”到“好用”的工程细节。第一,善用结构化输出。我们要求代理按统一JSON格式返回分析结论、改动说明和风险点,而不是自由格式文本。这样后续验证层可以直接解析,还能生成结构化报告。第二,缓存历史验证结果。同一个kernel的同类优化任务,如果验证结果已经存在,就不用重复跑测试,直接查缓存就能知道上次结果。这个机制在代理多轮迭代时特别高效。第三,持久化中间产物。代理在优化过程里可能会生成一些被否掉的候选版本,我们不会删掉,而是保留下来作为负面案例。这些案例在后续训练检索模型、或者做自动评测时都很有价值。这些细节看起来不起眼,但真正跑过几个项目之后,你就会发现,LLM代理能不能稳定发挥作用,往往取决于这些工程地基,而不是单一的大模型能力。6. 常见问题与排查实录6.1 代理给出的代码频繁编译失败怎么办这个问题几乎是100%会遇到的。代理生成的代码往往思路没问题,但细节总有疏漏。我们的处理办法是:把编译错误日志原样喂回给代理,让它自己修改。这里有个关键点,日志要完整,包括具体的行号和错误消息,不能只给个“编译失败”这种抽象信息。另外,我们设置了编译错误次数上限。同一个任务里,代理编译失败超过三次,我们会强制它停下来反思,让它重新读一遍自己之前生成的代码、对比正确的参考实现,然后再提交。实测下来,这个“反思”机制能明显降低连续编译失败的概率。6.2 代理生成的kernel数值误差超限怎么办数值误差超限的问题,常见于浮点运算顺序被代理改变、或者归约逻辑重写后引入精度损失。我们的排查顺序是先缩小范围:用相同输入分别跑代理代码和参考代码,定位第一个误差超过容忍度的输出位置。然后把那一小段代码单独拿出来交给代理看,让它分析误差来源。多数情况是因为它为了优化性能,把求和顺序换成了树形归约或者增加了并行累加次数,导致舍入误差变大。如果代理给的修复方案涉及牺牲一点性能换取精度,我们一般会接受,因为对于大多数推理场景,稳定性和精度比那百分之一的性能提升重要得多。6.3 上下文太长,关键信息丢失怎么办LLM代理处理大kernel时会遇到一个问题:源码好几千行、汇编上万行,全塞进上下文里不仅成本高,而且关键信号被淹没。我们的解决思路是“先摘要,再展开”。先让一个轻量脚本生成kernel的结构摘要,包括主要循环、访存指令类型、共享内存使用情况、关键函数调用关系。代理基于摘要判断最可能的瓶颈区域,然后只针对那个区域去读完整源码。这个机制几乎可以解决全部上下文长度问题。需要注意的是,摘要的质量直接决定后续分析准确性,所以我们对摘要脚本的要求是:必须保留与性能相关的信息,比如循环内是否有乘加链、是否有bank冲突风险,这些要比代码的注释重要得多。6.4 代理自信地给出错误结论时怎么办LLM代理有时会以非常肯定的语气给出错误结论,这是它作为概率模型的天性。我的经验是:不要试图靠“话术”让它变得谦虚,而是靠机制对冲风险。一个有效方法是引入“双模型对抗”。主代理负责出方案,一个独立的评审模型负责挑毛病。评审模型不直接生成优化方案,只负责检查现有方案的逻辑漏洞和风险点。如果评审模型提出了质疑,主代理必须针对质疑做出回应,并决定是否修改。这个“提议-反驳-修正”的结构实操下来效果不错,可以把明显有逻辑漏洞的方案挡在验证流水线之前。6.5 关于“代理的一等化”最后想说的话做到这里,回头看整个变化,我最大的感触是:LLM代理成为一等优化手段,靠的不只是模型变聪明了,而是我们把整个优化流程重新设计了一遍。让代理能在正确的时间、接触正确的数据、产生正确的动作、收到正确的反馈。我踩过不少坑,也走过弯路,但最终沉淀下来一套可复用的工作流。如果你也在尝试把LLM代理引入到自己的GPU/AI算子优化流程里,我建议先别急着追求全自动,而是从“代理生成建议 + 人工决策 + 自动验证”这种半自动模式开始。跑通闭环之后,再逐步把更多决策权交给代理。更重要的是,把每一轮优化的案例都沉淀下来,形成自己的案例库。大模型本身没有记忆力,案例库才是你和代理共同积累的长期记忆。有了这个记忆,LLM代理才能真正从一个偶尔灵光的咨询顾问,变成一个越来越靠谱的“一等优化手段”。
做GPU算子优化这行,真正让我觉得工作流被彻底重写的转折点,是2026年下半年开始,我们把LLM代理正式当成“一等优化手段”来用。以前提到优化kernel,大家脑子里是Nsight Compute、SASS汇编、occupancy分析这些传统套路,现在我的日常工作流里,最核心的步骤变成了:让LLM代理读一份完整的profile报告,自己定位瓶颈,生成候选kernel,然后跑验证闭环。这件事放在两年前我不敢想,放在半年前我觉得还不太成熟,但到了2026年下半年,它已经是我们在某个AI推理项目中实打实用起来的主力方案。这篇文章就围绕这个变化展开。我会把LLM代理为什么能在kernel优化里从“辅助工具”升级成“一等手段”讲清楚,然后拆解一套完整的优化流程,再给一个GQA算子优化的具体案例,最后聊聊正确性验证、工程化集成和踩过的坑。适合正在做GPU算子优化、AI编译优化、推理引擎开发,或者对LLM agent落地感兴趣的朋友。1. 变化从何而来:LLM代理凭什么成为“一等优化手段”1.1 什么叫做“一等优化手段”先解释一下我说的“一等优化手段”。它不是指你打开一个对话框,问一句“我这个kernel为什么慢”,然后让模型给一堆泛泛的建议。那只是辅助,连二等都算不上,顶多是个人工智障答疑。我理解的“一等优化手段”是:LLM代理被内嵌到优化闭环里,它有自己的输入管道,能读取性能分析器的原始输出、汇编代码、调度参数和源码;它有自己的工具调用能力,能编译、能跑测试、能收集反馈;它还能基于前一轮跑出来的结果自我迭代,直到性能或者正确性指标满足要求为止。换句话说,它从一个“问答机器人”变成了优化流水线里的一个“决策节点”。这个节点可以对优化动作负责,而且关键的是,它可以解释自己的决策依据。1.2 传统优化流程到底哪里卡脖子要理解这个变化,得先知道以前我们是怎么做kernel优化的。常规流程大概是:跑一个benchmark,拿到profile热点函数,然后用GPU性能分析工具去看这个kernel的occupancy、访存带宽、bank conflict、指令吞吐这些指标。很多时候一眼就能看出来是访存瓶颈还是计算瓶颈,但问题是,当你要深入优化的时候,你面对的是一个巨大的搜索空间。以一次典型优化为例:同样一个GEMM kernel,可能有十几种tiling策略、三五种子块尺寸、两种数据排布方式、若干共享内存padding方案。你怎么知道哪种组合最优?很多团队靠经验、靠文档、靠试错。传统auto-tuning也能做,但它是一个黑盒搜索,代价高、可解释性差,而且它不会告诉你“为什么这个方案好”。LLM代理的价值在于,它把“从profile数据里读取线索”“回忆历史优化案例”“生成候选代码”“判断瓶颈类型”这些能力整合到了一起。它改变了优化动作的产生方式:不再是一步步手查指标,而是基于完整上下文的一次性综合诊断。1.3 为什么是2026年下半年才爆发其实LLM代理能读代码、能生成代码这件事并不新鲜,但在2026年下半年,几个条件终于凑齐了。第一个是上下文窗口和处理能力。优化一个kernel往往需要同时看几千行源码、几百行SASS、一份几MB的profile JSON。过去这些数据根本塞不进上下文,现在可以了,而且在结构化摘要之后,重要信息不会丢。第二个是工具链的打通。GPU原厂分析器的输出格式越来越结构化,编译器的中间表示也开始面向工具开放,这让LLM代理都能直接解析原始数据,不再需要人手工转述。第三个是验证闭环的成熟。LLM代理生成代码之后,我们可以让它在沙箱里编译、跑数值校验、跑性能回归,然后把结果反馈给它进行下一轮迭代。没有这个闭环,代理的建议就永远是“建议”,而有了闭环,它就变成了一个真正能干活、能担责的优化执行者。我自己体会比较深的一点是:在这个时间点,劣化优化(也就是用LLM代理做“分析到改代码的最后一公里”)已经不是一个实验性玩法了,它在工程上稳定到可以进CI、支持回滚、做灰度验证。这就是我决定把它当作一等手段的根本原因。2. 全流程重构:LLM代理介入kernel优化的四个关键环节2.1 Profile数据预处理与瓶颈判定第一环,也是最基础的一环,是把原始的profile数据变成LLM代理能直接理解的结构化上下文。这个环节我以前做得非常痛苦。性能分析器导出的报告虽然很全,但信息密度极低,几千行指标只有几个是关键的。如果直接把原始报告全部塞给LLM代理,它很容易被噪音干扰,而且token消耗会很夸张。所以我们在前面加了一层预处理脚本,从分析器输出里抽取最核心的信号,包括:kernel执行时间占比warp占用率与理论占用率的比值全局内存/共享内存的访存指令占比主要stalall或wait原因计数指令issue rate说明计算单元还是没有喂饱这些信号组合成一个压缩后的“瓶颈快照”,和源码片段、编译选项一起交给LLM代理。代理拿到之后,会先输出一个瓶颈分类结论,比如“这是一个访存密集型瓶颈,主要卡在L2 miss和global load延迟上”或者“这是指令延迟型瓶颈,shared memory bank conflict导致stall”。这一步的输出质量直接决定后续优化方向对不对,所以我们用了不少心思在快照的生成规则上。实践中,我们还会让代理对“快照”给一个置信度。这个置信度不是它自己拍脑袋,而是通过一个历史案例库做相似度匹配得到的。如果当前这个kernel的特征和之前某个成功优化的案例高度相似,置信度就会高一些。有了这个机制,我们敢让代理直接给出优化动作,而不是只停留在分析层面。2.2 候选策略生成与kernel改写瓶颈判定完之后,重头戏就来了:让LLM代理基于诊断结果直接产生候选代码。这个环节和普通代码生成完全不是一回事。普通代码生成是“你给我一个描述,我写一个实现”,而kernel优化里的改写更像做一个高强度的代码迁移手术。它得读现有的SASS/PTX,判断哪些循环该展开,哪些内存访问可以合并,哪些延迟可以通过异步拷贝掩盖,然后把这些改动落到CUDA/Triton级别的源码上。举个例子,在某个reduce类kernel里,代理发现内核里有一段串行的原子操作,导致整个block的吞吐被拖死。它会建议把原子操作替换成先warp内reduce再原子写的方式,并且直接生成替换后的代码。这个建议放到以前,需要一个人熟读CUDA编程指南、理解硬件执行模型之后才能给出来,现在代理在几十秒内就能给出一版初稿。当然,初稿不一定能直接通过编译。我们在工作中经常遇到的情况是:代理改完的代码在语法上没问题,但在某个边界条件上处理错了,比如shared memory数组下标越界。这种情况我们不会直接弃用,而是会把编译错误信息喂回给代理,让它自己修复。多轮修复之后,代码质量基本能接近熟练工程师的水平。这个环节里,我们最看重的是“可解释的改动”。代理生成每一个改动时,都要附带一段理由说明,解释这个改动和瓶颈判定之间的因果关系。这段理由后面会成为优化记录的一部分,方便我们审计。2.3 编译选项与启动参数联合搜索kernel优化不只是改代码,很多时候启动配置比代码本身还重要。一个kernel最终的性能,同时取决于block大小、grid大小、shared memory动态分配量、编译选项里的优化级别、ptxas选项。传统的做法是写一个Python脚本,把这几个参数作为变量,跑一遍网格搜索或者贝叶斯搜索。这个方法的问题是会陷入局部最优,而且搜索次数上去了,成本很高。LLM代理在这个环节的作用,是把“内容特征”和“参数空间”连接起来。它会分析kernel访存模式和计算密度,给出一个更聪明的启动配置起点。举例来说,如果一个kernel的访存模式是连续广播式的,代理会优先考虑使用较小的block配合较大的grid;如果计算密度高,它可能倾向用更高的寄存器上限来压低spill。然后它不会只给一组参数,而是会生成一个参数矩阵,交给底层搜索器去做局部验证。这样搜索空间被大幅缩减,而且搜索方向有先验知识引导,收敛效率高很多。我在实际项目里测过,同样一个kernel、同样一个搜索预算,用LLM代理给出的起点比随机起点快3-5倍收敛。更重要的是,代理会在搜索过程中看中间结果,如果某组参数虽然慢但在profile里显示某个指标明显改善,它会把那组参数保留下来做进一步调查,而不是简单丢掉。2.4 验证与迭代闭环最后一个环节,也是让LLM代理真正“长跑”的关键:验证与迭代闭环。我们把代理生成的候选kernel放进一个统一的验证流水线里。这个流水线会做四件事:编译、数值校验、性能回归、细节指标收集。每一件事的结果都会被格式化成结构化的反馈,再送回给代理。代理看到反馈之后,会根据情况选择接受当前方案、继续微调某一处代码、或者完全推翻换一个思路。这套闭环机制让代理有了一种“干活”的感觉。它不是在一次性生成终极答案,而是在一个可控的循环里逐步逼近目标。我见过代理一轮优化不满意,第二轮加大了shared memory的复用粒度,第三轮发现导致bank conflict又做了一次padding,第四轮终于达到目标。整个过程大概两个多小时,换作人工操作,至少得一天。关于闭环,我特别想强调一个经验:反馈信息要分层。不要只把“性能提升了23%”这种笼统结果给代理,要把具体指标也放进去,比如“L2吞吐从XX提升到XX”“bank conflict计数从XX降到XX”“寄存器spill从XX降低到0”。代理只有看到这些细节,才能在下一次改写时做出有针对性的决策,而不是继续瞎试。3. 真实案例复盘:一个GQA kernel的完整优化过程3.1 案例背景与基线数据我拿一个实际做过的案例来复盘,这样看得更直观。项目背景是一个AI推理框架,里面某一段GQA(Grouped Query Attention)算子在特定序列长度和batch配置下,占据了端到端推理时间的19%左右。这个占比对注意力类算子来说偏高了,我们团队决定对它做一轮深度优化。先看基线profile数据。我们跑了一组测试,记录下来的关键指标如下表所示:指标项基线数值单次kernel平均耗时472usSMEff(流式多处理器实际利用率指标)31%全局load执行占比24.5%L2 hit rate62.1%SM busy wait占比18.7%寄存器spill量112 bytes/thread从这组数据里,基本能判断几个问题:首先,SM busy wait占比很高,说明warp在等数据,而不是在跑指令;其次,L2 hit rate不到65%,说明访存局部性很差;再加上全局load占比接近四分之一,这是一个典型的访存等待型瓶颈。如果是过去的流程,我会基于这些指标手工去翻源码找访存方式,然后试几种方案。这一次,我们把原始报告和源码直接交给了LLM代理。3.2 第一轮优化:从访存路径和指令排布动手代理拿到数据之后,第一轮给出来的诊断是:这个kernel的主要延迟来源是KV cache读取阶段。它发现当时的实现里,每个query会依次读取对应的多个KV头,这个读取过程没有做向量化,导致产生大量细粒度的非对齐load,L2请求次数被放大。代理给出的修改建议是:把KV读取的指针访问改成float4对齐路径,同时把读取KV数据的过程从query循环里拆出来,用异步拷贝指令把数据预取到shared memory,让计算和访存部分重叠。它还顺手帮我们调整了block内线程布局,让相邻线程读取连续地址,从而提升L2命中和DRAM burst效率。针对这一轮改动,我们做了复测,单次耗时从472us降到了331us,SMEff提升到了38%,L2 hit rate也提高到了71.4%。数字看起来不错,但还没有达到我们预期的性能目标,所以继续把它交给代理迭代。3.3 第二轮优化:根据occupancy和shared memory容量调整第二轮,代理没有直接改核心计算逻辑,而是让我们跑了一组occupancy实验,观察不同shared memory分配量下的实际占用率。跑完发现,当前kernel为了预取KV数据,把shared memory塞得很满,导致一个SM上同时驻留的block数量少了一半,warp级并行度不够,数据等待的时间盖过了异步拷贝带来的收益。代理根据这个现象给出一个新方案:不再为每个KV头分一块独立空间,而是把KV头按组共享同一块预取缓冲区,用索引标记区分不同组的位置。这样shared memory总量约下降了40%,occupancy从50%提升到了75%以上。这个改动对代码结构的影响不小,我们花了一些时间重构,测试之后单次耗时降到了282us。这个成绩已经达到了项目预期,我们决定就此收手,不再做激进优化。优化完成后的最终数据如下表:指标项基线数值优化后数值单次kernel平均耗时472us282usSMEff31%47%L2 hit rate62.1%79.3%SM busy wait占比18.7%9.2%寄存器spill量112 bytes/thread16 bytes/thread这个案例让我对LLM代理的实操价值有了更具体的认知。它两轮迭代分别解决了两个完全不同层次的问题:第一轮是访存路径不合理,第二轮是资源调配失衡。这两类问题在传统流程里,可能需要两个工程师分别排查,而且不一定能这么快给到可靠的修改方向。3.4 案例里我学到的取舍经验复盘这个案例,有一个点是很值得说的:代理第二轮建议重构shared memory分配策略时,它在输出里特别标注了“这个改动会引入索引计算开销,建议结合实测决定是否采用”。这个话术让我挺意外,因为它体现出了一种妥协意识:它知道自己推荐的方案不是免费的,需要权衡。我后来在别的项目里也遇到过类似情况,代理给出的最优方案A因为对代码侵入太大,被我们拒绝了,它随即生成了一个折中方案B,性能只比A差一点,但改动量小很多。这种“在约束条件下重新规划”的能力,对工程落地来说特别重要。同时也得说一句公道话,这个案例能顺利完成,前提是我们有比较严格的验证机制。代理每一轮给的代码,我们都跑了数值对比测试和单测,确认逻辑没有偏掉。LLM代理生成代码的想象力是够的,但约束性和边界条件依然是它的短板,需要人来兜底。4. 正确性验证与性能回归:让代理输出“可信”的工程保障4.1 正确性验证的三级围栏LLM代理再强,它在本质上还是一个概率模型,它可能给出结构漂亮但数值错误的代码。所以在所有流程里,我最重视的是正确性验证。我们的做法是设置三级围栏。第一级是静态检查。在编译阶段用编译器和代码扫描工具检查明显的数组越界、未初始化变量、类型不匹配问题。这一级能拦住大部分低级错误。第二级是数值校验。我们会对代理生成的kernel跑一组随机输入,和参考实现逐元素对比。对比时用相对误差和绝对误差双重判定。比如fp16的kernel我们一般设rtol=1e-2、atol=1e-2,fp32设rtol=1e-4。超过设定阈值就直接判失败,不会进入性能测试。第三级是场景回归。某些算子在小输入下正确,不代表在真实业务shape下也正确。所以我们会准备一组真实业务形状的测试样例,跑端到端对比,确保输出在可接受范围内。这套三级围栏跑一轮大概只需要几分钟,成本可控,但能极大减少代理代码引入线上问题的概率。4.2 性能回归看门狗正确性不是唯一的坑,性能回退同样要重视。我们在CI里挂了一个“性能看门狗”:每次代理提交新kernel版本,都必须和当前最优版本跑同一组benchmark,如果性能下降超过3%,这个版本会自动标记为失败,并附上详细对比数据。这个设计很关键,因为代理在优化过程中可能会在某一步“改回去”,导致性能倒挂;又或者它在局部优化某项指标,但整体性能变差了。比如有过一次,代理把某个访存密集kernel的global load全部改成了 더宽的向量类型,L2吞吐提升了不少,但因为指令issue宽度也被占满,计算效率反而下降了,整体耗时涨了5%。如果没有性能看门狗,我们很可能被L2吞吐这个“局部指标改善”误导。看门狗的逻辑我还想细化一下:它不只看固定基准,还会算一个“收益评估”。具体算法是,对于每个优化版本,记录它在不同shape下的耗时、带宽利用率和占用率,然后和一个线性插值得到的期望曲线对比。如果某个shape下性能大幅偏离期望,看门狗就会报警。这让我们能发现一些只有特定shape下才会暴露的问题。4.3 有效带宽与计算效率的计算逻辑验证性能时,除了跑一下看耗时的秒表,还要算两个硬指标:有效内存带宽和FLOPs利用率。这两个指标能告诉我们一个kernel到底在硬件能力方面发挥了几成。有效内存带宽的计算公式很简单:带宽 = 访存总量 / 实际耗时。比如一个kernel要读写的总数据量是8GB,实际耗时0.002秒,那有效带宽就是4000GB/s左右。把这个数值和硬件的理论峰值带宽做对比,就能快速判断是不是访存瓶颈。FLOPs利用率也类似:计算效率 = 实际计算量 /(耗时 × 硬件峰值算力)。举例来说,一个kernel的访存量是2GB,计算量是100TFLOPS,实际耗时0.0004秒,而硬件理论峰值是200TFLOPS,那么它的计算效率就是100 /(0.0004×200)约等于125%,说明有超额占用,大概率是和其他kernel在争抢资源。这些指标看似基础,但我发现很多团队在引入LLM代理之后反而容易忽略它们,原因是代理给出的报告里已经写了结论,大家懒得去验算。这绝对要不得。代理的结论只能作为参考,硬指标才是唯一可信的事实依据。4.4 人类与代理的分工边界工程保障做足之后,才到了人和代理怎么分工的问题。我的经验是:不要全自动,也不要完全人工,走“半自动”路线。代理负责出分析和代码,人负责审方案、卡准入、做最终决定。具体流程是:代理生成一批候选版本,每个版本附带详细说明;工程师快速浏览说明,挑出一个最合理的版本进入验证流水线;验证通过后,由工程师签字合并到主干。这里有一个容易被忽视的好处:代理给出的“附带说明”可以作为改动的审计日志。以前我们做kernel优化,经常出现“某天某个版本性能突变,但没人记得改了什么”的情况。现在代理每改一处都会生成一个简洁的第一性原理说明,长期积累下来,这是非常宝贵的技术文档。我自己在项目中,宁可让代理多花两分钟写清楚改动理由,也不接受它像一个黑盒一样直接把代码丢出来。因为黑盒的代码没法评审、没法维护,后面出了性能问题都无从查起。如果代理不解释,我就会把它当普通auto-tuning工具用,那就失去了“一等优化手段”的意义。5. 工程化集成:套件、流程与踩坑后的最佳实践5.1 一套可复用的工具链分层LLM代理作为一等优化手段,不是靠单个模型能力就能撑起来的,它需要一整套工程设施。我们内部总结了一个工具链的分层设计,大概分四层。数据层:负责收集和格式化基础数据,包括性能分析器的输出、SASS/PTX反汇编、源码、编译日志。这一层的核心工作是“把原始数据转化成结构化且易于检索的格式”。上下文组装层:负责从数据层中抽取和当前优化目标最相关的信息,组装成prompt。这个层是纯工程活,但非常重要。组装得好不好,直接决定代理分析质量。代理执行层:负责调用LLM、处理工具调用、管理多轮对话状态。这个层会记住前面分析过什么、改过什么,不需要每次从头讨论。验证层:负责编译、测试、性能对比,并把结果反馈回代理执行层。这个层充当了代理的“眼睛和手”,让它能做闭环推理。这套分层设计最大的好处是各层可以独立替换。比如性能分析器换了一款,只需要改数据层的解析逻辑,不影响其他层。LLM模型要升级,也只需要动代理执行层。5.2 离线优先与案例检索库说一个对落地影响巨大的经验:离线优先与案例检索库。我们最初直接把每次优化任务都发到在线大模型API上去处理,结果有几个问题:一是token开销不低,二是部分代码数据不适合频繁外传,三是模型经常没有往年案例记忆,每次遇到类似问题都要从零开始。后来我们改成了“离线优先”策略。本地维护一个轻量级代理环境,历史优化案例、profile快照、成功方案全部沉淀到本地向量库和结构化案例库里。新任务进来时,先做相似案例检索,把最相关的3-5个历史案例作为参照上下文,再让代理分析。这个改动带来的提升非常明显。以前代理第一次就给准方向的概率大概是40%到50%,加入案例检索之后,一次定位准的概率能到70%以上。尤其是同一个算子系列的优化,比如对GEMM、attention、layernorm这一类常见算子,历史案例的复用价值极高。我个人的观点是:到了2026年下半年,优化一个kernel的能力瓶颈,已经不在于模型服务本身强不强,而在于你的案例积累和检索工具有没有沉淀好。5.3 人工介入时机的判断还有一个经验是关于“什么时候该人工接管”。我们给代理设了一些触发条件:代理连续三轮没有产出有效迭代方案,或者连续两次在同一个问题上犯了同类型错误,或者验证流水线连续三次失败时,系统会自动向工程师发出求助信号。这个时候,工程师必须介入,而不是继续让代理自行尝试。为什么这么设计?因为LLM代理在明确了错误信号的场景下是能自我修正的,但在“方向错了但还没暴露”的情况下,它会沿着错误方向重复试探,浪费时间和计算资源。人工介入的临界点要设在“方向可疑”的时候,而不是“彻底失败”的时候。举例来说,有一次代理连续两轮都在调整block size,但每次调整之后性能都在原地打转。工程师介入后发现,它的优化方向完全被profile里的某个次要瓶颈带偏了,真正的瓶颈是shared memory的bank conflict。这个信息一输入,代理立刻切到了正确路径。如果没有人打断,它可能还要多浪费几轮。5.4 从“能用”到“好用”的工程细节最后补充几个从“能用”到“好用”的工程细节。第一,善用结构化输出。我们要求代理按统一JSON格式返回分析结论、改动说明和风险点,而不是自由格式文本。这样后续验证层可以直接解析,还能生成结构化报告。第二,缓存历史验证结果。同一个kernel的同类优化任务,如果验证结果已经存在,就不用重复跑测试,直接查缓存就能知道上次结果。这个机制在代理多轮迭代时特别高效。第三,持久化中间产物。代理在优化过程里可能会生成一些被否掉的候选版本,我们不会删掉,而是保留下来作为负面案例。这些案例在后续训练检索模型、或者做自动评测时都很有价值。这些细节看起来不起眼,但真正跑过几个项目之后,你就会发现,LLM代理能不能稳定发挥作用,往往取决于这些工程地基,而不是单一的大模型能力。6. 常见问题与排查实录6.1 代理给出的代码频繁编译失败怎么办这个问题几乎是100%会遇到的。代理生成的代码往往思路没问题,但细节总有疏漏。我们的处理办法是:把编译错误日志原样喂回给代理,让它自己修改。这里有个关键点,日志要完整,包括具体的行号和错误消息,不能只给个“编译失败”这种抽象信息。另外,我们设置了编译错误次数上限。同一个任务里,代理编译失败超过三次,我们会强制它停下来反思,让它重新读一遍自己之前生成的代码、对比正确的参考实现,然后再提交。实测下来,这个“反思”机制能明显降低连续编译失败的概率。6.2 代理生成的kernel数值误差超限怎么办数值误差超限的问题,常见于浮点运算顺序被代理改变、或者归约逻辑重写后引入精度损失。我们的排查顺序是先缩小范围:用相同输入分别跑代理代码和参考代码,定位第一个误差超过容忍度的输出位置。然后把那一小段代码单独拿出来交给代理看,让它分析误差来源。多数情况是因为它为了优化性能,把求和顺序换成了树形归约或者增加了并行累加次数,导致舍入误差变大。如果代理给的修复方案涉及牺牲一点性能换取精度,我们一般会接受,因为对于大多数推理场景,稳定性和精度比那百分之一的性能提升重要得多。6.3 上下文太长,关键信息丢失怎么办LLM代理处理大kernel时会遇到一个问题:源码好几千行、汇编上万行,全塞进上下文里不仅成本高,而且关键信号被淹没。我们的解决思路是“先摘要,再展开”。先让一个轻量脚本生成kernel的结构摘要,包括主要循环、访存指令类型、共享内存使用情况、关键函数调用关系。代理基于摘要判断最可能的瓶颈区域,然后只针对那个区域去读完整源码。这个机制几乎可以解决全部上下文长度问题。需要注意的是,摘要的质量直接决定后续分析准确性,所以我们对摘要脚本的要求是:必须保留与性能相关的信息,比如循环内是否有乘加链、是否有bank冲突风险,这些要比代码的注释重要得多。6.4 代理自信地给出错误结论时怎么办LLM代理有时会以非常肯定的语气给出错误结论,这是它作为概率模型的天性。我的经验是:不要试图靠“话术”让它变得谦虚,而是靠机制对冲风险。一个有效方法是引入“双模型对抗”。主代理负责出方案,一个独立的评审模型负责挑毛病。评审模型不直接生成优化方案,只负责检查现有方案的逻辑漏洞和风险点。如果评审模型提出了质疑,主代理必须针对质疑做出回应,并决定是否修改。这个“提议-反驳-修正”的结构实操下来效果不错,可以把明显有逻辑漏洞的方案挡在验证流水线之前。6.5 关于“代理的一等化”最后想说的话做到这里,回头看整个变化,我最大的感触是:LLM代理成为一等优化手段,靠的不只是模型变聪明了,而是我们把整个优化流程重新设计了一遍。让代理能在正确的时间、接触正确的数据、产生正确的动作、收到正确的反馈。我踩过不少坑,也走过弯路,但最终沉淀下来一套可复用的工作流。如果你也在尝试把LLM代理引入到自己的GPU/AI算子优化流程里,我建议先别急着追求全自动,而是从“代理生成建议 + 人工决策 + 自动验证”这种半自动模式开始。跑通闭环之后,再逐步把更多决策权交给代理。更重要的是,把每一轮优化的案例都沉淀下来,形成自己的案例库。大模型本身没有记忆力,案例库才是你和代理共同积累的长期记忆。有了这个记忆,LLM代理才能真正从一个偶尔灵光的咨询顾问,变成一个越来越靠谱的“一等优化手段”。