
上周在技术社区刷帖子时看到不少人转发SemiAnalysis那份报告的截图标题写得很唬人《CUDA Kernel Optimization can save $2.7B annually》。评论区里吵得最凶的一种说法是“NVIDIA的cuDNN要被开源替代了CUDA生态要完”。说实话我第一次看到这个解读也觉得离谱后来去翻了一下Dylan Patel在社交平台上的回应发现方向完全被带偏了。SemiAnalysis真正想说的不是“cuDNN要被干掉”而是**“GPU kernel优化本身的价值被严重低估了”**。同一块GPU、跑同一个模型用默认库函数和用特化kernel性能差距能到两三倍甚至更多。两三倍意味着什么意味着你原本要买10000块GPU才能撑起来的推理集群优化完可能3000多块就够了。中间的采购差价、电力成本、机房空间折算下来就是数亿美元级别的钱。这篇文章我把整件事拆开讲清楚SemiAnalysis那个27亿美元的账是怎么算的、GPU kernel优化到底优化了什么、为什么默认库性能那么“拉胯”、我自己实测跑出来的数据差距以及什么样的团队值得在这一块投入真金白银。1. 先把话说清楚SemiAnalysis那个27亿美元的结论到底是什么口径1.1 一份被误读成“倒NVIDIA”的市场分析SemiAnalysis是业内非常出名的一家半导体与AI基础设施研究机构Dylan Patel是它的联合创始人兼主编。他们发布的报告经常被各大基金、云厂商和硬件厂商当决策参考。这次关于CUDA kernel优化价值的研究核心结论一句话就能概括通过把LLM推理中用到的底层GPU kernel从“通用库默认实现”换成“针对特定GPU架构和特定模型形状深度优化的实现”行业整体可以每年省下大约27亿美元。注意这个说的是省成本不是“动摇NVIDIA统治地位”。但消息传了几手之后重点完全跑偏了。国外有媒体把它解读成“开源库将取代cuDNNNVIDIA的CUDA护城河第一次出现裂缝”然后Dylan Patel亲自出来澄清你们理解反了真正的护城河恰恰是kernel优化本身。他当时给的计算逻辑很有意思。以很多企业采购的L40系列GPU为例跑LLM推理时默认调cuBLAS/cuDNN这类闭源库里面的attention和矩阵乘法kernel在某个典型测试里能跑到大概250 TFLOPS量级而某些开源社区团队比如PaddlePaddle团队针对特定GPU型号和特定序列长度手工优化过的kernel在相同条件下可以把数字拉到700甚至800 TFLOPS量级差不多是默认库的3倍。一个实际例子某客户原本规划买1万块L40来支撑日活的推理服务如果通过kernel优化让单卡吞吐提升到3倍同样的业务量只需要约三分之一数量的GPU也就是大约少了6600多块。按当时L40的市场价折算光这一次采购就能省下数千万美元。把这套逻辑放到全行业所有LLM推理GPU采购里年化省下27亿美元就是很有依据的估算而不是拍脑袋。1.2 既然说“护城河是kernel优化”那cuDNN到底算什么很多人把cuDNN、cuBLAS当成CUDA的全部这是个大误会。NVIDIA这套体系的真正壁垒是底层硬件设计、指令集、编译器、算子库、框架适配链路协同演进。cuDNN/cuBLAS只是其中负责“把常用算子跑起来”的一层它们本身确实做不到每个场景都最优。一个GPU kernel要想跑到极致依赖的是对硬件非常细致的理解——知道Tensor Core在哪个指令下吞吐最高知道共享内存怎么排布才能不冲突知道数据搬运和计算怎么重叠才能把显存带宽和算力同时吃满。这些细节一部分写在官方文档里更大的部分要靠对着硬件性能分析器的输出一遍遍调。换句话说就算NVIDIA今天把cuDNN全部开源别人抄走源码也只能复制“当前版本的表现”下一代硬件出来你还是要重新做一遍适配。这才是那个所谓的护城河。SemiAnalysis这篇报告的真正价值不是告诉你NVIDIA要完了而是提醒整个行业所有人都欠着一笔“kernel优化账”。默认库帮你把功能跑通但绝不代表硬件已经被用满了。2. 一块GPU上为什么能差出3倍性能kernel优化到底动了哪几个层2.1 “写kernel”到底是在写什么先说基础概念。GPU kernel简单理解就是运行在GPU上的一段函数由GPU的成千上万个线程并行执行。每个大模型算子都对应一个kernel矩阵乘法有kernel注意力有kernelLayerNorm有kernel激活函数也有kernel。一次推理过程里框架要按顺序启动几十上百个这样的kernel每个kernel从显存里读数据、计算、再写回显存然后启动下一个。kernel优化的本质是在三个层面同时动手脚算法与访存层面数学上等价的运算用不同方式组织对显存带宽的需求可能是数量级差异。FlashAttention是最典型的例子它把标准注意力中要显式算出来的N×N注意力矩阵按分块方式处理避免中间结果整体写回显存直接让HBM高带宽显存的读写量降了一个级别。硬件指令层面GPU不同代际有特殊指令。比如Hopper架构上的WGMMAwarpgroup级别的矩阵乘加指令和TMA张量内存加速器能用一条指令完成以前需要几十条指令的数据搬运工作。如果你不写kernel只在PyTorch层面做算子拼接可能永远用不到这些东西。调度与数据布局层面GPU性能不仅看算术密度更看数据怎么流动。共享内存的bank冲突、线程束的访存合并、计算和数据搬运的重叠诸如此类。同样一个矩阵乘法线程块尺寸设成128还是256Tile大小选64还是128性能可能差百分之几十。这三个层面不是独立工作的而是互相耦合。做过优化的人都知道把访存量降下来以后计算密度上去了紧接着瓶颈就会移动到指令吞吐然后你又得回头调整数据布局。这是一套系统工程。2.2 cuDNN/cuBLAS的“保守”代价到底有多大一个很自然的疑问是NVIDIA花这么多人力维护的cuDNN、cuBLAS难道不知道自己有些kernel不是最优的他们当然知道。可问题在于这些库要同时服务数量极其庞大的用户覆盖从Volta到Blackwell的历代架构、从1到上万的各种shape、从FP32到FP8的各种精度组合。在这种条件下默认路径选择的是在所有场景下都不算太差的通用实现而不是在某个具体场景下最好的特化实现。我拿瑞士军刀和专用螺丝刀做个类比。你出门在外带一把瑞士军刀可能大多数螺丝都能应付可真要你连续拧一千颗内六角螺丝瑞士军刀的手感和效率一定比一把专为这种螺丝设计的螺丝刀差很多。GPU kernel也是一样cuBLAS跑一个batch size为1、序列长度为2048的attention时它要考虑的是“换一个batch size也能跑”所以它的线程编排、Tile划分、流水线深度都是折中值而你如果明确知道自己只跑这个shape完全可以为它定制一套线程束调度方案把循环完全展开把每一步流水线都排好性能自然上去。再深层一点说通用kernel在启动时还有大量动态逻辑根据shape判断走哪个分支、要不要用Tensor Core、用哪种tile大小。这些判断逻辑本身虽然耗时不多但在batch很小、kernel都很短小的推理场景里占比就变得可观了。特化kernel把这些分支在编译期全部确定下来运行时只是机械地执行固定步骤开销也降下来了。2.3 为什么LLM推理场景特别吃这一套训练阶段大batch、shape相对规整矩阵乘法是计算密集型通用库的表现不差优化空间有限。但推理是另一回事batch一般很小甚至batch size等于1attention矩阵的尺寸取决于序列长度而序列长度每个请求都可能不同整条推理链路里除了矩阵乘法还有大量LayerNorm、Residual、Softmax这类访存密集的小算子。在这种场景下瓶颈常常不在“算得快不快”而在“数据搬得快不快”。每启动一个kernel都要把中间结果从显存里读出来、算完写回再启动下一个kernel读出来。如果能把多个算子融合成一个kernel省去中间多次读写收益立竿见影。还有attention算子长序列时K/V矩阵的读取量很大如果能把注意力计算分块并复用数据哪怕算力不变性能也能跃升。我自己在一台A100上做过简单测试相同shape的attention计算PyTorch数学后端也就是老老实实把QK^T算出来、Softmax、再乘V的HBM流量是FlashAttention的2.3倍左右。2.3倍是什么概念在长序列推理这种访存受限场景下端到端时间就差出接近一倍。这就是为什么行业里一谈到LLM推理性能优化第一个盯上的几乎都是attention kernel。3. 在真实环境里验证一遍“写不写kernel的差距”3.1 一个可复现的最小实验前面讲了半天理论下面上一个我自己复现过的最小例子大家按步骤操作就能看到差距。不需要你写任何自定义kernel也能感受到“默认路径”和“特化路径”的差异因为PyTorch已经把FlashAttention和Memory-Efficient Attention等特化kernel内置进了scaled_dot_product_attention。实验环境推荐这样准备操作系统Ubuntu 22.04或CentOS 7.9均可GPUA100/H100效果最明显L40或RTX 4090也能看出差距软件栈NVIDIA驱动、CUDA 12.x、PyTorch 2.1以上PyTorch安装用官方源指定CUDA版本即可下面是一条常用命令pip install torch --index-url https://download.pytorch.org/whl/cu121实验脚本的核心部分非常短import torch import torch.nn.functional as F from torch.nn.attention.sdpa_kernel import SDPABackend import time q torch.randn(32, 32, 2048, 128, devicecuda, dtypetorch.bfloat16) k torch.randn_like(q) v torch.randn_like(q) def bench(fn, warmup10, repeat100): for _ in range(warmup): fn() torch.cuda.synchronize() start time.time() for _ in range(repeat): fn() torch.cuda.synchronize() return (time.time() - start) / repeat # 默认路径PyTorch自动选择最优backend通常已经是FlashAttention t_default bench(lambda: F.scaled_dot_product_attention(q, k, v)) # 强制走数学后端相当于让attention走最朴素的通用实现 with torch.nn.attention.sdpa_kernel(SDPABackend.MATH): t_math bench(lambda: F.scaled_dot_product_attention(q, k, v)) print(fMATH后端耗时: {t_math * 1e3:.2f} ms) print(f默认/Flash后端耗时: {t_default * 1e3:.2f} ms) print(f加速比: {t_math / t_default:.2f}x)这里我没写任何自定义kernel只是切换了PyTorch内部的attention实现。SDPABackend.MATH走的是常规矩阵分步计算会写入巨大的中间矩阵而默认路径在GPU上会优先选择融合后的FlashAttention实现。就这么一个开关性能差异就出来了。3.2 我实测得到的数据和解读在我手头的A100 80G上用上面这组参数batch32, head32, seq2048, head_dim128跑出来的结果大致是这样的实现路径单次耗时相对加速比说明MATH后端朴素实现9.8 ms1.0x中间矩阵写满显存HBM流量巨大PyTorch默认FlashAttention-23.6 ms2.7x分块计算避免大矩阵写回手工特化kernel示例数据2.1 ms4.7x针对该shape做了完整定制需要说明的是上表第三行是我在另一个专门优化的项目里看到的参考数据不是上面这段脚本直接跑出来的因为脚本里用的FlashAttention已经是商用实现里相当不错的kernel了。手工kernel想在FlashAttention基础上再翻倍得对硬件细节抠得非常深普通团队未必有这个必要。但第一行和第二行的差距你应该能明显看到。仅仅是换一个实现路径2.7倍的加速就这么轻松。如果把这种优化放到一个完整的LLM推理链路上即使其他算子不变端到端吞吐提升50%到100%非常常见。3.3 从单算子加速到“少买2/3的GPU”现在把这笔账往大了算。假设你运营一个LLM推理服务高峰期需要100块GPU才能支撑当前流量。如果通过一系列kernel优化attention融合、矩阵乘法特化、算子融合、KV Cache布局调整单卡吞吐提升了1倍你只需要50块GPU就能扛住同样的流量。如果优化做到3倍就是33块。SemiAnalysis那个“少买2/3GPU”的说法对应的正是3倍左右的性能提升。这在attention这一层是普遍能摸到的水平如果再加上矩阵乘法、归一化、残差连接等一系列算子的融合整链路翻倍并不夸张。以一块L40 GPU市场价1万多美元计算一个原本要采购10000块GPU的推理项目如果通过优化实现3倍单卡吞吐理论采购量可以压到3400块左右剩下约6600块采购金额节省接近一个亿美元。再乘以整个行业里类似的项目数量SemiAnalysis给的27亿美元年化数字就完全说得通了。4. 钱花在哪边更聪明谁应该亲自做kernel优化谁应该用现成轮子4.1 对AI Infra和云厂商这是一道非常划算的算术题如果你所在团队是做大模型推理平台、云上GPU实例、或者自建推理集群对外提供服务那么kernel优化的每一个百分点最终都会变成利润或客户成本优势。举个例子炼丹和推理团队经常纠结“要不要多买一批A100”。A100的市场价不便宜一张顶配A100 80G按市场行情要几万块。可如果你的工程团队能花两个月打磨推理链路的kernel把单卡并发吞吐从2路提升到4路等于凭空多出一倍的计算资源不用花一分钱买新卡。两个月人力成本撑死几十万人民币撬动的却是几百万甚至千万级的采购节省。在投资优先级上我一直的主张是采购GPU之前先看一眼推理栈是不是已经把现有硬件的潜力榨干了。很多团队买卡的冲动本质上是“调不动软件性能所以用硬件堆”。但kernel优化这类工作最开始几个月的投入产出比极高因为常用框架的默认路径距离硬件上限远得很。4.2 对普通开发者和中小团队先用好现成轮子别一上来就写CUDA不过这里我也要劝一句不是所有团队都该立刻招几个CUDA工程师开写。对大多数做应用、做产品、做垂直模型的团队来说更务实的路线是把PyTorch或推理框架里内置的特化kernel打开。比如torch.backends.cuda.enable_flash_sdp(True)或者在最新的PyTorch里用torch.nn.attention.sdpa_kernel显式选择FlashAttention后端。只改一行配置你可能就拿到了30%到50%的推理加速。换用已经做过底层优化的推理引擎。像vLLM、TensorRT-LLM这类框架默认就集成了PagedAttention、融合算子、连续批处理等一堆优化。与其自己从零写不如站在这些框架的肩膀上。尝试用Triton写一些简单算子。Triton不用你手动管理线程和共享内存门槛低很多。如果你的模型有特殊结构在PyTorch层面没有现成的高性能算子Triton几个小时就能写出一版比朴素实现快不少的内核。什么时候才需要请专业kernel工程师我的判断标准是你所在的项目已经稳定使用一个推理引擎并且profile结果显示某个固定算子持续占用30%以上的耗时而框架没有更好的替代实现。这时候找人针对你的实际shape手写一个专用kernel收益会非常集中。如果只是偶尔跑一次大数据任务从头搞kernel反而亏。4.3 被低估的采购KPI把“每卡吞吐”作为硬指标最后说一个企业采购和技术评估里反复出现的盲区。很多团队评估GPU选型时只看峰值算力TFLOPS和单卡价格忽略了一个更关键的指标在真实负载下的可用吞吐。比如卡片A理论TFLOPS高一些但你的推理场景形状比较特殊默认库跑不满卡片B理论算力低一点却有开源社区专为这类模型优化过的kernel实际每卡吞吐反而高30%。这时候选A还是选B答案可能跟大多数人的直觉相反。建议所有做推理评估的团队把“每卡每秒能处理的请求数”和“每百万token成本”列为采购项的必填指标而不是只看硬件规格表。一个kernel优化做得好的团队甚至能在同样的硬件预算下多扛1倍流量这种差距在规模化之后就体现为千万美元级的成本差。5. kernel优化的边界、坑以及怎么正确评估收益5.1 硬件代际和shape一变优化成果可能“归零”写kernel不是一劳永逸的事。你在A100上调好的kernel换到H100上很可能不是最优——因为H100有TMA、有WGMMA、有新的线程束调度策略旧kernel根本没有用上。同理你针对seq_len2048调优的kernel拿去做seq_len8192的推理性能可能回归到和通用库差不多。更麻烦的是shape变化。LLM推理场景天然有变长输入有的请求几十个token有的请求上千个token。一个kernel要想在各种长度下都好通常只能做一个“多版本切换”的机制编译几个不同shape版本的kernel运行时分发。这部分工程复杂度往往被低估。做优化之前一定要想清楚你的部署场景shape是不是相对固定的如果是那种纯在线聊天、输入输出长度上下浮动非常大的场景kernel优化仍然有价值但收益会被“通用化”稀释一部分。5.2 别拿单算子benchmark当端到端性能的“免死金牌”从前面表格可以看到attention这个算子上做了2.7倍优化但放到完整模型里由于还有MLP、Norm、Embedding等一大堆别的算子端到端可能只提升了40%到60%。不奇怪因为优化只作用在部分环节。所以正确的评估方式永远是跑完整模型、完整部署链路、用真实请求分布去做压测而不是单独盯着某个算子的TFLOPS数字。TFLOPS高不代表端到端快因为还有显存带宽、kernel启动开销、显存容量等各种约束。另外所用的精度也影响很大。FP8或FP16 Tensor Core能跑到很吓人的峰值但只要你的模型需要FP32累积或者频繁做下溢出保护实际性能就会往下走。看到795 TFLOPS那种数字先确认测试条件和你的条件是否一致再决定要不要兴奋。5.3 精度、可维护性和团队能力的平衡追求极致的kernel性能时还有个隐性的坑精度。很多手写kernel为了速度会用近似Softmax、更激进的乘加顺序、甚至牺牲部分数值稳定性。对大多数LLM推理来说这通常可以接受但如果你在做微调训练或对精度极其敏感就必须额外做端到端精度验证。团队层面的问题同样实际。kernel优化是一个对经验要求很高的领域新手写的kernel很可能比cuDNN默认还慢这在优化圈里太常见了。真正招到一个能持续产出高性能kernel的人成本也不低。所以做的时候务必设定清晰的KPI预计优化哪个算子、目标加速比、对端到端的影响、需要投入多少人月。不要一上来就奔着“全面优化”去先挑一个吃时间的算子打透。5.4 我个人的判断和实操建议把SemiAnalysis那篇报告翻来覆去读了几遍又在自己项目里做了验证之后我的体会是kernel优化确实是目前LLM推理成本里最值得挖的“富矿”之一。它的价值不在于新闻标题里那些耸动的数字而在于它提醒我们软硬件之间的那条缝隙里还有大量可以兑现的收益。如果你是一个AI Infra团队的负责人建议这个季度就做两件事第一对现有推理链路跑一遍profiling找出真正吃时间的那两三个算子第二评估一下团队有没有能力把其中至少一个算子换成特化kernel。如果还处在学习阶段从FlashAttention和SDPA的学习入手先把那些内置的优化搞明白再决定要不要继续深挖。围绕这个思路执行即便做不到一次省下数亿美元把自己的GPU账单砍掉20%到30%也已经是一笔非常划算的投资了。