Skip to content

Commit daee90e

Browse files
xudoyuanclaudecoderfeli
authored
DSL-ify raw arith float ops in kernels (flash/mla/pa/moe), fastmath v… (#930)
* DSL-ify raw arith float ops in kernels (flash/mla/pa/moe), fastmath via fast_fp_math Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * kernels: DSL-ify raw integer arith ops into operators Replace raw MLIR integer arith in kernels with DSL operators: - arith.cmpi(pred, a, b) -> a == / != / < / <= / > / >= - arith.divsi/divui -> //, remsi/remui -> % - arith.andi/ori/xori -> & / | / ^, shli -> <<, shrui/shrsi -> >> Operands stay DSL values (drop _raw/as_mlir_value/.ir_value unwraps). At raw-i1 consumers (scf.IfOp / llvm.intr_expect / arith.select cond), use as_ir_value(...), which handles both ArithValue (comparison over ArithValue operands) and Boolean (comparison over Numeric operands). Deliberately left as raw arith, with reasons: - unsigned compare where an operand can be negative (signed compare would misclassify) — must stay ult - pow2 strength-reduced shift/and standing in for divide/remainder - unsigned-division helpers whose contract is unsigned - integer min/max (no DSL integer min/max), ceil-div (no operator) - operands that are genuinely raw ir.Value (ballot / readfirstlane / scf result / dpp) with no DSL wrapper Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * kernels: replace raw MLIR index builders with DSL De-index kernel code by replacing raw MLIR index builders with DSL: - arith.index(n) / arith.constant(v, index=True) -> fx.Index(v) - arith.index_cast(T.i32/i64, x) -> fx.Int32(x) / fx.Int64(x) At raw low-level consumers (get_llvm_ptr / llvm.* / rocdl.* / buffer DMA offset), the DSL value is unwrapped with as_ir_value(...). scf.for loop-carried counters that were arith.constant(0, index=True) become fx.Index(0) (type-preserving). Left as-is (with reasons): - index values used as layout coordinates (vec_load/vec_store/ linear_offset/cs_off/memref) and anything combined or compared with them: the layout shim casts coordinates from index, so they must stay index-typed - arith.index_cast(T.index, x) producing grid/launch or coordinate index values - raw index operands of raw shift/and builders (strength-reduced pow2 paths) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * kernels: DSL-ify unsigned expert-id compare in dispatch kernel The last raw arith.cmpi here needed unsigned ult (local_expert_id can be negative for non-local experts; a signed compare would misclassify them). fx.Uint32 reinterprets the same i32 bits as unsigned, so the DSL `<` emits ult — behavior-preserving. Result feeds a dynamic if, so wrap with as_ir_value. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * kernels: drop redundant as_ir_value at arith.select conditions arith.select unwraps DSL Numeric/Boolean conditions itself (via _to_raw), so wrapping the condition in as_ir_value was unnecessary. Pass the DSL comparison directly. as_ir_value stays only where the consumer is a raw MLIR builder that requires an ir.Value (scf.IfOp, llvm.*, rocdl.*, get_llvm_ptr, vector.*, buffer DMA offsets). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * kernels: keep is_local as a DSL Boolean in dispatch kernel The as_ir_value wrapper was redundant: is_local feeds a dynamic `if` (the AST rewriter converts the condition to i1 itself) and is_local.select(...) (a DSL method). Keep it as the DSL Boolean from fx.Uint32 comparison. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * attention/pa: use contract fastmath (not fast) to preserve fp8 accuracy The paged-decode accumulation/reduction ops originally used the narrow `contract` fastmath flag (FMA fusion only, preserves accumulation order). DSL-ifying them under a `fast_fp_math` hint widened the flag to `fast`, whose reassoc reorders fp accumulation and loses precision on fp8 (bf16/ fp16 tolerate it). Switch the pa launchers' compile hint from {"fast_fp_math": True} to {"fastmath": contract} so the DSL operators emit `contract`, matching the original per-op flag. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * attention: minimal parens + .maximumf()->fx.maxnumf() cleanup Behavior-preserving cleanup of the DSL-ified attention kernels: - drop redundant parentheses left by the operand-wrapping conversion (e.g. `(a) - ((b) * (c))` -> `a - b * c`), keeping only precedence- required grouping - replace the `X.maximumf(Y)` method form with the `fx.maxnumf(X, Y)` free function (and `.minimumf` -> `fx.minnumf`); maxnumf matches the original flash reduction op and differs from maximumf only on NaN, which softmax max operands never produce Verified behavior-identical by AST equivalence (redundant parens do not appear in the AST; only the exact maximumf->maxnumf transform differs), plus flash gfx942 numerics. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * attention: use top-level fx.* math instead of the fmath alias fmath is just `flydsl.expr.math`, and fx.rsqrt/fx.log/fx.fma/... are the same functions re-exported at top level (fmath is fx.math; fx.rsqrt is fmath.rsqrt). Use the fx.* names for consistency with the rest of the DSL and drop the redundant as_mlir_value on fx.log args (fx.log unwraps its argument internally). Behavior-identical (same function objects); flash gfx942 numerics unchanged. Note: rocdl.exp2/rcp are intentionally kept -- they lower to the bare v_exp/v_rcp hardware instructions, whereas fx.exp2 lowers to an __ocml_exp2_f32 call (slower, range-reduced), so they are not equivalent. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * moe/mxfp: DSL-ify the e8m0 amax bit-extract in the fp4 epilogue The amax exponent extraction used raw arith.bitcast/shrui/shli on _raw-unwrapped DSL operands. Rewrite with DSL ops (bit-exact): - arith.bitcast(T.i32, amax_f) + arith.shrui(.., 16) -> amax_f.bitcast(Uint32) >> 16 (Uint32 so >> emits the unsigned shift, matching shrui) - arith.shli(amax_dpp, 16) -> amax_dpp << 16 - arith.bitcast(T.f32, f32b) -> f32b.bitcast(Float32) - .maximumf() -> fx.maxnumf() for consistency Pure bit manipulation, no fastmath involved; moe a8w4/fp4 numerics pass. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * moe/mxfp: use fx.absf instead of the _fabs_f32 llvm-intrinsic helper _fabs_f32 wrapped a raw llvm.call_intrinsic("llvm.fabs.f32"). fx.absf (math.absf) lowers to the same llvm.fabs.f32 (via llvm.intr.fabs), so replace the helper with fx.absf at all call sites and delete it. Also `.maximumf()` -> fx.maxnumf() in gemm1 for consistency. Pure bit-op abs, behavior-identical; moe a8w4/fp4 numerics pass. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * kernels: DSL-ify remaining bit-exact bitcast/fabs sites Full-scan follow-up. Replace raw ops whose operands are already DSL and whose DSL form lowers to the same instruction (bit-exact / same intrinsic): - mfma_preshuffle: arith.bitcast(T.i32/f32, x) -> x.bitcast(fx.Int32/Float32) - silu_and_mul_fq: llvm.call_intrinsic("llvm.fabs.f32") -> fx.absf; and arith.maximumf -> fx.maxnumf - pa_decode_swa: arith.bitcast(T.i32, weight_local) -> weight_local.bitcast(fx.Int32) Left as-is (raw operands / no equivalent / unvalidatable): rocdl.exp2/rcp (bare v_exp/v_rcp), arith.minsi/maxsi (no DSL int min/max), the shrui on a raw index param, cmpf-result andi, ds_bpermute-result bitcast, and the multi-gpu dispatch bitcasts (raw i64 operand, no local validation path). Validated: test_preshuffle_gemm 58 passed; imports clean. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * moe/2stage: broadcast DSL bf16 scale via fx.Vector.filled extract_bf16_scale now returns a DSL Float32 (correct). The bf16 groupwise accumulator broadcast fed it to the raw vector.broadcast builder, which only takes an ir.Value -> "must be a Value". Use fx.Vector.filled(4, scale_val, fx.Float32) which accepts a DSL scalar and lowers to the same vector.broadcast. Bit-identical; bf16 moe_gemm_2stage passes. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * moe/mma: drop the now-unused arith param from extract_bf16_scale extract_bf16_scale no longer uses the passed-in arith module (its body is DSL << / & / .bitcast now), so remove the parameter and drop it at the three call sites in moe_gemm_2stage gemm1/gemm2. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * mma/preshuffle: fix bitcast on ArithValue operands (w4a16 path) The earlier .bitcast(fx.Int32/Float32) conversions in the w4a16 unpack functions operate on raw ArithValue operands, but ArithValue.bitcast expects an ir.Type (T.i32), not a Numeric class -> "must be a Type (std::bad_cast)" on the int4_bf16 groupwise moe path (not covered by test_preshuffle_gemm). Revert the two unpack sites to arith.bitcast(T.i32, ...) (they run on raw ArithValue with raw downstream). For extract_bf16_scale, keep it DSL by wrapping the raw dword in fx.Uint32 first so Numeric.bitcast applies; its DSL Float32 result is consumed by the fx.Vector.filled scale broadcast. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * moe/2stage: normalize scale_val to fx.Float32 before Vector.filled The bf16 scale broadcast can receive scale_val either as a DSL Float32 (bf16 groupwise via extract_bf16_scale) or as a raw ArithValue (other paths, e.g. gfx950 g32-eager int4_bf16). fx.Vector.filled requires a Numeric fill_value, so wrap scale_val in fx.Float32 first (passthrough for DSL, wraps a raw ArithValue). Fixes the gfx950 int4_bf16 failures. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Co-authored-by: Felix Li <felix.li@amd.com>
1 parent 47009a3 commit daee90e

13 files changed

Lines changed: 241 additions & 339 deletions

kernels/attention/flash_attn_utils.py

Lines changed: 74 additions & 136 deletions
Large diffs are not rendered by default.

kernels/attention/mla_fwd_decode_m16x8_fp8_fp8.py

Lines changed: 30 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@
1919
import flydsl.expr as fx
2020
from flydsl._mlir import ir
2121
from flydsl._mlir.dialects import llvm
22+
from flydsl.compiler.kernel_function import CompilationContext
2223
from flydsl.expr import arith, const_expr, gpu, range_constexpr, rocdl
23-
from flydsl.expr import math as fmath
2424
from flydsl.expr.arith import _to_raw as _raw
2525
from flydsl.expr.typing import T
2626
from flydsl.expr.typing import Vector as Vec
@@ -329,32 +329,10 @@ def kn_mla_fwd_decode_m16x8_fp8_fp8(
329329

330330
# ---- Types ----
331331
fm_fast = arith.FastMathFlags.fast
332-
# fastmath without ninf: safe for operations that may encounter -inf
333-
# (boundary masking sets OOB attention scores to -inf)
334-
fm_no_inf = (
335-
arith.FastMathFlags.nnan
336-
| arith.FastMathFlags.nsz
337-
| arith.FastMathFlags.arcp
338-
| arith.FastMathFlags.contract
339-
| arith.FastMathFlags.afn
340-
| arith.FastMathFlags.reassoc
341-
)
342332

343333
def _mfma_fp8(result_type, operands, **kw):
344334
return rocdl.mfma_f32_16x16x32_fp8_fp8(result_type, operands, **kw)
345335

346-
def _fadd(a, b, fastmath=fm_no_inf):
347-
return arith.addf(_raw(a), _raw(b), fastmath=fastmath)
348-
349-
def _fsub(a, b, fastmath=fm_no_inf):
350-
return arith.subf(_raw(a), _raw(b), fastmath=fastmath)
351-
352-
def _fmul(a, b, fastmath=fm_no_inf):
353-
return arith.mulf(_raw(a), _raw(b), fastmath=fastmath)
354-
355-
def _fmax(a, b, fastmath=fm_no_inf):
356-
return arith.maximumf(_raw(a), _raw(b), fastmath=fastmath)
357-
358336
# ---- LDS setup ----
359337
lds = fx.SharedAllocator().allocate(SharedStorage).peek()
360338
lds_base_idx = ArithValue(_raw(fx.ptrtoint(lds.storage.ptr))).index_cast(T.index)
@@ -757,7 +735,7 @@ def _warp_reduce_max_16(val):
757735
"""Butterfly max reduce across MFMA column groups (strides 32, 16)."""
758736
w = _f32(val)
759737
for sh in [32, 16]:
760-
w = _fmax(w, _shfl_xor_f32(w, sh), fm_no_inf)
738+
w = fx.maxnumf(w, _shfl_xor_f32(w, sh))
761739
return w
762740

763741
def _warp_reduce_add_16(val):
@@ -917,7 +895,7 @@ def _softmax(
917895
# Local max
918896
local_max = scaled[0]
919897
for i in range_constexpr(1, P_VALS_PER_THR):
920-
local_max = _fmax(local_max, scaled[i], fm_no_inf)
898+
local_max = fx.maxnumf(local_max, scaled[i])
921899

922900
# Warp reduce max (within 16-lane groups)
923901
local_max = _warp_reduce_max_16(local_max)
@@ -927,18 +905,18 @@ def _softmax(
927905
new_row_max = local_max
928906
rescale = c_one_f32
929907
else:
930-
new_row_max = _fmax(local_max, row_max_old, fm_no_inf)
908+
new_row_max = fx.maxnumf(local_max, row_max_old)
931909
# rescale = exp2((old_max - new_max) * log2e)
932-
diff = _fsub(row_max_old, new_row_max, fm_no_inf)
933-
rescale = _fast_exp2(_fmul(diff, c_log2e, fm_no_inf))
910+
diff = row_max_old - new_row_max
911+
rescale = _fast_exp2(diff * c_log2e)
934912

935913
# exp(p - max) for each value, and sum
936914
p_exp_vals = [None] * P_VALS_PER_THR
937915
local_sum = c_zero_f32
938916
for i in range_constexpr(P_VALS_PER_THR):
939-
exp_arg = _fmul(_fsub(scaled[i], new_row_max, fm_no_inf), c_log2e, fm_no_inf)
917+
exp_arg = (scaled[i] - new_row_max) * c_log2e
940918
p_exp_vals[i] = _fast_exp2(exp_arg)
941-
local_sum = _fadd(local_sum, p_exp_vals[i], fm_no_inf)
919+
local_sum = local_sum + p_exp_vals[i]
942920

943921
# Warp reduce sum
944922
local_sum = _warp_reduce_add_16(local_sum)
@@ -947,7 +925,7 @@ def _softmax(
947925
if const_expr(is_first_iter):
948926
row_sum_e_new = local_sum
949927
else:
950-
row_sum_e_new = _fadd(_f32(rescale) * row_sum_e_old, local_sum, fm_no_inf)
928+
row_sum_e_new = _f32(rescale) * row_sum_e_old + local_sum
951929

952930
return p_exp_vals, new_row_max, row_sum_e_new, rescale
953931

@@ -1824,8 +1802,8 @@ def _v_base_i32(p_lds_kv_base):
18241802
def _write_lse(pqo_loc_i32, rm, rse):
18251803
"""Write LSE for split output (first 16 lanes per warp)."""
18261804
if ArithValue(lane_idx) < 16:
1827-
log2_sum = fmath.log2(rse, fastmath=fm_fast)
1828-
lse = fmath.fma(log2_sum, c_inv_log2e, rm, fastmath=fm_fast)
1805+
log2_sum = fx.log2(rse, fastmath=fm_fast)
1806+
lse = fx.fma(log2_sum, c_inv_log2e, rm, fastmath=fm_fast)
18291807
row_idx = _raw(ArithValue(lane_idx) + warp_idx * 16 + _idx(pqo_loc_i32) * NUM_QO_HEADS)
18301808
buffer_ops.buffer_store(lse, split_lse_rsrc, row_idx)
18311809

@@ -2078,19 +2056,22 @@ def launch_mla_fwd_decode_m16x8_fp8_fp8(
20782056
):
20792057
"""JIT host function: configures grid/block and launches the kernel."""
20802058
assert TOTAL_LDS_BYTES <= lds_size, f"Kernel requires {TOTAL_LDS_BYTES} bytes LDS but CU budget is {lds_size}"
2081-
kn_mla_fwd_decode_m16x8_fp8_fp8(
2082-
query,
2083-
kv_buffer,
2084-
kv_page_indices,
2085-
work_indptr,
2086-
work_info_set,
2087-
final_output,
2088-
split_output,
2089-
split_lse,
2090-
softmax_scale,
2091-
).launch(
2092-
grid=(num_cus, 1, 1),
2093-
block=(NUM_THREADS, 1, 1),
2094-
smem=0,
2095-
stream=stream,
2096-
)
2059+
# DSL arithmetic (+ - * .maximumf) picks up fastmath from the ambient hint;
2060+
# enable it for the whole traced body so ops emit fastmath<fast>.
2061+
with CompilationContext.compile_hints({"fast_fp_math": True}):
2062+
kn_mla_fwd_decode_m16x8_fp8_fp8(
2063+
query,
2064+
kv_buffer,
2065+
kv_page_indices,
2066+
work_indptr,
2067+
work_info_set,
2068+
final_output,
2069+
split_output,
2070+
split_lse,
2071+
softmax_scale,
2072+
).launch(
2073+
grid=(num_cus, 1, 1),
2074+
block=(NUM_THREADS, 1, 1),
2075+
smem=0,
2076+
stream=stream,
2077+
)

kernels/attention/pa_decode_tile.py

Lines changed: 27 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,9 @@
3232

3333
import flydsl.compiler as flyc
3434
import flydsl.expr as fx
35+
from flydsl.compiler.kernel_function import CompilationContext
3536
from flydsl.compiler.protocol import dsl_size_of
3637
from flydsl.expr import arith, const_expr, gpu, range_constexpr
37-
from flydsl.expr import math as fmath
3838
from flydsl.expr.typing import ReductionOp, T
3939
from flydsl.runtime.device import get_rocm_arch
4040
from kernels.common import buffer_ops, dpp_utils
@@ -397,7 +397,6 @@ def _k_ops_flat(tt_i32):
397397
v_scale_f = fx.Float32(value_scale)
398398
NEG_INF = fx.Float32(float("-inf"))
399399
ZERO_F = fx.Float32(0.0)
400-
fm_contract = arith.FastMathFlags.contract
401400
# Softmax scores are finite or the -inf mask sentinel -- never NaN -- so
402401
# nnan lets maxnum lower to a bare v_max (no v_cmp_u NaN check + its s_nop
403402
# hazard) and fuse to v_max3. (ninf must NOT be set: -inf is load-bearing.)
@@ -452,9 +451,9 @@ def _quant_q_row(m, qi, gs_head, q_row_off):
452451
# (a buffer load is 128b max); head_dim=256 splits into 2 pieces.
453452
q_units = [_q_load_chunk(base_elem + u * QLOAD_UNIT) for u in range_constexpr(N_QLOADS)]
454453

455-
absmax = fmath.absf(q_units[0]).reduce(ReductionOp.MAX).to(fx.Float32)
454+
absmax = fx.absf(q_units[0]).reduce(ReductionOp.MAX).to(fx.Float32)
456455
for u in range_constexpr(1, N_QLOADS):
457-
absmax = fx.maxnumf(absmax, fmath.absf(q_units[u]).reduce(ReductionOp.MAX).to(fx.Float32))
456+
absmax = fx.maxnumf(absmax, fx.absf(q_units[u]).reduce(ReductionOp.MAX).to(fx.Float32))
458457
for sh in (8, 4, 2, 1):
459458
absmax = fx.maxnumf(absmax, dpp_utils.dpp_xor_f32(absmax, sh))
460459

@@ -742,7 +741,7 @@ def _lmax_off_m(m):
742741
p_off0 + a * (c16 // 4) * f32, fx.Int32, fx.Vector.from_elements([words[a]], dtype=fx.Int32)
743742
)
744743
for sh in (16, 32):
745-
ls = ls.addf(ls.shuffle_xor(sh, WAVE), fastmath=fm_contract)
744+
ls = ls + ls.shuffle_xor(sh, WAVE)
746745
# PV output is [head-dim, query-row=lane16] after the operand
747746
# swap, so correction/denominator are per-lane scalars (no sCorr).
748747
safe_prev = arith.select(m_prev > NEG_INF, m_prev, ZERO_F)
@@ -751,9 +750,7 @@ def _lmax_off_m(m):
751750
_st_lw(sLsum_off, lane16, warp, ls)
752751
gpu.barrier()
753752
gsum = _ld_lw_row(sLsum_off, lane16).reduce(ReductionOp.ADD)
754-
l_new = fx.Float32(
755-
arith.mulf(arith.unwrap(l_prev), arith.unwrap(corr_reg), fastmath=fm_contract)
756-
).addf(gsum, fastmath=fm_contract)
753+
l_new = l_prev * corr_reg + gsum
757754

758755
p_ops = _lds_load(sP_off + lane16 * SP_ROW_BYTES + rgroup * 64, fx.Int64, NVOPS)
759756

@@ -879,17 +876,15 @@ def _lmax_off_m(m):
879876
if const_expr(head_dim == 64):
880877
fx.rocdl.sched_dswr(NCHUNK)
881878
for sh in (16, 32):
882-
ls = ls.addf(ls.shuffle_xor(sh, WAVE), fastmath=fm_contract)
879+
ls = ls + ls.shuffle_xor(sh, WAVE)
883880
# PV (V=A, P=B) -> output [head-dim, query-row=lane16]; same as
884881
# the phase-split path.
885882
corr_reg = fx.Float32(exp2_amdgcn_scalar(m_prev - m_new))
886883
if rgroup == 0:
887884
_st_lw(sLsum_off, lane16, warp, ls)
888885
gpu.barrier()
889886
gsum = _ld_lw_row(sLsum_off, lane16).reduce(ReductionOp.ADD)
890-
l_new = fx.Float32(arith.mulf(arith.unwrap(l_prev), arith.unwrap(corr_reg), fastmath=fm_contract)).addf(
891-
gsum, fastmath=fm_contract
892-
)
887+
l_new = l_prev * corr_reg + gsum
893888
p_ops = _lds_load(sP_off + lane16 * SP_ROW_BYTES + rgroup * 64, fx.Int64, NVOPS)
894889
corr_b = fx.Vector.from_elements([corr_reg], dtype=fx.Float32).broadcast_to(OP_ELEMS)
895890
# Single tile: batch both vh's V loads upfront (no sibling chain
@@ -919,13 +914,7 @@ def _lmax_off_m(m):
919914
if const_expr(per_token_kv):
920915
o_scale = inv_l
921916
else:
922-
o_scale = fx.Float32(
923-
arith.mulf(
924-
arith.unwrap(inv_l),
925-
arith.unwrap(v_scale_f * inv_fp8),
926-
fastmath=fm_contract,
927-
)
928-
)
917+
o_scale = inv_l * (v_scale_f * inv_fp8)
929918
o_scale_b = fx.Vector.from_elements([o_scale], dtype=fx.Float32).broadcast_to(OP_ELEMS)
930919
qi_e = row // query_group_size
931920
gs_head_e = row - qi_e * query_group_size
@@ -983,24 +972,25 @@ def pa_decode_tile_launch(
983972
stride_q_head: fx.Int32,
984973
stream: fx.Stream = fx.Stream(None),
985974
):
986-
pa_decode_tile_kernel(
987-
output,
988-
pmax,
989-
psum,
990-
pout,
991-
query,
992-
key_cache,
993-
value_cache,
994-
block_tables,
995-
context_lengths,
996-
key_scale,
997-
value_scale,
998-
max_blocks_per_seq,
999-
stride_ks_block,
1000-
stride_ks_head,
1001-
stride_q_row,
1002-
stride_q_head,
1003-
).launch(grid=(num_seqs, num_kv_heads, NP), block=(BLOCK_THREADS, 1, 1), stream=stream)
975+
with CompilationContext.compile_hints({"fastmath": arith.FastMathFlags.contract}):
976+
pa_decode_tile_kernel(
977+
output,
978+
pmax,
979+
psum,
980+
pout,
981+
query,
982+
key_cache,
983+
value_cache,
984+
block_tables,
985+
context_lengths,
986+
key_scale,
987+
value_scale,
988+
max_blocks_per_seq,
989+
stride_ks_block,
990+
stride_ks_head,
991+
stride_q_row,
992+
stride_q_head,
993+
).launch(grid=(num_seqs, num_kv_heads, NP), block=(BLOCK_THREADS, 1, 1), stream=stream)
1004994

1005995
return {"launch": pa_decode_tile_launch, "kernel": pa_decode_tile_kernel}
1006996

0 commit comments

Comments
 (0)