cutlass 入门
学下 cutlass, 写点总结
swizzle
为减少 (主要是 mma ldmatrix 的) bank conflict, 需要对 shape stride offset 后得到的标量一维地址进行 swizzle, 记作 Swizzle o Offset o Layout
(mma 只能小矩阵的乘法, 导致多个线程加载一个小部分的内存, 在行主序的情况下更容易导致 bank conflict, 可以参考文章)
具体过程
swizzle<B, M, S>
- B: Base / num_bits: 参与亦或的位的长度 (len(z) == len(y))
- M: Mask / num_base: 保持不变的末尾长度, 可以看做变换中的单位长度
- S: Shift / num_shift: 参与亦或的两段 bit 的距离
贴下 cutlass 中的原注释
1 | INPUT: |
总的来说, swizzle 的输出就是把输入的一部分和另一部分做异或
本质
swizzle 本质就是把二维坐标中的 new_icol = icol xor irow
从这个角度理解, 就可以:
- 把坐标的低
M位看做操作的具体单元 - 更高的
S位看做是表示列号的范围 - 再高的
B位看做是表示行号的范围
这样, 定义中的
1 | true_mask = ((1 << B) - 1) << (M + S) |
就可以理解为列号异或行号了
swizzle 融入 layout 优化
在某些 slice(固定某些坐标) 的情况下, swizzle(layout(irow, icol)) 可以被简化为一个 new_layout(irow, icol), 而结果不变, 这样可以节约运算
这种简化要求 swizzle 具有一些性质, 比较简单的要求就是在 slice 的要求下, y 和 z 的所有对应的位 i 中, y_i 和 z_i 有一个不变:
- 都不变: 显然, swizzle 的结果不变
y_i不变:z_i不变:
有一个简单的判断方法可以快速判断:
设 A = slice(max_index), A 中为 1 的位就是 swizzle 前活跃的位 (和数位 dp 之类的类似, 如果 slice 的这一位可以活动, 那能表示的最大值的这一位一定是 1)
collision_bitwise = A and (~sw(A))
证明:
对一对 $Y_i/Z_i$,设:$a_z=A_{Z_i},\ a_y=A_{Y_i}$
则: $\operatorname{sw}(A)_{Z_i}=a_z\oplus a_y$
四种情况是:
| $a_z$ | $a_y$ | 含义 | $\operatorname{sw}(A)_{Z_i}$ |
|---|---|---|---|
| 0 | 0 | 都不 active | 0 |
| 0 | 1 | 只有 $Y_i$ active | 1 |
| 1 | 0 | 只有 $Z_i$ active | 1 |
| 1 | 1 | $Y_i,Z_i$ 同时 active | 0 |
再观察 $C$ 在 $Z_i$ 位置上的值:$C_{Z_i}=A_{Z_i}\land \neg \operatorname{sw}(A)_{Z_i}$
代入:$C_{Z_i}=a_z\land\neg(a_z\oplus a_y)$
| $a_z$ | $a_y$ | $a_z\oplus a_y$ | $a_z\land\neg(a_z\oplus a_y)$ |
|---|---|---|---|
| 0 | 0 | 0 | 0 |
| 0 | 1 | 1 | 0 |
| 1 | 0 | 1 | 0 |
| 1 | 1 | 0 | 1 |
$C_i$ 为 1 当且仅当 $Z_i$ 和 $Y_i$ 都 active (对 sw(A) 取反消除了 $Y, Z$ 之外的位的影响)