Kernels
3v324v23 Claude Opus 4.6 (1M context) commited on
Commit
1e2bc2b
·
1 Parent(s): 4d94a7d

perf: remove autotune, hard-code per-kernel configs from live dump

Browse files

Autotune isn't buying anything for these kernels: at runtime the shapes
are fixed by the model config (H ∈ {1, 80}, rope_dim=64), and live-dump
(TRITON_PRINT_AUTOTUNING=1) on motif3_seq B=8 S=4096 n_layers=4 showed
every kernel's best config sitting in a tight cluster that doesn't
change across reasonable workload sizes.

Replace @triton .autotune + config helpers with a small dict of static
(BLOCK_H, num_warps, num_stages) per kernel, passed at each kernel
launch. Values are the plurality-pick from the live dump:

_rope_fwd_kernel BLOCK_H=1, warps=1, stages=3 # k_pe, H=1
_rope_bwd_kernel BLOCK_H=2, warps=1, stages=1 # k_pe bwd
_kv_rope_fwd_kernel BLOCK_H=32, warps=8, stages=2 # H=80
_q_rope_inplace_fwd_kernel BLOCK_H=8, warps=1, stages=2 # H=80
_q_rope_bwd_kernel BLOCK_H=4, warps=2, stages=2 # H=80

Validation (same shape, autotune-full-sweep vs no-autotune, both B=8
n_layers=4): step 10 loss matches (0.0001), per-kernel time within
±15% (normalized, dominated by run-to-run noise). Warm-up cost drops
by ~213 s (full 640-trial sweep → 5 single-config compiles).

If model config changes materially (new H, different D), rerun the
dump and update the constants. The key=(rope_dim, head_num) invariant
that autotune used to key on is now enforced implicitly: any caller
that exercises a meaningfully different shape must update the configs.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

Files changed (1) hide show
  1. torch-ext/activation/fused_rope.py +23 -51
torch-ext/activation/fused_rope.py CHANGED
@@ -13,49 +13,32 @@ import triton
13
  import triton.language as tl
14
 
15
  # ---------------------------------------------------------------------------
16
- # Autotune search space — hand-picked from a full-sweep dump on motif3_seq
17
- # (B=4, S=4096, H=80, rope_dim=64, B200) with TRITON_PRINT_AUTOTUNING=1.
18
- # Best configs clustered around BLOCK_H∈{2,4,8}, warps∈{2,4}, stages=2 for
19
- # every RoPE kernel; keeping a handful of neighbours for shape robustness.
20
- # Triton caches per-(key) best config — one-time compile cost per distinct shape.
21
- # autotune key is (rope_dim, head_num) only; stride is not included because all
22
- # kernels assume last-dim unit stride + head-major layout (enforced by the
23
- # `stride(-1) == 1` assert at each wrapper entry), so layout never branches.
 
 
 
24
  # ---------------------------------------------------------------------------
25
 
26
- def _rope_autotune_configs_fwd():
27
- # Covers best configs observed across the 3 fwd kernels:
28
- # _rope_fwd (k_pe, H=1 tail) → BLOCK_H=2, warps=2
29
- # _q_rope_inplace_fwd → BLOCK_H=8, warps=2
30
- # _kv_rope_fwd → BLOCK_H=8, warps=4
31
- return [
32
- triton.Config({"BLOCK_H": 2}, num_warps=2, num_stages=2),
33
- triton.Config({"BLOCK_H": 4}, num_warps=2, num_stages=2),
34
- triton.Config({"BLOCK_H": 8}, num_warps=2, num_stages=2),
35
- triton.Config({"BLOCK_H": 8}, num_warps=4, num_stages=2),
36
- ]
37
-
38
-
39
- def _rope_autotune_configs_bwd():
40
- # Covers best configs for both bwd kernels:
41
- # _q_rope_bwd → BLOCK_H=4, warps=2
42
- # _rope_bwd → BLOCK_H=2, warps∈{1,2} (flaky; tiebreak jitter on 88µs
43
- # total budget — any of these is within noise)
44
- return [
45
- triton.Config({"BLOCK_H": 2}, num_warps=2, num_stages=2),
46
- triton.Config({"BLOCK_H": 4}, num_warps=2, num_stages=2),
47
- triton.Config({"BLOCK_H": 8}, num_warps=2, num_stages=2),
48
- ]
49
 
50
 
51
  # ---------------------------------------------------------------------------
52
  # Triton kernels
53
  # ---------------------------------------------------------------------------
54
 
55
- @triton.autotune(
56
- configs=_rope_autotune_configs_fwd(),
57
- key=["rope_dim", "head_num"],
58
- )
59
  @triton.jit
60
  def _rope_fwd_kernel(
61
  X, # [B*S, H, rope_dim] interleaved
@@ -102,10 +85,6 @@ def _rope_fwd_kernel(
102
  tl.store(O_ptr + imag_off, out_imag, mask=mask)
103
 
104
 
105
- @triton.autotune(
106
- configs=_rope_autotune_configs_bwd(),
107
- key=["rope_dim", "head_num"],
108
- )
109
  @triton.jit
110
  def _rope_bwd_kernel(
111
  DO, # [B*S, H, rope_dim] contiguous
@@ -172,6 +151,7 @@ def _rope_fwd(
172
  D, H, seq_len,
173
  x.stride(0), x.stride(1),
174
  out.stride(0), out.stride(1),
 
175
  )
176
  return out
177
 
@@ -197,6 +177,7 @@ def _rope_bwd(
197
  D, H, seq_len,
198
  grad_out.stride(0), grad_out.stride(1),
199
  grad_in.stride(0), grad_in.stride(1),
 
200
  )
201
  return grad_in
202
 
@@ -254,10 +235,6 @@ def fused_apply_rope(x, freqs_cis):
254
  # Reference: Megatron rotary_fwd_kv_kernel
255
  # ---------------------------------------------------------------------------
256
 
257
- @triton.autotune(
258
- configs=_rope_autotune_configs_fwd(),
259
- key=["rope_dim", "k_nope_dim", "v_dim", "head_num"],
260
- )
261
  @triton.jit
262
  def _kv_rope_fwd_kernel(
263
  KV, # [B*S, H, k_nope_dim + v_dim]
@@ -338,6 +315,7 @@ def _kv_rope_fwd(
338
  k_pe.stride(0),
339
  key.stride(0), key.stride(1),
340
  value.stride(0), value.stride(1),
 
341
  )
342
  return key, value
343
 
@@ -394,10 +372,6 @@ class FusedKVRoPE(torch.autograd.Function):
394
  # gradient is copied through unchanged.
395
  # ---------------------------------------------------------------------------
396
 
397
- @triton.autotune(
398
- configs=_rope_autotune_configs_bwd(),
399
- key=["nope_dim", "rope_dim", "head_num"],
400
- )
401
  @triton.jit
402
  def _q_rope_bwd_kernel(
403
  DO, # [B*S, H, nope_dim + rope_dim] grad (contiguous rope fmt)
@@ -471,6 +445,7 @@ def _q_rope_bwd(
471
  nope_dim, rope_dim, H, seq_len,
472
  grad_out.stride(0), grad_out.stride(1),
473
  grad_in.stride(0), grad_in.stride(1),
 
474
  )
475
  return grad_in
476
 
@@ -488,10 +463,6 @@ def _q_rope_bwd_fake(grad_out, cos, sin, nope_dim, rope_dim, seq_len):
488
  # Backward: out-of-place via existing _q_rope_bwd_kernel (nope grad copy + inverse rope)
489
  # ---------------------------------------------------------------------------
490
 
491
- @triton.autotune(
492
- configs=_rope_autotune_configs_fwd(),
493
- key=["nope_dim", "rope_dim", "head_num"],
494
- )
495
  @triton.jit
496
  def _q_rope_inplace_fwd_kernel(
497
  Q, # [B*S, H, nope_dim + rope_dim] modified in-place on [..., nope_dim:]
@@ -555,6 +526,7 @@ def _q_rope_inplace_fwd(
555
  q, cos, sin,
556
  nope_dim, rope_dim, H, seq_len,
557
  q.stride(0), q.stride(1),
 
558
  )
559
 
560
 
 
13
  import triton.language as tl
14
 
15
  # ---------------------------------------------------------------------------
16
+ # Static configs per kernel — no autotune.
17
+ #
18
+ # Picked from a full-sweep dump (TRITON_PRINT_AUTOTUNING=1) on motif3_seq,
19
+ # B=8, S=4096, n_layers=4, 8×B200, EP=8 (plurality across 8 ranks; see
20
+ # PR description for details). These are the shapes the kernels see at
21
+ # the current prod workload; hard-coding avoids autotune warm-up cost and
22
+ # tie-break jitter between near-equivalent configs.
23
+ #
24
+ # If model config changes materially (different H, D, batch-size/seq-len
25
+ # regime), re-run the dump and update these. Autotune key used to be
26
+ # (rope_dim, head_num); same shape invariants still apply at runtime.
27
  # ---------------------------------------------------------------------------
28
 
29
+ # BLOCK_H, num_warps, num_stages per kernel. H values denote head_num
30
+ # (head-shared k_pe is H=1; per-head q/kv is H=80 in motif3_seq).
31
+ _CFG_ROPE_FWD = dict(BLOCK_H=1, num_warps=1, num_stages=3) # k_pe fwd, H=1
32
+ _CFG_ROPE_BWD = dict(BLOCK_H=2, num_warps=1, num_stages=1) # k_pe bwd, H=1
33
+ _CFG_KV_ROPE_FWD = dict(BLOCK_H=32, num_warps=8, num_stages=2) # kv fused, H=80
34
+ _CFG_Q_ROPE_INPLACE_FWD = dict(BLOCK_H=8, num_warps=1, num_stages=2) # q in-place, H=80
35
+ _CFG_Q_ROPE_BWD = dict(BLOCK_H=4, num_warps=2, num_stages=2) # q bwd, H=80
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
36
 
37
 
38
  # ---------------------------------------------------------------------------
39
  # Triton kernels
40
  # ---------------------------------------------------------------------------
41
 
 
 
 
 
42
  @triton.jit
43
  def _rope_fwd_kernel(
44
  X, # [B*S, H, rope_dim] interleaved
 
85
  tl.store(O_ptr + imag_off, out_imag, mask=mask)
86
 
87
 
 
 
 
 
88
  @triton.jit
89
  def _rope_bwd_kernel(
90
  DO, # [B*S, H, rope_dim] contiguous
 
151
  D, H, seq_len,
152
  x.stride(0), x.stride(1),
153
  out.stride(0), out.stride(1),
154
+ **_CFG_ROPE_FWD,
155
  )
156
  return out
157
 
 
177
  D, H, seq_len,
178
  grad_out.stride(0), grad_out.stride(1),
179
  grad_in.stride(0), grad_in.stride(1),
180
+ **_CFG_ROPE_BWD,
181
  )
182
  return grad_in
183
 
 
235
  # Reference: Megatron rotary_fwd_kv_kernel
236
  # ---------------------------------------------------------------------------
237
 
 
 
 
 
238
  @triton.jit
239
  def _kv_rope_fwd_kernel(
240
  KV, # [B*S, H, k_nope_dim + v_dim]
 
315
  k_pe.stride(0),
316
  key.stride(0), key.stride(1),
317
  value.stride(0), value.stride(1),
318
+ **_CFG_KV_ROPE_FWD,
319
  )
320
  return key, value
321
 
 
372
  # gradient is copied through unchanged.
373
  # ---------------------------------------------------------------------------
374
 
 
 
 
 
375
  @triton.jit
376
  def _q_rope_bwd_kernel(
377
  DO, # [B*S, H, nope_dim + rope_dim] grad (contiguous rope fmt)
 
445
  nope_dim, rope_dim, H, seq_len,
446
  grad_out.stride(0), grad_out.stride(1),
447
  grad_in.stride(0), grad_in.stride(1),
448
+ **_CFG_Q_ROPE_BWD,
449
  )
450
  return grad_in
451
 
 
463
  # Backward: out-of-place via existing _q_rope_bwd_kernel (nope grad copy + inverse rope)
464
  # ---------------------------------------------------------------------------
465
 
 
 
 
 
466
  @triton.jit
467
  def _q_rope_inplace_fwd_kernel(
468
  Q, # [B*S, H, nope_dim + rope_dim] modified in-place on [..., nope_dim:]
 
526
  q, cos, sin,
527
  nope_dim, rope_dim, H, seq_len,
528
  q.stride(0), q.stride(1),
529
+ **_CFG_Q_ROPE_INPLACE_FWD,
530
  )
531
 
532