torch.compile 技术剖析(三):Lowering
1. realize 是什么?
在 Inductor 里,realize 的意思是:把一个还没有真正落到内存里的中间表达式,强制变成一个真实 buffer。
例如:
out = relu(a + b)
a + b 不一定会生成中间 tensor。Inductor 可以直接融合成:
out[i] = relu(a[i] + b[i])
这里 a+b 没有 realize,没有写 HBM。
但如果是:
out = mm(a + b, w)
如果 mm lowering 到 cuBLAS,cuBLAS 只能接受真实矩阵指针:
A pointer, B pointer, C pointer
它不能接受表达式:
A[i,j] = a[i,j] + b[i,j]
所以必须先:
tmp = a + b # realize 成真实 buffer
out = cuBLAS_mm(tmp, w)
因此:
x = x.realize_input()
不是因为“后面要读数据”,而是因为后面的 extern kernel 需要真实 storage pointer。
Reduction 不一定需要 realize,因为如果 reduction 是 Inductor 自己生成的 kernel,它可以把表达式 inline 进去:
s = sum(a + b)
可以生成:
acc += a[i] + b[i]
不需要先生成 tmp = a+b。
一句话:realize 是 materialize;它会把 lazy IR / view / expression 变成真实 buffer,常见于进入 cuBLAS/cuDNN 这种 extern kernel 前。realize 本质上是在 IR 上加了一个“必须物化成真实 buffer”的约束;它会切断 lazy 表达式继续被重写、融合、inline 的自由度。
2. Channels-last layout 是什么?
Channels-last 是一种 4D 图像 tensor 的内存布局。逻辑 shape 仍然通常是:
[N, C, H, W]
但物理内存顺序更像:
[N, H, W, C]
也就是:同一个像素位置的不同 channel 连续存放。
普通 NCHW contiguous:
size = [N, C, H, W]
stride = [C*H*W, H*W, W, 1]
例如访问:
x[n,c,h,w] offset = n*C*H*W + c*H*W + h*W + w
这表示同一个 channel 内的 H/W 连续。
Channels-last:
stride = [H*W*C, 1, W*C, C]
访问:
x[n,c,h,w] offset = n*H*W*C + c + h*W*C + w*C
所以:
x[n,0,h,w]
x[n,1,h,w]
x[n,2,h,w]
在内存中是连续的。
这对卷积有好处,因为卷积经常在同一个 (h,w) 位置遍历 channel:
for c in C:
use x[n,c,h,w]
channels-last 让这些访问连续,更容易 coalesced load、vectorized load、cache line 利用率更高,也更适合 cuDNN 的一些 NHWC/Tensor Core 路径。
一句话:channels-last 不是改变 tensor 的逻辑索引,而是改变底层 stride,让 channel 维在物理内存里最连续。
Comments
No comments yet.