[diffusion][kernel] avoid 4D scale-shift autotuning (#36521)
This commit is contained in:
@@ -90,6 +90,7 @@ Several norms look interchangeable and are not. Start here.
|
||||
|
||||
| Entry point | Backend | Contract | Applies to |
|
||||
|---|---|---|---|
|
||||
| `fuse_scale_shift_kernel` | Triton | close | contiguous BLC; scalar/row/token modulation plus causal-video `[B, F, 1, C]`, using a static capped power-of-two tile to avoid request-time autotuning |
|
||||
| `fused_rmsnorm_scale_shift_bitexact` | Triton | bit-exact vs flashinfer CuTe RMSNorm + aten modulate | bf16, contiguous rows, `H == 64 * threads_per_row` |
|
||||
| `fused_scale_residual_rmsnorm_scale_shift_bitexact` | Triton | bit-exact, incl. the preceding residual-gate add | as above |
|
||||
| `fused_layernorm_modulate` | Triton | bit-exact vs aten `vectorized_layer_norm` | bf16, `N % 4 == 0`, 16B-aligned |
|
||||
|
||||
@@ -272,16 +272,6 @@ def _fused_residual_layernorm_scale_shift_gate_select01_kernel(
|
||||
tl.store(gate_row_ptr + cols, gate, mask=mask)
|
||||
|
||||
|
||||
@triton.autotune(
|
||||
configs=[
|
||||
triton.Config({"BLOCK_N": 64}, num_warps=2),
|
||||
triton.Config({"BLOCK_N": 128}, num_warps=4),
|
||||
triton.Config({"BLOCK_N": 256}, num_warps=4),
|
||||
triton.Config({"BLOCK_N": 512}, num_warps=4),
|
||||
triton.Config({"BLOCK_N": 1024}, num_warps=8),
|
||||
],
|
||||
key=["inner_dim"],
|
||||
)
|
||||
@triton.jit
|
||||
def _fused_scale_shift_4d_kernel(
|
||||
output_ptr,
|
||||
@@ -416,9 +406,12 @@ def fuse_scale_shift_kernel(
|
||||
x_2d = x.view(rows, C)
|
||||
output_2d = output.view(rows, C)
|
||||
|
||||
def grid(meta):
|
||||
return (rows, triton.cdiv(C, meta["BLOCK_N"]))
|
||||
|
||||
# Autotuning this bandwidth-bound kernel is much more expensive than
|
||||
# the launch itself on causal video models. A capped power-of-two
|
||||
# tile is fastest or within noise across the production hidden sizes.
|
||||
block_n = max(64, min(512, triton.next_power_of_2(C)))
|
||||
num_warps = 2 if block_n == 64 else 4
|
||||
grid = (rows, triton.cdiv(C, block_n))
|
||||
num_frames = scale.shape[1]
|
||||
assert (
|
||||
L % num_frames == 0
|
||||
@@ -454,6 +447,8 @@ def fuse_scale_shift_kernel(
|
||||
L,
|
||||
num_frames,
|
||||
frame_seqlen,
|
||||
BLOCK_N=block_n,
|
||||
num_warps=num_warps,
|
||||
)
|
||||
else:
|
||||
# 2D: [B, C] or [1, C] -> treat as [B, 1, C] and broadcast over L
|
||||
|
||||
+4
@@ -77,6 +77,10 @@ framework-specific optimization workflow.
|
||||
- Locations: `elementwise.py`, `layernorm.py`, `fused_scale_shift_gate.py`, `qwen_image.py`, `triton/scale_shift.py`
|
||||
- Use cases: `x * (1 + scale) + shift`, `a * (k + b) + c`, and Qwen-style `(layernorm/residual layernorm) + scale/shift + gate select`.
|
||||
- Constraints: `x` must be CUDA and contiguous. `scale/shift` support 0D/1D/2D/3D/4D broadcast. 4D `[B, F, 1, C]` requires `L % F == 0`.
|
||||
- Causal-video cold start: the 4D path uses a static capped power-of-two
|
||||
column tile rather than Triton autotuning. Do not reintroduce request-time
|
||||
autotuning here: LingBot-World calls this path once per transformer block,
|
||||
and tuning overhead can dominate its first denoise step.
|
||||
- NPU fallback: `scale_shift.py` swaps to `npu_fallback` native path.
|
||||
- Validation: `test/registered/kernels/ops/diffusion/test_qwen_image_modulation.py`.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user