Skip to content

[Feat] Add MLA Decode kernel - #1644

Open
wch0810 wants to merge 3 commits into
tile-ai:ascendc_ptofrom
wch0810:feat/add_mla_decode_example
Open

[Feat] Add MLA Decode kernel#1644
wch0810 wants to merge 3 commits into
tile-ai:ascendc_ptofrom
wch0810:feat/add_mla_decode_example

Conversation

@wch0810

@wch0810 wch0810 commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

Description

Add MLA Decode (DeepSeek Multi-head Latent Attention Decode) for Ascend NPU, implemented in example_mla_decode.py + test_mla_decode.py based on TileLang Developer mode (pass_configs four-True). Dual-loop structure + persistent grid + KV L1 double-buffer + online softmax (negative-domain min-merge) + tail mask. Single fused kernel computing fused attention score (Q@KV^T + Q_pe@K_pe^T), softmax, and output projection (P@KV).

Layered test suite (20 cases: L0 3 + L1 9 + L2 3 + Boundary 5 incl 1 KNOWN-LIMITATION) + do_bench (end-to-end) + msprof op (kernel-only). 15 robustness asserts (batch/col_indices/actual_seqlen_kv/dim mismatch) + with_compile_retry decorator for intermittent bisheng compiler failures.

Golden Config (B=132, H=128, kv_heads=1, kv_ctx=8192, dim=512, pe_dim=64, fp16)

do_bench (end-to-end, includes host overhead)

Config Latency (us) TFlops Utilization vs GPU Max Diff
B=132, H=128, N=8192, D=512 4116.31 73.169 20.10% 0.76x (slow 1.31x) 1.221e-04
  • 5 warmup + 5 repeat, mean
  • GPU baseline: 3131 us (kernel.get_profiler().do_bench(warmup=500) on GPU source main_no_split)

msprof bottleneck analysis (block 0 representative, 20 cores highly consistent)

Metric Cube (cube0) Vector (vector0)
time 4010.43 us 4012.31 us
aic_cube_ratio (GEMM) 31.57%
aic_mte1_ratio (GM→L1) 34.66%
aic_scalar_mte1_stall 3242.06 us / 81.83%
aiv_vec_ratio (softmax) 31.76%
aiv_scalar_wait_id0 2318.27 us / 57.49%
aiv_scalar_wait_id2 1583.24 us / 39.27%
aic_cube_wait_ratio 87.70%
aic_mte1_wait_ratio 80.34%
L2 read_hit 52.58% 99.99%

Bottleneck root cause: sync-bound (Cube MTE1 stall 81.83% from KV 2.15x duplicate read + L2 read_hit 52.58%, KV 1GB >> L2 192MB) + memory-bound (Vector wait 96.76% waiting for Cube sync via workspace).

Precision (float16, precision-standard.md §4.1)

Level Cases Result matched_ratio max_abs
L0 (blocking) 3 ✅ PASS 0.9999 ~ 1.0000 1.221e-04 ~ 4.883e-04
L1 (blocking) 9 ✅ PASS 0.9966 ~ 1.0000 6.104e-05 ~ 7.812e-03
L2 (non-blocking) 3 ✅ PASS (rejected)
Boundary (non-blocking) 4 ✅ PASS 0.9999 ~ 1.0000 0 ~ 2.441e-04
  • Thresholds: atol=2⁻¹⁴ (6.10e-5), rtol=2⁻⁹ (1.95e-3), max_abs_limit=1e-1, required_ratio=0.99
  • Dual-gate AND: matched_ratio ≥ 0.99 AND max_abs ≤ 1e-1
  • INF/NAN structural compare: positions must match, not counted in numeric tolerance

…sserts, and msprof profiling

- Developer mode (pass_configs 4x True: AUTO_CV_COMBINE/SYNC/AUTO_SYNC/MEMORY_PLANNING)
- Dual-loop + persistent grid + KV L1 double-buffer
- Online softmax with negative-domain min-merge + tail mask
- Layered test suite: L0 (3) + L1 (9) + L2 (3) + Boundary (5, incl 1 KNOWN-LIMITATION)
- Mixed tolerance precision check (fp16 atol=2^-14, rtol=2^-9, max_abs=1e-1, ratio=0.99)
- 15 robustness asserts (batch/col_indices/actual_seqlen_kv/dim mismatch)
- with_compile_retry decorator for intermittent bisheng compiler failures
- msprof op support (--level msprof, kernel-only Task Duration)
- do_bench support (--level bench, 5 warmup + 5 repeat)
- Precision: 20/20 PASS (19 PASS + 1 KNOWN-LIMITATION for fp16 max overflow)
- Performance: 3764 us (msprof kernel-only), gap 1.25x vs 3036 us GPU target
- Zero T.barrier_all / T.sync_grid / T.Scope / set_flag / wait_flag
@github-actions

Copy link
Copy Markdown

👋 Hi! Thank you for contributing to the TileLang project.

Please remember to run bash format.sh in the root directory of the project to ensure your changes are properly linted and formatted. This will help ensure your contribution passes the format check.

We appreciate you taking this step! Our team will review your contribution, and we look forward to your awesome work!

🚀

…(GPU baseline)

The golden config is batch=132 (matching l0_perf_target), and the GPU
baseline is 3131 us (kernel.get_profiler().do_bench(warmup=500) on GPU
source main_no_split). Previous values batch=128 and target=3036 were
incorrect and caused all bench runs to use the wrong config.

Verified with batch=132:
- Precision: 20/20 PASS (L0 3/3 + L1 9/9 + L2 3/3 + Boundary 5 incl 1 KNOWN-LIMITATION)
- do_bench: 4116.31 us (gap 1.31x vs 3131 us)
- msprof kernel-only: 4028.94 us (block 0 Task Duration)
- ruff format/check: passed
@wch0810 wch0810 changed the title [Example] Add MLA Decode kernel with layered test suite, robustness a… [Feat] Add MLA Decode kernel Aug 21, 2026
@wch0810

wch0810 commented Aug 21, 2026

Copy link
Copy Markdown
Contributor Author

/re-test

@github-actions

Copy link
Copy Markdown

🔄 Re-running failed jobs

Original workflow run: View details

Only the failed jobs will be re-executed.

…sion-only test

- example_mla_decode.py: keep only kernel + 1 CI smoke case (inline golden)
- test_mla_decode.py: own ref_mla_decode golden, precision tests only (L0/L1/L2/Boundary)
- Remove bench/msprof from test file (perf testing handled separately)
- All comments in English
- Verified: smoke 'Test Passed!' + --level all 20/20 PASS (19 PASS + 1 KNOWN-LIMITATION)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant