TIRx Harness:为Agentic GPU编程打造的开源编译器试验台 如果你过去一年也一直在关注 AI 编程这件事大概能发现一个很有意思的分化让大模型写网页、写 Python 脚本、处理日常业务逻辑它们已经能顶半个初级工程师但一旦落到高性能 GPU kernel 这个层级情况就完全不是一回事。生成的 CUDA 代码看起来像模像样一编译就报错一跑起来数值爆炸好不容易跑通了性能又可能比一个 naive baseline 还慢。我做 TIRx Harness 这个开源项目就是想给Agentic GPU Programming提供一个真正可用的Open Compiler Harness——说白了它不是一个帮你写 kernel 的编译器而是一个让AI agent 写 kernel这件事变得可验证、可迭代、可度量的试验台。这篇文章会把整个项目的定位、架构、实操流程和踩坑记录完整过一遍适合正在做 AI 辅助高性能计算、或者想在自己工作流里引入 agent 编程的工程师参考。市面上已经有很多AI 生成代码的工具但它们大多停在了生成代码这一步后面的编译、运行、正确性校验、性能对比全得靠人肉接力。TIRx Harness 想解决的恰好是这条路最后、也是最麻烦的一段怎么让 agent 生成的东西能被自动地验证、反馈、优化形成闭环。项目本身不绑定特定的大模型也不绑定固定的编译器后端它把中间表示、代码生成、评测反馈这几个环节做成可插拔的接口任何想要把 LLM 引入 GPU 编程流程的团队都能基于它快速搭出自己的工具链。整个项目是开放的代码、评测样例、反馈协议全部公开这也是Open Compiler Harness这个名字里 Open 的真正含义。1. 项目定位给 Agentic GPU 编程准备一个试验台1.1 TIRx Harness 到底是什么先把名字拆开看。Harness 在工程里的通常含义是固定住被测对象、提供输入输出通道、收集结果的辅助装置最常见的例子是测试框架里那一层 fixture。编译器领域的环境compiler harness则会负责翻译命令行、注入环境变量、抓取编译产物让同一个测试套件能跑在不同的编译器上。TIRx Harness 继承的正是这个理念它把GPU kernel 生成、编译、运行、验证这整条流水线包装成一套可控的框架让外部调用者——不管是人还是 AI agent——可以反复向它提交代码然后拿回结构化的结果。TIRx 里的 TIR指的是Tensor Intermediate Representation也就是以张量计算为核心的中间表示层。熟悉 TVM 生态的同学对 TIR 应该不陌生它是一套带类型的、面向硬件的低层 IR既保留了循环、缓冲、线程绑定这类硬件细节又有明确的语义边界。TIRx 里的 x我把它解释成 experimental 或 extended我们不是要重新发明一套 IR而是把 TIR 的编译与验证流程做成一个开放 harness。所以 TIRx Harness 解决的问题可以概括成一句话当你的 agent 拿到一个算子需求比如写一个 row-wise softmax kernel输入是 8192×512 的 float32 张量它生成一段 CUDA 代码之后这个 harness 负责回答接下来所有的问题——这段代码能编译吗跑起来结果对吗和手写 baseline 比是快还是慢差距具体体现在哪这些问题如果让人类一个一个去查一次迭代可能就要半小时而 harness 的目的是把它压缩到几十秒内并且把结果整理成 agent 能直接消费的反馈。1.2 为什么中间要插一层 TIR而不是让 agent 直接吐 CUDA这是项目设计里我最想深入说的一点。很多人第一反应是既然最终目标是 CUDA 代码为什么不让 agent 直接写 CUDA跳过 TIR 这一层答案是直接写 CUDA 确实存在但它让整个闭环变成了黑盒对黑盒。如果你让 agent 直接生成 CUDA反馈回路里就只有两个节点编译器和 profiler。编译器只会告诉你这句语法错了或者这里用了非法内存操作而 profiler 只会给你一个时间或吞吐数字。这两类反馈都是低信噪比的因为它们不携带结构性的、可定位的问题描述。比如一个 kernel 性能差 30%可能是 tile 大小不合理可能是内存访问没有合并可能是共享内存 bank conflict也可能是 occupancy 太低。这些原因在 profiler 的输出里混在一起agent 很难直接拿来做下一轮改进。TIR 这一层提供了更好的介入点。TIR 里的计算逻辑和调度策略是分离的你可以用 schedule 原语split、fuse、reorder、vectorize、parallel、cache_read 这些把计算映射到 GPU 线程和显存结构上而不是在纯 CUDA 代码里手动管理所有细节。这意味着harness 在 IR 层面可以给 agent 提供更精确的反馈比如你的向量化因子设成 4但 TIR 校验发现尾部的处理分支会产生多余的 predicated instructions或者这个 shared memory 的复用模式导致 bank conflict建议调整 split 的比例。这类反馈是结构化、可消耗的而不是让 agent 去猜。1.3 和直接用模板 nvcc这类方案有什么本质区别我用一个对比表来说明这也是我在项目文档里反复强调的设计分界线方案生成方式验证方式反馈质量可扩展性手写模板 人工调参人写代码人跑测试凭经验判断极差LLM 直接生成 CUDA模型生成人复制到工程里编译编译器报错 人工 profiling差Agent 编译执行验证模型生成自动编译运行通过/失败 简单耗时中等TIRx Harness模型生成 TIR 或 CUDA 后统一降级自动编译 数值校验 性能对比结构化错误报告 数值分布 性能归因好区别的核心不在于听起来更高级而在于feedback loop 的质量。前两种方案里反馈是给人类看的LLM 只是代码生成器TIRx Harness 做的事情是把反馈设计成给 agent 看的——每条反馈都有明确的结构、字段和可操作的语义。没有这一层哪怕模型能力再强也很难在多轮迭代里稳定收敛到一个既正确又快的 kernel。后面章节我会用实际案例说明这一点。2. 整体架构与设计取舍2.1 三层结构Agent Runtime、Compilation Core、Evaluation LayerTIRx Harness 在代码上分三个相互独立的模块它们之间有明确的接口协议可以单独替换。第一层是Agent Runtime。这一层负责和大模型通信拼 prompt、接收模型输出、把输出解析成结构化的 kernel source 或 TIR 程序。设计上这一层完全不假设你用的是哪家模型。我只依赖一个OpenAI-compatible chat/completion 接口这样的通用协议所以任何满足协议的本地部署模型或者云端 API 都能接入。这一层的核心封装工作是 prompt 管理和输出解析——模型经常会在代码块之外夹带解释性文字也偶尔会给出不完整的代码片段Runtime 层需要把它们剥离、校验、规范化再交给下一层。第二层是Compilation Core。它负责把 agent 提交的程序从文本变成可执行的东西。如果 agent 提交的是 TIR DSL 描述就走 TIR - schedule - codegen - 目标代码这条路径如果 agent 直接提交 CUDA/HIP 源码harness 也会支持但会额外做一层静态检查。Compilation Core 里面挂的是经过我们实测验证的工具链CUDA 后端用 nvcc ptxasHIP 后端用 hipcc统一在底下封装了一个构建环境管理器管理 include 路径、架构参数sm_86、sm_90 这类、编译优化选项比如是否开 fast math、maxrregcount 设多少。第三层是Evaluation Layer也是我认为整个 harness 最核心的部分。它负责把编译出来的 kernel 跑起来做三件事第一数值正确性校验拿 kernel 输出和参考实现一般是 torch 或 numpy 算出来的结果做逐元素对比产出 max abs error、mean abs error、mismatch ratio 这些指标第二性能测量包含 warmup 次数、有效计时次数、吞吐量计算第三性能归因把 profiling 数据PTXAS verbose 输出、CUDA event 时间线、shared memory 利用率提炼成几条可读的诊断信息。2.2 反馈回路是设计核心不是附属品我在第一版里犯过一个错误把 Evaluation Layer 的产出直接以文本形式拼进下一轮 prompt。结果 agent 经常被冗余信息淹没比如 200 行的 ptxas 警告、50 个 profiling 计数器、再加上编译日志模型根本分不清什么才是需要修的问题。后面我做了大改把反馈严格格式化为一个固定结构并且要求只要有一条链路失败后面链路的字段就置空让 agent 的注意力不会被已经失败的东西吸引走。实际运行一轮后的反馈记录长这样ITERATION 3 / TASK softmax_2d COMPILE_STATUS : PASS RUNTIME_STATUS : PASS NUMERICAL_STATUS : FAIL MAX_ABS_ERROR : 2.3e-3 MEAN_ABS_ERROR : 8.1e-5 MISMATCH_RATIO : 0.18 GFLOPS : 14.2 BASELINE_GFLOPS : 8.7 SPEEDUP : 1.63 WARNINGS : [reduction loop uses uncoalesced access pattern on dim 1]这个格式在 prompt 里的占用不大但信息密度非常高。agent 看到 NUMERICAL_STATUS 是 FAIL、MISMATCH_RATIO 在 0.18立刻知道问题是部分元素数值不对看到 WARNINGS 里的未合并访问提示会去调整循环结构而不是盲目改 tile 大小。这就是反馈给 agent 看和反馈给人看的本质差别人要的是能够定位问题的日志agent 要的是能够引导下一次生成的最小充分指令集。2.3 为什么选择可插拔架构而不做一个 All-in-One 编译器其实最开始我也犹豫过要不要干脆把 TIR 编译器、评测器、前端 API 打包成一个 Docker 镜像用户拉下来直接跑这样确实省事但会失去灵活性。GPU 编程生态的分裂程度非常高有人用 Ampere有人用 Hopper还有人用 AMD 的 CDNA有人就想要 CUDA有人必须兼容 HIP甚至不同团队的编译选项习惯都完全不一样。如果 harness 把所有东西写死那它就只能服务我一个人。所以最终我定了一个原则核心流程统一边缘策略开放。编译参数、评测次数、数值容差、模型接入方式、反馈格式全部开放为配置项通过一个 YAML 配置文件控制。下面是一个完整的任务定义文件实例也是我第一次跑通整个闭环时用的配置task_name: softmax_2d description: Row-wise softmax on 2D tensor. 请生成一个 CUDA kernel输入 shape 由 runtime 决定。 problem_shape: rows: 8192 cols: 512 dtype: float32 reference: torch.softmax(input, dim-1) compile: target: cuda arch: sm_86 maxrregcount: 128 fast_math: false eval: atol: 1e-4 rtol: 1e-5 warmup_iters: 10 timed_iters: 50 metric: gflops agent: max_iterations: 8 temperature: 0.2 feedback_schema: structured_v1这套配置的每一行背后都有一个具体的设计原因。atol: 1e-4, rtol: 1e-5是我们实测后定下来的一组保守容差既能容忍 float32 累加本身的舍入误差又能识别出真正的算法错误比如漏了 max 减法导致的上溢。warmup_iters: 10是为了让 GPU 频率和显存分配稳定下来否则第一个测量点通常会偏高或偏低。temperature: 0.2是代码生成场景的推荐值太低模型容易走重复路径太高又会随机引入不稳定的生成内容0.2 是我试下来正确率和探索性平衡得最好的点。3. 核心实现与实操流程3.1 环境准备从空机器到第一次跑通TIRx Harness 的依赖相对克制Python 3.11 及以上、CUDA Toolkit 12.x或 ROCm 5.7 以上的机器、LLVM 后端用来做 TIR 的底层调度与目标代码生成、PyTorch 2.x作为参考实现提供方。GPU 端至少需要一块支持 CUDA 的卡显存 8GB 以上比较舒适因为测试 shape 一般都挑得比较大避免 kernel 太快跑完导致计时误差过大。克隆项目并安装的步骤很简单git clone https://github.com/example/tirx-harness.git cd tirx-harness conda create -n tirx python3.11 -y conda activate tirx pip install -e . --extra-index-url https://download.pytorch.org/whl/cu121注意CUDA 版本和 PyTorch wheel 的 cu121 后缀必须匹配你本机的驱动版本不匹配的话 import torch 时会直接报 libcudart 相关的错误。如果公司机器上已经装了很多 CUDA 版本建议先把CUDA_HOME显式指向你打算用的那个 toolkit再重新激活 conda 环境避免环境变量串味。安装完成后第一件事不是急着接模型而是先跑一次内置的 smoke testtirx-harness run --task tasks/softmax.yaml --kernel examples/softmax_naive.cu这条命令用一个人工写好的 naive kernel 验证整条流水线通了没有。如果这条能跑通说明编译、运行、评测三个环节都没有问题接着再去接 agent 才不会出现模型生成半天结果是 harness 自己坏了这种让人抓狂的状况。3.2 定义任务规格把算子需求转换成 machine-readable 的形式这一步是整个流程的起点也是最容易被低估的环节。直接给 agent 一句自然语言帮我写一个高效 softmax它大概率会生成一个看起来正确但结构随意的 kernel因为你把高效的定义留给了模型去猜。TIRx Harness 的做法是把需求拆成机器可读的任务规格其中最关键的两个字段是reference和problem_shape。reference字段定义了数值正确性的标准。我们一般用 PyTorch 里的算子作为参考比如torch.softmax(input, dim-1)评测时 harness 会用同样的随机种子生成输入张量分别跑参考实现和被测 kernel然后做逐元素对比。problem_shape字段则定义了评测时的实际工作量。这里有个小细节任务规格里写的是rows: 8192, cols: 512实际评测时 harness 不会只跑这一个 shape它会在你指定的范围内随机变体比如 rows 取 4096~16384cols 取 256~1024防止 agent 针对单个 shape 做硬编码优化。另一个容易被忽略的字段是description。它虽然看起来是给模型看的自然语言但我建议写清楚约束条件比如不允许使用 cuDNN 或任何第三方库调用kernel 必须由你直接生成优先考虑共享内存复用。这些约束不写进去模型就会走捷径生成一堆cudnnSoftmaxForward的调用那评测就完全失去意义了。3.3 跑起第一个 Agent 循环八轮迭代里发生了什么有了任务规格就可以接 agent 了。TIRx Harness 提供了一个很小的 Python API 来驱动整个循环核心代码可以浓缩成下面这样from tirx_harness import HarnessRunner, TaskSpec from tirx_harness.agent import OpenAIClient runner HarnessRunner(harness.yaml) task TaskSpec.from_yaml(tasks/softmax_2d.yaml) agent OpenAIClient( modelyour-model-endpoint, temperature0.2, max_tokens4096, ) state [] for iteration in range(task.agent.max_iterations): prompt build_prompt(task, state) response agent.chat(prompt) kernel_source extract_code_block(response) record runner.evaluate(kernel_source, task) state.append(record) print(f[iter {iteration1}] status{record.status} speedup{record.speedup:.2f}) if record.numerically_ok and record.speedup 1.2: print(converged at iteration, iteration 1) break我第一次跑这个循环的时候用了最简单的一个任务算一个二维 row-wise softmax。迭代过程很有意思。第一轮 agent 给出的 kernel 是标准的 two-pass 实现先扫一遍求每行的 max 和 sum再扫一遍做除法。编译通过、数值也正确但速度只有 baseline 的 0.9 倍因为两次遍历同一块数据显存带宽被浪费了。第二轮agent 看到了速度偏慢的反馈改成了 fused 写法用两层循环在单个 thread 内先求 max 再求 sum。这一次编译和数值都通过了速度提到了 baseline 的 1.3 倍左右但 harness 在 WARNINGS 字段里给出了shared memory 使用率偏低、bank conflict 偏高的诊断。第三轮 agent 据此引入了 shared memory tile 的方案把每个 block 处理多条 row同时对 shared memory 的写入做了 padding 来避免 bank conflict。这一版把速度推到了 baseline 的 2.1 倍。最终它停在了第五轮——不是因为它发不出更好的代码了而是 harness 判定speedup 1.2的目标已经达成提前收敛了。整个过程大概用了不到十分钟。对比一下人工做同样的事先读代码再改代码再编译再拿 profiling 工具跑一遍没有半小时下不来。这就是 Agentic GPU Programming 在实际工作流里的价值体现。3.4 性能测量与回归数字稳定比数字大更重要性能测量这块我吃了很多亏也是在开发过程中反复修改最多次的部分。GPU 上的性能测量最大的陷阱是假阳性——你测出来 3 倍加速其实是上一轮 kernel 还在跑计时没有对齐或者 GPU 核心频率因为温度墙被压低了baseline 跑得比平时慢。为了把这些噪声按下去harness 的评测协议做了几个硬性约束。首先每次评测前必须做一次预热 清场跑 10 次目标 kernelwarmup让显存分配器、L2 cache 状态、GPU 频率都稳定下来然后再进入正式计时阶段。正式计时跑 50 次收集的数据取中位数而不是平均值。为什么取中位数因为平均对异常值敏感偶尔一次时钟中断、一次上下文切换就会把平均值拉高 20% 甚至更多中位数能抵御这种离群点在性能对比场景里比平均值可靠得多。其次baseline 的测量必须和被测 kernel 使用完全相同的协议。我在项目里专门写了一个 baseline registry把每个算子的参考 kernel 预先编译好、缓存起来每次评测都用同一份 baseline 记录做对比而不是临时再跑。这样加速比这个数字在多次评测之间是可比较的不会因为 baseline 本身抖动影响结论。最后所有评测记录都会写进一个 JSONL 日志文件每条记录包含 kernel 源码的 SHA256 哈希、编译选项、评测时间、各项指标。这个设计让我在做回归验证时非常省心任何一次改动只要把新的评测结果和旧记录做 diff就能立刻发现是变快了还是变慢了变在哪一轮迭代。之前这种可追溯性是完全没有的——代码改了、性能变了但说不清是哪个改动引起的。4. 实操中踩过的坑与排查实录4.1 生成的 kernel 数值对不上tol 怎么调才不算误杀数值校验是我在项目早期最容易翻车的地方。第一次跑通闭环时我用的容差是atol1e-6, rtol1e-6结果 agent 生成的几乎所有 kernel 都被判为 FAIL。原因很简单float32 在 512 维的 reduction 上本身累加顺序不同就会带来小数点后 5~6 位的误差torch.softmax内部的实现和 CUDA kernel 的归约顺序不可能完全一致所以 1e-6 这种精度要求根本不现实。后来我把容差调成了atol1e-4, rtol1e-5情况立刻改观。但这组数字也不是拍脑袋定的我做了一组基线实验拿一个已知正确但写法不同的 kernel比如 two-pass softmax和torch.softmax对比最大误差发现不同 shape 下误差在 2e-5 到 1e-4 之间波动。于是我把 atol 定在了 1e-4 附近留一点裕量同时又足够敏感能抓住真正的错误。所以我的建议是不要照抄任何项目的数值容差在自己的任务形状上跑一个已知正确的 kernel统计它相对参考实现的误差分布再把你自己的容差设定在误差分布上限的 2~3 倍。这个做法比盲目调参可靠得多。另外fast_math: false这个编译选项必须保持默认关闭因为 fast math 会启用近似数学函数虽然能带来可观的性能提升但会把误差放大一到两个数量级直接让数值校验失去意义。4.2 循环不收敛问题出在反馈太唠开发过程中最耗时间的坑是 agent 在同样的问题上反复打转。有一次让 agent 优化一个 reduction 类算子它连着四轮都在改 block 大小和 grid 大小数值始终正确性能却一直没突破。我把那几轮 prompt 翻出来复盘发现反馈文本里塞了太多无关信息包括一段完整的 ptxas 警告、一列 profiler 计数器、还有一行建议你可以尝试以下方法的模型参考建议。问题在于agent 面对这种长文本反馈时会把注意力分散到所有地方最终选择一条最安全的路径——改 block 大小因为这是成本最低、看起来最合理的操作。但它没有意识到问题真正出在 memory access pattern 上。这个例子让我彻底明白了给 agent 的反馈必须瘦身。一条消息里只能有一个最需要解决的问题最多两个次要问题而且每个问题都要给出具体的修改方向。TIRx Harness 的 structured_v1 反馈格式就是这么来的——它把数值问题、性能问题、编译问题拆开只把当前最严重的那一环显示在摘要里其余信息折叠到可展开的 detail 字段。实操心得如果你在跑多轮 agent 迭代发现它连续 2 轮都在同一个维度上做无关紧要的改动多半是反馈信息的引导力不够。试着把反馈压缩到三条以内的核心警告动手优化之前先想清楚你是想让 agent 收敛还是想让 agent 探索收敛需要强引导探索需要弱约束两者不能混在一个阶段。4.3 性能数字忽高忽低GPU 测量的两大隐形杀手性能测试不稳定是我跟很多使用者交流时被问得最多的问题。有人说同一个 kernel 上午测 1.8 倍、下午测 1.3 倍怀疑是模型生成不稳定。其实大部分时候这个锅不该让模型背而是测量方法论的问题。第一个杀手是GPU 频率动态变化。消费级显卡和部分数据中心显卡频率会随负载和温度自动浮动。如果你的测试脚本没有足够长的 warmup或者两次评测之间间隔太长导致 GPU 进入了低功耗空闲态那么每次评测时内核实际运行的频率都不一样性能数字自然飘忽。TIRx Harness 的做法是在评测前主动跑一段固定负载的热身任务让 GPU 频率爬上去并稳定住然后再插桩计时同时要求 warmup_iters 不低于 10 次否则评测器会直接跳过该轮并提示你增加预热次数。第二个杀手是L2 cache 残留。如果你连续评测多个相同 shape 的 kernel前一个 kernel 写出的数据可能还残留在 L2 里后一个 kernel 的首次访问会比正常情况下快很多。对 benchmark 来说这个假快会严重干扰判断。我们的评测器在每次正式计时前会向一块与评测数据同尺寸的冲刷缓存 buffer 写入一次脏数据确保 L2 里没有上一个 kernel 的残留。你如果自己写评测脚本这个细节最容易漏但也最容易导致每周的性能报告互相不可比。4.4 重编译太慢整个循环的最大拖累项真要让 Agentic GPU Programming 在工程里落地真正杀死体验的不是模型生成质量而是重编译延迟。一次 nvcc 编译一个小 kernel 通常只要几秒钟但加上 ptxas 优化、链接、host 代码生成如果每次迭代都是全新编译十轮迭代下来光编译就要好几分钟。对 agent 循环来说这段时间是纯浪费因为反馈回路拖得越长agent 上下文里保留的注意力就越稀薄。我做了两层优化。第一层是基于哈希的编译缓存对 kernel 源码、编译选项、目标架构、include 路径取 SHA256 哈希作为编译产物缓存的 key。如果一次迭代生成的代码和之前的尝试哈希相同直接复用已编译的 .so 文件跳过整个 nvcc 调用。这在 agent 反复生成类似代码时尤其有效经常能省掉 3~4 次完全重复的编译。第二层是增量式重编译不重新构建 host 端的调度代码只重新编译 device kernel然后通过 CUDA 的运行时加载机制类似 cuModuleLoad 的流程把新的 kernel 函数注入到已经运行的程序里。这一步把单轮编译时间从 5 秒左右压到了 1 秒以内。代价是实现复杂一些需要自己管理 module 生命周期和 kernel 函数句柄。但对于想让 agent 在十分钟内完成二十次迭代的场景这个复杂度是值得的。4.5 工具链兼容性的几个细节跨 GPU 厂商和跨架构的兼容问题是 harness 这种项目必须面对的现实。CUDA 和 HIP 两套生态表面上 API 非常接近但底层的 ptxas 和 amdgen 的优化行为差异很大同一个 TIR schedule在 NVIDIA 卡上效果很好到了 AMD 卡上可能因为 wavefront 大小不同、shared memory 组织方式不同而性能崩盘。TIRx Harness 目前的做法是把架构参数全部显式化不猜、不自动探测让你在任务配置里写清楚arch: sm_90还是arch: gfx942。这样虽然需要使用者多写一行配置但避免了同一份任务规格在不同机器上行为完全不同的混乱。还有一个容易踩的细节是maxrregcount。这个值限制单个 kernel 使用的寄存器数量直接影响占用率。默认不设置时ptxas 会为了性能尽量多用寄存器可能导致每个 SM 上驻留的线程块数偏少。如果 agent 生成的 kernel 里有大量寄存器压力性能反而下降。我把 maxrregcount 设成 128 作为默认值不是因为它最优而是因为它是一个能让绝大多数 kernel 达到合理占用率的中间值。实测下来对 512 线程的 block 配置128 寄存器基本能把 occupancy 保持在 50% 以上。如果你的 kernel 特别复杂可以把值放宽但这属于 per-kernel 的调优不适合放在全局默认里。5. 项目落地后的几个反思与后续方向5.1 三个最值得分享的设计教训第一个教训是反馈格式比模型能力更影响收敛速度。我做过一个对照实验同一个模型、同一个任务一组用纯文本反馈性能不太好建议优化内存访问另一组用结构化反馈包含 NUMERICAL_STATUS、WARNINGS 字段。结果结构化反馈那组平均 4 轮收敛纯文本反馈那组 8 轮都没收敛。这不是模型笨而是模糊的反馈给了它太多自由发挥空间。给 agent 的指令里明确性永远排在创造性前面。第二个教训是评测的可复现性比性能本身更重要。我早期只关心这轮 kernel 快不快没有记录每次评测的完整环境信息结果后来想回溯是哪一次改动让性能下降的根本找不到原始记录。现在 TIRx Harness 里每条评测记录都带上了 kernel 哈希、编译选项、GPU 频率区间、L2 冲刷状态、时间戳这才让整个 agent 循环变成可审计的工程过程而不是一个靠运气的黑盒。第三个教训是不要试图把 Agent 循环变成全自动独角戏。最理想的工作流是人制定任务规格、设好约束、圈定搜素空间然后让 agent 在 harness 的保护下快速迭代但关键决策比如数值容差、是否开启 fast math、目标架构选哪个应该始终由人控制。我试过把一切都交给 agent 自主决定结果它为了速度悄悄把 fast_math 打开数值误差飙到 1e-2 还自以为成功。人机边界划在哪里这本身就是这个领域最值得研究的问题。5.2 后续想扩展的几个方向当前版本已经有了一个完全可用的闭环但距离我理想中的 Agentic GPU Programming 基础设施还有不少路要走。接下来我最想做的三个方向第一引入多 agent 协作让一个 agent 负责生成 kernel另一个 agent 专门分析 profiling 输出并给出修改建议两个 agent 共享同一个评测协议第二把 benchmark corpus 从单一算子扩展到覆盖访存密集型、计算密集型、reduction 密集型三大类各二十个左右的典型算子建立一套公开的评测排行榜第三和 CI/CD 集成让每次 PR 触发一次自动的 agent 优化流程把AI 辅助 GPU 优化变成团队日常开发的一部分而不是偶尔跑一次的实验玩具。我个人在实际使用中最大的感受是这类项目真正的价值不在于让 AI 替代工程师写代码而在于把优化一个 GPU kernel这件事从依赖个人经验的手艺活变成一套可以被记录、被复现、被持续改进的工程化流程。TIRx Harness 作为开放项目把 Agentic GPU Programming 这个方向的基建往前推了一步也希望更多人来把各自的编译器适配、评测协议和典型算子案例加进来。毕竟一个 harness 的价值永远取决于它服务了多少不同的工作负载而 GPU 编程世界里的工作负载还远远没有被穷尽。