前言
在上一篇中,我们聊了前端优化 :它在计算图(算子)层面 做"减法"------算子融合、常量折叠、CSE、DCE、布局变换,回答的是 "算什么、少算什么" 的问题。
但前端优化有一个天然的极限:它只能决定" launching 哪些算子",却决定不了 "每个算子内部跑得有多快" 。一个卷积 kernel 是跑到 10% 的硬件峰值,还是 90% 的硬件峰值,取决于另一层优化------后端优化(Backend Optimization)。
本篇我们就来拆解:AI 编译器是如何在循环层、指令层,把一块硅片的性能榨到极限的。
一、 后端优化的定位:从"算什么"到"怎么算"
先看后端优化在整个编译器流水线中的位置:
#mermaid-svg-CJdbC2I3XKMPP8oh{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-CJdbC2I3XKMPP8oh .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-CJdbC2I3XKMPP8oh .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-CJdbC2I3XKMPP8oh .error-icon{fill:#552222;}#mermaid-svg-CJdbC2I3XKMPP8oh .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-CJdbC2I3XKMPP8oh .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-CJdbC2I3XKMPP8oh .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-CJdbC2I3XKMPP8oh .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-CJdbC2I3XKMPP8oh .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-CJdbC2I3XKMPP8oh .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-CJdbC2I3XKMPP8oh .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-CJdbC2I3XKMPP8oh .marker{fill:#333333;stroke:#333333;}#mermaid-svg-CJdbC2I3XKMPP8oh .marker.cross{stroke:#333333;}#mermaid-svg-CJdbC2I3XKMPP8oh svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-CJdbC2I3XKMPP8oh p{margin:0;}#mermaid-svg-CJdbC2I3XKMPP8oh .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-CJdbC2I3XKMPP8oh .cluster-label text{fill:#333;}#mermaid-svg-CJdbC2I3XKMPP8oh .cluster-label span{color:#333;}#mermaid-svg-CJdbC2I3XKMPP8oh .cluster-label span p{background-color:transparent;}#mermaid-svg-CJdbC2I3XKMPP8oh .label text,#mermaid-svg-CJdbC2I3XKMPP8oh span{fill:#333;color:#333;}#mermaid-svg-CJdbC2I3XKMPP8oh .node rect,#mermaid-svg-CJdbC2I3XKMPP8oh .node circle,#mermaid-svg-CJdbC2I3XKMPP8oh .node ellipse,#mermaid-svg-CJdbC2I3XKMPP8oh .node polygon,#mermaid-svg-CJdbC2I3XKMPP8oh .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-CJdbC2I3XKMPP8oh .rough-node .label text,#mermaid-svg-CJdbC2I3XKMPP8oh .node .label text,#mermaid-svg-CJdbC2I3XKMPP8oh .image-shape .label,#mermaid-svg-CJdbC2I3XKMPP8oh .icon-shape .label{text-anchor:middle;}#mermaid-svg-CJdbC2I3XKMPP8oh .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-CJdbC2I3XKMPP8oh .rough-node .label,#mermaid-svg-CJdbC2I3XKMPP8oh .node .label,#mermaid-svg-CJdbC2I3XKMPP8oh .image-shape .label,#mermaid-svg-CJdbC2I3XKMPP8oh .icon-shape .label{text-align:center;}#mermaid-svg-CJdbC2I3XKMPP8oh .node.clickable{cursor:pointer;}#mermaid-svg-CJdbC2I3XKMPP8oh .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-CJdbC2I3XKMPP8oh .arrowheadPath{fill:#333333;}#mermaid-svg-CJdbC2I3XKMPP8oh .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-CJdbC2I3XKMPP8oh .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-CJdbC2I3XKMPP8oh .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-CJdbC2I3XKMPP8oh .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-CJdbC2I3XKMPP8oh .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-CJdbC2I3XKMPP8oh .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-CJdbC2I3XKMPP8oh .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-CJdbC2I3XKMPP8oh .cluster text{fill:#333;}#mermaid-svg-CJdbC2I3XKMPP8oh .cluster span{color:#333;}#mermaid-svg-CJdbC2I3XKMPP8oh div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-CJdbC2I3XKMPP8oh .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-CJdbC2I3XKMPP8oh rect.text{fill:none;stroke-width:0;}#mermaid-svg-CJdbC2I3XKMPP8oh .icon-shape,#mermaid-svg-CJdbC2I3XKMPP8oh .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-CJdbC2I3XKMPP8oh .icon-shape p,#mermaid-svg-CJdbC2I3XKMPP8oh .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-CJdbC2I3XKMPP8oh .icon-shape .label rect,#mermaid-svg-CJdbC2I3XKMPP8oh .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-CJdbC2I3XKMPP8oh .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-CJdbC2I3XKMPP8oh .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-CJdbC2I3XKMPP8oh :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 用户代码
PyTorch / TensorFlow
前端优化
图级: 融合/折叠/CSE/布局
优化后的计算图 IR
后端优化
循环级/指令级: 切分/向量化/调度
自生成 Kernel
CUDA C++ / PTX / SASS
厂商库调用
cuBLAS / cuDNN / CUTLASS
硬件执行
GPU / CPU / NPU
注意后端面临的两条落地路径,这是理解后端优化的关键:
#mermaid-svg-D7OleMl6YJXwPdBY{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-D7OleMl6YJXwPdBY .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-D7OleMl6YJXwPdBY .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-D7OleMl6YJXwPdBY .error-icon{fill:#552222;}#mermaid-svg-D7OleMl6YJXwPdBY .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-D7OleMl6YJXwPdBY .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-D7OleMl6YJXwPdBY .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-D7OleMl6YJXwPdBY .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-D7OleMl6YJXwPdBY .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-D7OleMl6YJXwPdBY .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-D7OleMl6YJXwPdBY .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-D7OleMl6YJXwPdBY .marker{fill:#333333;stroke:#333333;}#mermaid-svg-D7OleMl6YJXwPdBY .marker.cross{stroke:#333333;}#mermaid-svg-D7OleMl6YJXwPdBY svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-D7OleMl6YJXwPdBY p{margin:0;}#mermaid-svg-D7OleMl6YJXwPdBY .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-D7OleMl6YJXwPdBY .cluster-label text{fill:#333;}#mermaid-svg-D7OleMl6YJXwPdBY .cluster-label span{color:#333;}#mermaid-svg-D7OleMl6YJXwPdBY .cluster-label span p{background-color:transparent;}#mermaid-svg-D7OleMl6YJXwPdBY .label text,#mermaid-svg-D7OleMl6YJXwPdBY span{fill:#333;color:#333;}#mermaid-svg-D7OleMl6YJXwPdBY .node rect,#mermaid-svg-D7OleMl6YJXwPdBY .node circle,#mermaid-svg-D7OleMl6YJXwPdBY .node ellipse,#mermaid-svg-D7OleMl6YJXwPdBY .node polygon,#mermaid-svg-D7OleMl6YJXwPdBY .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-D7OleMl6YJXwPdBY .rough-node .label text,#mermaid-svg-D7OleMl6YJXwPdBY .node .label text,#mermaid-svg-D7OleMl6YJXwPdBY .image-shape .label,#mermaid-svg-D7OleMl6YJXwPdBY .icon-shape .label{text-anchor:middle;}#mermaid-svg-D7OleMl6YJXwPdBY .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-D7OleMl6YJXwPdBY .rough-node .label,#mermaid-svg-D7OleMl6YJXwPdBY .node .label,#mermaid-svg-D7OleMl6YJXwPdBY .image-shape .label,#mermaid-svg-D7OleMl6YJXwPdBY .icon-shape .label{text-align:center;}#mermaid-svg-D7OleMl6YJXwPdBY .node.clickable{cursor:pointer;}#mermaid-svg-D7OleMl6YJXwPdBY .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-D7OleMl6YJXwPdBY .arrowheadPath{fill:#333333;}#mermaid-svg-D7OleMl6YJXwPdBY .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-D7OleMl6YJXwPdBY .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-D7OleMl6YJXwPdBY .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-D7OleMl6YJXwPdBY .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-D7OleMl6YJXwPdBY .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-D7OleMl6YJXwPdBY .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-D7OleMl6YJXwPdBY .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-D7OleMl6YJXwPdBY .cluster text{fill:#333;}#mermaid-svg-D7OleMl6YJXwPdBY .cluster span{color:#333;}#mermaid-svg-D7OleMl6YJXwPdBY div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-D7OleMl6YJXwPdBY .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-D7OleMl6YJXwPdBY rect.text{fill:none;stroke-width:0;}#mermaid-svg-D7OleMl6YJXwPdBY .icon-shape,#mermaid-svg-D7OleMl6YJXwPdBY .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-D7OleMl6YJXwPdBY .icon-shape p,#mermaid-svg-D7OleMl6YJXwPdBY .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-D7OleMl6YJXwPdBY .icon-shape .label rect,#mermaid-svg-D7OleMl6YJXwPdBY .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-D7OleMl6YJXwPdBY .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-D7OleMl6YJXwPdBY .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-D7OleMl6YJXwPdBY :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 是: 标准GEMM/Conv
否: 融合算子/特殊形状
优化后的计算图
模式匹配:
是否是标准算子?
形状是否规整?
Lowering 到厂商库
cuBLAS / cuDNN
厂商已调至 80-90% 峰值
自主代码生成 Codegen
TVM / Triton / XLA / Inductor
循环变换 + 自动调优
- 库调用路径:标准的大 GEMM、标准卷积,直接交给 cuBLAS/cuDNN,它们由厂商用汇编级手段调优过,自生成代码很难打赢。
- 代码生成路径 :前端融合出来的"非标准"算子(如
softmax + layernorm + residual融合体)、特殊形状、新硬件,库覆盖不了,这时编译器必须自己生成高效 kernel------这正是后端优化技术的主战场。
二、 动手之前:先理解硬件(内存层次与 Roofline)
后端优化的一切手段,都源于两个硬件事实。
事实 1:内存层次决定了"数据搬运比计算贵"
#mermaid-svg-qmLMOjloHugrrl8c{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-qmLMOjloHugrrl8c .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-qmLMOjloHugrrl8c .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-qmLMOjloHugrrl8c .error-icon{fill:#552222;}#mermaid-svg-qmLMOjloHugrrl8c .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-qmLMOjloHugrrl8c .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-qmLMOjloHugrrl8c .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-qmLMOjloHugrrl8c .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-qmLMOjloHugrrl8c .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-qmLMOjloHugrrl8c .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-qmLMOjloHugrrl8c .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-qmLMOjloHugrrl8c .marker{fill:#333333;stroke:#333333;}#mermaid-svg-qmLMOjloHugrrl8c .marker.cross{stroke:#333333;}#mermaid-svg-qmLMOjloHugrrl8c svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-qmLMOjloHugrrl8c p{margin:0;}#mermaid-svg-qmLMOjloHugrrl8c .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-qmLMOjloHugrrl8c .cluster-label text{fill:#333;}#mermaid-svg-qmLMOjloHugrrl8c .cluster-label span{color:#333;}#mermaid-svg-qmLMOjloHugrrl8c .cluster-label span p{background-color:transparent;}#mermaid-svg-qmLMOjloHugrrl8c .label text,#mermaid-svg-qmLMOjloHugrrl8c span{fill:#333;color:#333;}#mermaid-svg-qmLMOjloHugrrl8c .node rect,#mermaid-svg-qmLMOjloHugrrl8c .node circle,#mermaid-svg-qmLMOjloHugrrl8c .node ellipse,#mermaid-svg-qmLMOjloHugrrl8c .node polygon,#mermaid-svg-qmLMOjloHugrrl8c .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-qmLMOjloHugrrl8c .rough-node .label text,#mermaid-svg-qmLMOjloHugrrl8c .node .label text,#mermaid-svg-qmLMOjloHugrrl8c .image-shape .label,#mermaid-svg-qmLMOjloHugrrl8c .icon-shape .label{text-anchor:middle;}#mermaid-svg-qmLMOjloHugrrl8c .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-qmLMOjloHugrrl8c .rough-node .label,#mermaid-svg-qmLMOjloHugrrl8c .node .label,#mermaid-svg-qmLMOjloHugrrl8c .image-shape .label,#mermaid-svg-qmLMOjloHugrrl8c .icon-shape .label{text-align:center;}#mermaid-svg-qmLMOjloHugrrl8c .node.clickable{cursor:pointer;}#mermaid-svg-qmLMOjloHugrrl8c .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-qmLMOjloHugrrl8c .arrowheadPath{fill:#333333;}#mermaid-svg-qmLMOjloHugrrl8c .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-qmLMOjloHugrrl8c .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-qmLMOjloHugrrl8c .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-qmLMOjloHugrrl8c .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-qmLMOjloHugrrl8c .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-qmLMOjloHugrrl8c .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-qmLMOjloHugrrl8c .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-qmLMOjloHugrrl8c .cluster text{fill:#333;}#mermaid-svg-qmLMOjloHugrrl8c .cluster span{color:#333;}#mermaid-svg-qmLMOjloHugrrl8c div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-qmLMOjloHugrrl8c .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-qmLMOjloHugrrl8c rect.text{fill:none;stroke-width:0;}#mermaid-svg-qmLMOjloHugrrl8c .icon-shape,#mermaid-svg-qmLMOjloHugrrl8c .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-qmLMOjloHugrrl8c .icon-shape p,#mermaid-svg-qmLMOjloHugrrl8c .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-qmLMOjloHugrrl8c .icon-shape .label rect,#mermaid-svg-qmLMOjloHugrrl8c .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-qmLMOjloHugrrl8c .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-qmLMOjloHugrrl8c .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-qmLMOjloHugrrl8c :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 寄存器 Registers
~1 cycle · 线程私有 · 每SM约256KB
共享内存 / L1
~20-30 cycles · Block共享 · 可配置至百KB级
L2 Cache
~200 cycles · 全芯片共享 · 数十MB
HBM 全局内存
~400-800 cycles · TB/s级带宽但延迟高
数量级概念(以 A100 为例):FP16 Tensor Core 峰值算力约 312 TFLOPS ,HBM 带宽约 1.5 TB/s 。做一次乘加只要"一瞬间",但从 HBM 搬一个数却要几百个周期。算得再快,喂不上数据也是白搭。
事实 2:Roofline 模型 ------ 后端优化的"导航仪"
性能 (GFLOPS)
│ ┌────────────── 算力屋顶 (如 Tensor Core 峰值)
│ /
│ /
│ / ← 目标: 把 kernel 推向屋顶线
│ /
│ / 内存墙斜坡 (斜率 = HBM 带宽)
│ /
│ /
└──────────────────────→ 算术强度 (FLOPs / Byte)
内存受限区 计算受限区
后端优化的第一步永远是诊断:
- Memory-bound(在斜坡上) → 优化数据复用、合并访问、向量化搬运;
- Compute-bound(在屋顶下) → 上 Tensor Core、展开循环压榨指令级并行;
- Latency-bound(搬和算串行) → 双缓冲、流水线化。
三、 后端优化的五大核心技术
1. 循环变换(Loop Transformation):代码生成的骨架
前端给后端的是一个"数学描述"(如 C[i,j] += A[i,k] * B[k,j]),后端要决定循环怎么写。经典手段如下:
| 变换 | 做了什么 | 解决什么问题 |
|---|---|---|
| 分块 Tiling/Blocking | 把大循环切成适合缓存的小块 | 数据复用,减少 HBM 访问(最核心) |
| 循环交换 Interchange | 调整循环嵌套顺序 | 让最内层访问连续内存(行优先友好) |
| 循环展开 Unroll | 展开最内层循环 | 减少循环控制开销,暴露指令级并行 |
| 向量化 Vectorize | 一次搬运/计算多个数据(如 float4) |
提高带宽利用率,减少指令数 |
| 并行化 Parallelize | 把循环映射到 GPU 的 grid/block/thread | 用满成千上万个计算单元 |
以 GEMM 的 Tiling 为例,这是理解后端优化的"Hello World":
#mermaid-svg-IHqMFDoQ2glypXs5{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-IHqMFDoQ2glypXs5 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-IHqMFDoQ2glypXs5 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-IHqMFDoQ2glypXs5 .error-icon{fill:#552222;}#mermaid-svg-IHqMFDoQ2glypXs5 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-IHqMFDoQ2glypXs5 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-IHqMFDoQ2glypXs5 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-IHqMFDoQ2glypXs5 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-IHqMFDoQ2glypXs5 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-IHqMFDoQ2glypXs5 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-IHqMFDoQ2glypXs5 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-IHqMFDoQ2glypXs5 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-IHqMFDoQ2glypXs5 .marker.cross{stroke:#333333;}#mermaid-svg-IHqMFDoQ2glypXs5 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-IHqMFDoQ2glypXs5 p{margin:0;}#mermaid-svg-IHqMFDoQ2glypXs5 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-IHqMFDoQ2glypXs5 .cluster-label text{fill:#333;}#mermaid-svg-IHqMFDoQ2glypXs5 .cluster-label span{color:#333;}#mermaid-svg-IHqMFDoQ2glypXs5 .cluster-label span p{background-color:transparent;}#mermaid-svg-IHqMFDoQ2glypXs5 .label text,#mermaid-svg-IHqMFDoQ2glypXs5 span{fill:#333;color:#333;}#mermaid-svg-IHqMFDoQ2glypXs5 .node rect,#mermaid-svg-IHqMFDoQ2glypXs5 .node circle,#mermaid-svg-IHqMFDoQ2glypXs5 .node ellipse,#mermaid-svg-IHqMFDoQ2glypXs5 .node polygon,#mermaid-svg-IHqMFDoQ2glypXs5 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-IHqMFDoQ2glypXs5 .rough-node .label text,#mermaid-svg-IHqMFDoQ2glypXs5 .node .label text,#mermaid-svg-IHqMFDoQ2glypXs5 .image-shape .label,#mermaid-svg-IHqMFDoQ2glypXs5 .icon-shape .label{text-anchor:middle;}#mermaid-svg-IHqMFDoQ2glypXs5 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-IHqMFDoQ2glypXs5 .rough-node .label,#mermaid-svg-IHqMFDoQ2glypXs5 .node .label,#mermaid-svg-IHqMFDoQ2glypXs5 .image-shape .label,#mermaid-svg-IHqMFDoQ2glypXs5 .icon-shape .label{text-align:center;}#mermaid-svg-IHqMFDoQ2glypXs5 .node.clickable{cursor:pointer;}#mermaid-svg-IHqMFDoQ2glypXs5 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-IHqMFDoQ2glypXs5 .arrowheadPath{fill:#333333;}#mermaid-svg-IHqMFDoQ2glypXs5 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-IHqMFDoQ2glypXs5 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-IHqMFDoQ2glypXs5 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-IHqMFDoQ2glypXs5 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-IHqMFDoQ2glypXs5 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-IHqMFDoQ2glypXs5 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-IHqMFDoQ2glypXs5 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-IHqMFDoQ2glypXs5 .cluster text{fill:#333;}#mermaid-svg-IHqMFDoQ2glypXs5 .cluster span{color:#333;}#mermaid-svg-IHqMFDoQ2glypXs5 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-IHqMFDoQ2glypXs5 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-IHqMFDoQ2glypXs5 rect.text{fill:none;stroke-width:0;}#mermaid-svg-IHqMFDoQ2glypXs5 .icon-shape,#mermaid-svg-IHqMFDoQ2glypXs5 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-IHqMFDoQ2glypXs5 .icon-shape p,#mermaid-svg-IHqMFDoQ2glypXs5 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-IHqMFDoQ2glypXs5 .icon-shape .label rect,#mermaid-svg-IHqMFDoQ2glypXs5 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-IHqMFDoQ2glypXs5 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-IHqMFDoQ2glypXs5 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-IHqMFDoQ2glypXs5 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 寄存器 / Tensor Core
Shared Memory (Block 级)
HBM 全局内存
合并加载, 只搬 1 次
合并加载, 只搬 1 次
块内反复复用 bk 次
A 的 tile: bm×bk
B 的 tile: bk×bn
A_shared
B_shared
C_tile 累加器: bm×bn
不分块时,每个乘加都要去 HBM 取数,算术强度 ≈1;分块后,一块数据被复用 bm×bn 次,把"内存问题"变成了"计算问题"。
2. 访存优化:喂饱饥饿的计算单元
① 合并访问(Coalesced Access)
GPU 以 warp(32 线程)为单位发起内存事务。若 32 个线程访问地址连续 的数据,硬件可合并为一次 128B 事务;若步长错乱,可能退化为 32 次事务,带宽利用率暴跌。后端的循环映射必须保证最内层线程维度 ↔ 内存连续维度对齐。
② Bank Conflict 与 Padding
Shared Memory 分为 32 个 bank。同一 warp 内多线程访问同一 bank 的不同地址 时会串行化。经典解法是把 tile 宽度 +1 填充(padding),错开 bank。
③ 双缓冲(Double Buffering):用空间换时间,隐藏延迟
❌ 单缓冲 (串行): [搬T0][算T0][搬T1][算T1][搬T2][算T2] ← 计算单元大量空转
✅ 双缓冲 (重叠): [搬T0][搬T1][搬T2][搬T3]
[算T0][算T1][算T2] ← 搬运与计算并行
原理:开两块 shared memory 缓冲,计算第 N 块的同时预取第 N+1 块,用 cp.async 等异步拷贝指令实现,把内存延迟"藏"进计算时间里。
3. 计算指令优化:请出 Tensor Core / SIMD
当 kernel 进入计算受限区,普通 CUDA Core 已经不够用了,后端必须发射专用矩阵指令:
| 硬件 | 专用指令/单元 | 典型形态 |
|---|---|---|
| NVIDIA GPU | Tensor Core (WMMA API / PTX mma.sync) |
一条指令完成 16×8×16 级别的矩阵乘累加 |
| Intel CPU | AVX-512 / AMX | SIMD 向量指令 / 片上矩阵加速块 |
| ARM CPU | NEON / SME | 向量 / 可伸缩矩阵扩展 |
以 A100 为例的峰值差距(数量级示意):
FP32 CUDA Core : ████ 19.5 TFLOPS
TF32 Tensor : ███████████████████████████████ 156 TFLOPS
FP16 Tensor : ██████████████████████████████████████████████████████ 312 TFLOPS
后端编译器要做的是:识别归约循环 → 匹配 Tensor Core 指令形态 → 处理数据布局与对齐要求 → 发射 WMMA/MMA 指令。这一步往往带来 10 倍级 的跃迁。
4. 自动调优(Auto-Tuning):让机器搜索调度
tile 取 64 还是 128?展开几层?几个 warp?是否双缓冲?------这些选择的组合空间是天文数字,且最优解与硬件强相关,人工无法穷举。于是有了自动调优:
#mermaid-svg-AVaL4sXZNPAxvQPV{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-AVaL4sXZNPAxvQPV .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-AVaL4sXZNPAxvQPV .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-AVaL4sXZNPAxvQPV .error-icon{fill:#552222;}#mermaid-svg-AVaL4sXZNPAxvQPV .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-AVaL4sXZNPAxvQPV .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-AVaL4sXZNPAxvQPV .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-AVaL4sXZNPAxvQPV .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-AVaL4sXZNPAxvQPV .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-AVaL4sXZNPAxvQPV .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-AVaL4sXZNPAxvQPV .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-AVaL4sXZNPAxvQPV .marker{fill:#333333;stroke:#333333;}#mermaid-svg-AVaL4sXZNPAxvQPV .marker.cross{stroke:#333333;}#mermaid-svg-AVaL4sXZNPAxvQPV svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-AVaL4sXZNPAxvQPV p{margin:0;}#mermaid-svg-AVaL4sXZNPAxvQPV .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-AVaL4sXZNPAxvQPV .cluster-label text{fill:#333;}#mermaid-svg-AVaL4sXZNPAxvQPV .cluster-label span{color:#333;}#mermaid-svg-AVaL4sXZNPAxvQPV .cluster-label span p{background-color:transparent;}#mermaid-svg-AVaL4sXZNPAxvQPV .label text,#mermaid-svg-AVaL4sXZNPAxvQPV span{fill:#333;color:#333;}#mermaid-svg-AVaL4sXZNPAxvQPV .node rect,#mermaid-svg-AVaL4sXZNPAxvQPV .node circle,#mermaid-svg-AVaL4sXZNPAxvQPV .node ellipse,#mermaid-svg-AVaL4sXZNPAxvQPV .node polygon,#mermaid-svg-AVaL4sXZNPAxvQPV .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-AVaL4sXZNPAxvQPV .rough-node .label text,#mermaid-svg-AVaL4sXZNPAxvQPV .node .label text,#mermaid-svg-AVaL4sXZNPAxvQPV .image-shape .label,#mermaid-svg-AVaL4sXZNPAxvQPV .icon-shape .label{text-anchor:middle;}#mermaid-svg-AVaL4sXZNPAxvQPV .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-AVaL4sXZNPAxvQPV .rough-node .label,#mermaid-svg-AVaL4sXZNPAxvQPV .node .label,#mermaid-svg-AVaL4sXZNPAxvQPV .image-shape .label,#mermaid-svg-AVaL4sXZNPAxvQPV .icon-shape .label{text-align:center;}#mermaid-svg-AVaL4sXZNPAxvQPV .node.clickable{cursor:pointer;}#mermaid-svg-AVaL4sXZNPAxvQPV .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-AVaL4sXZNPAxvQPV .arrowheadPath{fill:#333333;}#mermaid-svg-AVaL4sXZNPAxvQPV .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-AVaL4sXZNPAxvQPV .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-AVaL4sXZNPAxvQPV .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-AVaL4sXZNPAxvQPV .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-AVaL4sXZNPAxvQPV .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-AVaL4sXZNPAxvQPV .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-AVaL4sXZNPAxvQPV .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-AVaL4sXZNPAxvQPV .cluster text{fill:#333;}#mermaid-svg-AVaL4sXZNPAxvQPV .cluster span{color:#333;}#mermaid-svg-AVaL4sXZNPAxvQPV div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-AVaL4sXZNPAxvQPV .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-AVaL4sXZNPAxvQPV rect.text{fill:none;stroke-width:0;}#mermaid-svg-AVaL4sXZNPAxvQPV .icon-shape,#mermaid-svg-AVaL4sXZNPAxvQPV .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-AVaL4sXZNPAxvQPV .icon-shape p,#mermaid-svg-AVaL4sXZNPAxvQPV .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-AVaL4sXZNPAxvQPV .icon-shape .label rect,#mermaid-svg-AVaL4sXZNPAxvQPV .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-AVaL4sXZNPAxvQPV .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-AVaL4sXZNPAxvQPV .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-AVaL4sXZNPAxvQPV :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 快速筛选
精确评估
生成搜索空间
tile大小/线程布局/展开/缓冲级数
采样候选调度
评估
代价模型打分
如 XGBoost
真实硬件实测耗时
进化搜索 / 机器学习引导
更新采样策略
收敛 → 输出最优 schedule
生态中的代表选手:
- TVM AutoTVM / Ansor(Auto-scheduler):模板化 / 自动生成搜索空间,代价模型 + 进化搜索;
- Triton
@triton.autotune:对BLOCK_SIZE, num_warps, num_stages等配置自动 benchmark; - TensorRT 构建期调优:对每层候选 kernel 真机计时,选最快者并缓存(timing cache);
- cuDNN benchmark 模式 (
torch.backends.cudnn.benchmark):固定形状下对卷积算法实测择优。
💡 为什么必须调优?因为优化手段之间存在相互制约:tile 太大 → 寄存器溢出(register spilling)反而变慢;展开太多 → 占用寄存器导致并发度下降。最优解是多个约束的平衡点,只能搜,不能猜。
5. 库 Lowering:站在厂商的肩膀上
对于标准算子,后端最"聪明"的做法往往是不自己写:
| 库 | 覆盖范围 | 说明 |
|---|---|---|
| cuBLAS | GEMM | NVIDIA 官方调优,大矩阵可达峰值 80%+ |
| cuDNN | Conv/Pool/Norm 等 | 内置多种卷积算法 + heuristic 选择 |
| CUTLASS | 可定制 GEMM 模板 | 暴露 tiling/epilogue 定制能力,是"半自动生成"的桥梁 |
| oneDNN / ACL | Intel CPU / ARM | CPU 与边缘设备的对应物 |
库路径的缺点是黑盒、不灵活 :它不认识前端融合出来的"异形"算子,也改不了 epilogue。因此现代编译器的策略是 "标准算子走库,融合算子走 codegen" 的混合路线。
四、 案例:一个 GEMM Kernel 的五版进化
下面用一个教学示例(某 GPU 上的示意量级,具体数值因硬件而异,重点看趋势)展示后端优化的叠加效果:
#mermaid-svg-gIIuo2AKZpd5aaRr{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-gIIuo2AKZpd5aaRr .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-gIIuo2AKZpd5aaRr .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-gIIuo2AKZpd5aaRr .error-icon{fill:#552222;}#mermaid-svg-gIIuo2AKZpd5aaRr .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-gIIuo2AKZpd5aaRr .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-gIIuo2AKZpd5aaRr .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-gIIuo2AKZpd5aaRr .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-gIIuo2AKZpd5aaRr .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-gIIuo2AKZpd5aaRr .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-gIIuo2AKZpd5aaRr .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-gIIuo2AKZpd5aaRr .marker{fill:#333333;stroke:#333333;}#mermaid-svg-gIIuo2AKZpd5aaRr .marker.cross{stroke:#333333;}#mermaid-svg-gIIuo2AKZpd5aaRr svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-gIIuo2AKZpd5aaRr p{margin:0;}#mermaid-svg-gIIuo2AKZpd5aaRr .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-gIIuo2AKZpd5aaRr .cluster-label text{fill:#333;}#mermaid-svg-gIIuo2AKZpd5aaRr .cluster-label span{color:#333;}#mermaid-svg-gIIuo2AKZpd5aaRr .cluster-label span p{background-color:transparent;}#mermaid-svg-gIIuo2AKZpd5aaRr .label text,#mermaid-svg-gIIuo2AKZpd5aaRr span{fill:#333;color:#333;}#mermaid-svg-gIIuo2AKZpd5aaRr .node rect,#mermaid-svg-gIIuo2AKZpd5aaRr .node circle,#mermaid-svg-gIIuo2AKZpd5aaRr .node ellipse,#mermaid-svg-gIIuo2AKZpd5aaRr .node polygon,#mermaid-svg-gIIuo2AKZpd5aaRr .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-gIIuo2AKZpd5aaRr .rough-node .label text,#mermaid-svg-gIIuo2AKZpd5aaRr .node .label text,#mermaid-svg-gIIuo2AKZpd5aaRr .image-shape .label,#mermaid-svg-gIIuo2AKZpd5aaRr .icon-shape .label{text-anchor:middle;}#mermaid-svg-gIIuo2AKZpd5aaRr .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-gIIuo2AKZpd5aaRr .rough-node .label,#mermaid-svg-gIIuo2AKZpd5aaRr .node .label,#mermaid-svg-gIIuo2AKZpd5aaRr .image-shape .label,#mermaid-svg-gIIuo2AKZpd5aaRr .icon-shape .label{text-align:center;}#mermaid-svg-gIIuo2AKZpd5aaRr .node.clickable{cursor:pointer;}#mermaid-svg-gIIuo2AKZpd5aaRr .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-gIIuo2AKZpd5aaRr .arrowheadPath{fill:#333333;}#mermaid-svg-gIIuo2AKZpd5aaRr .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-gIIuo2AKZpd5aaRr .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-gIIuo2AKZpd5aaRr .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-gIIuo2AKZpd5aaRr .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-gIIuo2AKZpd5aaRr .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-gIIuo2AKZpd5aaRr .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-gIIuo2AKZpd5aaRr .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-gIIuo2AKZpd5aaRr .cluster text{fill:#333;}#mermaid-svg-gIIuo2AKZpd5aaRr .cluster span{color:#333;}#mermaid-svg-gIIuo2AKZpd5aaRr div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-gIIuo2AKZpd5aaRr .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-gIIuo2AKZpd5aaRr rect.text{fill:none;stroke-width:0;}#mermaid-svg-gIIuo2AKZpd5aaRr .icon-shape,#mermaid-svg-gIIuo2AKZpd5aaRr .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-gIIuo2AKZpd5aaRr .icon-shape p,#mermaid-svg-gIIuo2AKZpd5aaRr .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-gIIuo2AKZpd5aaRr .icon-shape .label rect,#mermaid-svg-gIIuo2AKZpd5aaRr .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-gIIuo2AKZpd5aaRr .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-gIIuo2AKZpd5aaRr .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-gIIuo2AKZpd5aaRr :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} v0 朴素版
直接读写全局内存
≈ 1%~5% 峰值
v1 + Shared Memory 分块
数据块内复用
≈ 10x
v2 + 合并访问 + float4 向量化 + 展开
消除 bank conflict
≈ 再 2~3x
v3 + 双缓冲异步拷贝
隐藏内存延迟
≈ 再 +20%~40%
v4 + Tensor Core (WMMA)
专用矩阵指令
≈ 数倍跃迁, 逼近 cuBLAS 的 60%~90%
| 版本 | 引入的后端技术 | 瓶颈变化 | 相对提升(示意) |
|---|---|---|---|
| v0 | 无 | 严重内存受限 | 1x |
| v1 | Tiling + Shared Memory | 内存压力大幅缓解 | ~10x |
| v2 | Coalescing + Vectorize + Unroll | 带宽利用率拉满 | ~20-30x |
| v3 | Double Buffering | 延迟被隐藏 | ~30-40x |
| v4 | Tensor Core + 自动调优 | 进入计算受限区,逼近屋顶 | ~50-100x |
从 1% 峰值到逼近厂商库------这就是后端优化的价值,也是 CUDA 程序员与编译器共同的手艺。
五、 前端与后端:不是两层,而是一个闭环
最后必须强调:前端与后端不是孤立的两层,而是相互制约的闭环。
| 维度 | 前端优化 | 后端优化 |
|---|---|---|
| 粒度 | 算子 / 计算图 | 循环 / 指令 |
| 回答的问题 | 算什么、少算什么 | 怎么算、算多快 |
| 典型技术 | 融合、折叠、CSE、DCE、布局变换 | Tiling、向量化、展开、Tensor Core、Auto-tuning |
| 硬件相关性 | 低(相对硬件无关) | 高(与具体硬件深度耦合) |
| 代表工具 | TorchFX、ONNX GraphSurgeon、Grappler | TVM/Ansor、Triton、CUTLASS、XLA codegen、Inductor |
闭环体现在哪?
- 融合决策依赖后端能力 :前端把 5 个算子融合成 1 个,前提是后端能生成一个高效的融合 kernel。Torch Inductor / XLA:GPU 如今用 Triton 做融合代码生成,正是"前端融合策略"与"后端 codegen 能力"协同设计的产物。
- 布局决策联动:前端选 NHWC,是为了后端能命中 Tensor Core 友好的库 kernel;后端发现某布局更优,也会反馈给前端插入 transpose。
- 形状信息传递 :前端做静态形状推断(上一篇的常量折叠),后端才能做特化 tiling 与向量化------动态形状是后端优化最大的敌人。
总结
用一句话概括后端优化的方法论:
先诊断(Roofline),再对症:内存受限做复用与合并,计算受限上 Tensor Core,延迟受限做流水与双缓冲,最后把参数选择交给自动调优。
- 循环变换 是骨架,访存优化 是血脉,Tensor Core 是肌肉,自动调优 是神经系统,库 Lowering 是站在巨人肩膀上的捷径。
- 前端让图"更小",后端让 kernel"更快",二者闭环协同,才构成 AI 编译器的完整战斗力。