介绍如何利用现代大语言模型,通过可验证的循环流程生成、校验并优化GPU内核。
AI translation, not an official translation. Refer to the original for technical details.
Adapted from @maharshii# 用大语言模型"振动编码"GPU内核 手写GPU内核需要耐心、精力,还会让人抓狂。我一直在用现代大语言模型(Claude Opus 5、GPT 5.6 Sol)来直接生成内核。下面我来谈谈这一过程中的心得。 说实话,编写GPU内核是一项极易验证的任务。 首先,确定你想为哪些操作编写内核。其次,写出第一个版本,确保它能编译通过且没有明显错误。第三,用一个较慢的参考实现来验证正确性。如果结果不匹配,就尝试修复正确性问题。完成之后,对内核的执行时间进行基准测试。后续版本在此基础上不断迭代,持续优化,直到达到屋顶线指标或令你满意为止。 上图将其展示为一个可验证的循环: - 编译检查是一个紧凑的本地循环(B <-> C),甚至在你考虑正确性之前就已进行。 - 正确性检查(D <-> E <-> F)是核心可验证奖励循环。正是这一部分使得内核编写成为适合自动化验证的好问题,因为你有一个可供对比的真值参考实现。 - 优化(G -> H -> 返回D)对每个新版本复用相同的正确性循环,因为一个速度快但结果错误的内核毫无价值,每个版本都必须验证正确性。 - 屋顶线/满意度检查(I)是外层循环,用于决定是继续优化还是停止。 ## 第一个版本 上图仍是较高层次的视角,细节中藏着魔鬼。我们需要确保大语言模型智能体拥有所有必要的上下文,才能开始编写一个质量较好的第一版。 CUDA DSL在这里发挥了作用。Triton、CuTeDSL和Tilelang都很容易上手,均基于Python。与CUDA C++相比,它们的学习曲线较为平缓,但这些DSL中的抽象层可能反而会让我们的智能体更加困惑。我们需要一种方式将这些抽象的上下文传递给智能体。 现代大语言模型已经知道如何编写"良好的"Triton代码,无需任何额外上下文即可很好地处理Triton的抽象。然而,对于像CuTeDSL这样的其他DSL(它比Triton提供了更多控制权),我发现设置一个上下文目录让智能体查找DSL抽象的相关内容会很有帮助。 > 例如,将NVIDIA cutlass仓库克隆到上下文目录中,是一种让智能体在编写CuTeDSL内核时查找布局代数、Copy/GEMM原子、内存层次结构、示例内核等相关抽象的好方法。 根据我的经验,一个质量较好的内核第一版应当能够编译通过且没有明显错误,并能通过我下面将要介绍的正确性测试。 ## 测试、基准测试与性能分析 在为智能体提供足够上下文之后,真正的瓶颈转移到了验证环节。参考实现本身,以及针对它的验证变得越来越重要。我将这一阶段称为正确性测试,或简称为测试。参考实现的速度并不像其意图那样重要。你打算测量和验证什么,你的智能体就会为什么而优化。 通常,当计算不应在低精度下进行时,我会测量最大绝对/相对误差(MAE)、均方误差(MSE/RMSE)以及峰值信噪比(PSNR)。当涉及低精度时,我倾向于测量 PSNR 和余弦相似度(cossim)。 让内核版本实际在 GPU 上运行的方式,取决于 GPU 是本地可用还是通过云端访问。无论如何,我们的智能体应该能够以某种方式访问其输出结果。 我发现以下"阶梯式"方法是组织 N 个测试函数的好方式: 可以像这样调用: 对于基准测试阶梯,你可以做多件事: - 对整体花费时间进行端到端内核执行时间基准测试 - 使用内核内追踪对内核内部各部分进行基准测试,并将结果输出(使用自定义追踪器或 CUPTI) - 将生成的 IR、PTX、SASS 和 CUBIN 转储到 dumps 目录,供智能体逐一查阅 最后一点可以进一步展开。有时,DSL 在降低层级时可能会生成次优的 PTX(最终体现在 SASS 上),而你发现了更好的指令或形状可以替代使用。我们的智能体可以通读 PTX/SASS 文本文件,并直接内联更底层的代码,而不是让 DSL 去处理那些次优的部分。同样,将"可搜索"的 PTX 文档作为上下文传入,在这里非常有帮助。 将一切整合在一起的最后一环是性能分析。如果你的智能体能够访问 NCU(Nsight Compute Systems)CLI,你可以要求它对内核进行性能分析,并作为上述可验证反馈循环的一部分生成报告。 ## 结语 "那么 GPU 内核开发就此终结了吗?" "嗯,是,但其实也不是。" 说"是",是因为布局、索引、抽象以及整体结构等困难部分,在有足够上下文的情况下,基本上可以由智能体来解决。你可以轻松地将 2 到 3 周的工作压缩到 1 到 2 天。说"不是",是因为真正的瓶颈已经从内核本身转移到了验证环节。现在没有一种放之四海而皆准的做法:你的上下文和测试框架越好,整个过程就越快。专业化场景将从中受益更多,而一套完善的测试框架将是你所需要的一切。 最后,与其将智能体视为完全自主的存在,不如将其视为你可以加以引导的超级聪明的助手——在这里,这一点依然至关重要。这正是你对 GPU 和内核的基础理解大显身手的地方。人类的角色(也就是你)在这里仍然不可或缺。 这种感觉苦乐参半,我懂的 :)