Skip to content

perf(kernels): speed up linear-attention prefill ~2.6x (Q/K LDS tiling + dk-split) - #600

Open
donghanbj wants to merge 2 commits into
mainfrom
perf/optimize-linear-attention-prefill
Open

perf(kernels): speed up linear-attention prefill ~2.6x (Q/K LDS tiling + dk-split)#600
donghanbj wants to merge 2 commits into
mainfrom
perf/optimize-linear-attention-prefill

Conversation

@donghanbj

Copy link
Copy Markdown
Contributor

Summary

Optimizes the gated-delta chunked linear-attention prefill kernel
(linear_attention_prefill_chunked) on gfx1151, which was latency / LDS-bound.
Two combined, orthogonal changes:

  • Q/K LDS tiling + bank-conflict padding — cache the per-chunk K and Q tiles
    in LDS with a +1-float row pad (qk_stride = dk + 1). This removes the 32-way
    LDS bank conflicts (dk=128 is an exact multiple of the 32 banks) and drops the
    repeated global query reads in the P-matrix and output phases.
  • dk-split (HIPDNN_EP_LA_PREFILL_DK_SPLIT, default 4) — g_split lanes
    cooperate on each output column and split the dk reduction of the two dv-wide
    phases (B and output), combining via a warp shuffle (block = g_split*dv). This
    fixes the ~50%-idle-thread underutilization (256 threads vs dv=128 columns) and
    multiplies resident wavefronts to hide the latency-bound state reads. Falls back
    to the per-column path (g_split=1) when a shape can't satisfy the split.

The decode path and everything outside the prefill kernel are unchanged.

Results (gfx1151 / Qwen3.5-35B-A3B, seq=1842)

main this PR
kernel (standalone, best) 25.3 ms 9.7 ms (2.6x)
TTFT (end-to-end, median) ~3608 ms ~2947 ms (-18%)
prefill throughput ~511 tok/s ~625 tok/s (+22%)
decode ~17.2 ms/tok ~17.5 ms/tok (unchanged)

Kernel occupancy 16 waves/SIMD, no scratch spill. Output is numerically identical
in quality: cosine 0.9999996 vs the per-token decode oracle.

Test plan

  • Standalone correctness vs the per-token decode oracle (cosine 0.9999996),
    verified for all g_split in {1, 2, 4, 8}.
  • 1_build.bat: LIT 354/356 pass, plugin-registrar + output-allocator unit
    tests pass.
  • VLM end-to-end (Qwen3.5-35B-A3B), 3x back-to-back vs main in the same
    thermal window: TTFT / prefill improved as above, generated text correct.
  • CI green.

Note: the hand-written GPU kernels under lib/Runtime/Kernels/** are
formatter-exempt per .lintrunner.toml; this PR keeps the existing 4-space
hand style and leaves the decode kernel byte-for-byte unchanged.

…g + dk-split)

The gated-delta chunked prefill kernel (linear_attention_prefill_chunked)
was latency/LDS-bound on gfx1151. Two combined changes:

- Cache the per-chunk K and Q tiles in LDS with a +1-float row pad
  (qk_stride = dk+1) to kill the 32-way LDS bank conflicts and drop the
  repeated global query reads in the P-matrix and output phases.
- dk-split (HIPDNN_EP_LA_PREFILL_DK_SPLIT, default 4): g_split lanes
  cooperate on each output column and split the dk reduction of the two
  dv-wide phases (B and output), combined via warp shuffle
  (block = g_split*dv). Fixes the ~50%-idle-thread underutilization
  (256 threads vs dv=128 columns) and hides the latency-bound S reads.

gfx1151 / Qwen3.5-35B-A3B (seq=1842): kernel 25.3 -> 9.7 ms (2.6x,
standalone, 16 waves/SIMD, no scratch spill); end-to-end TTFT -18%,
prefill throughput +22%, decode unchanged. Output cosine 0.9999996 vs
the per-token decode oracle.

Co-authored-by: Cursor <cursoragent@cursor.com>
@github-actions

Copy link
Copy Markdown

Thanks for opening a PR!

This project follows LLVM's incremental-development and AI-tool-use
guidance. See CONTRIBUTING.md
for the project workflow.

Before requesting review, please check that:

  1. The change is focused. Substantial work links the relevant issue
    or design discussion.
  2. The PR documents relevant test results and updates affected
    documentation.
  3. If AI tools provided substantial assistance, the description
    explains what was assisted and how it was validated, and commit
    trailers identify the tool. The contributor has reviewed and
    understands the result.

Reviewers are assigned through
CODEOWNERS where ownership
is configured.

@github-actions

github-actions Bot commented Jul 30, 2026

Copy link
Copy Markdown

L2 Accuracy Results (EP vs CPU)

Model Combined L2 Total Elems Skipped NaN/Inf
conv_test_hybrid 4.8668E-07 64 0
GroupQueryAttention_seq256 25.2366 2621440 0
MatMulNBits_o_seq128 259.906 368640 0
QMoE_seq128 34.9552 368640 0

Threshold: 0.01 | Run: 3440 - Commit: a5b51e3

@github-actions

github-actions Bot commented Jul 30, 2026

Copy link
Copy Markdown

MorphiZen EP Performance Results

Model QPS Session (s) 1st Infer (ms) CPU% Mem (MB)
full_model_seq128 7.51 6.09 366 3 1245
GroupQueryAttention_seq128 4318.11 1.72982 11 6 310
matmul_down_seq128 517.46 2.33 75 3 352

EPContext Export Performance

Model QPS Session (s) 1st Infer (ms) CPU% Mem (MB)
full_model_seq128 7.55 45.68 360 3 15590

EPContext Import Performance

Model QPS Session (s) 1st Infer (ms) CPU% Mem (MB)
full_model_seq128 7.54 9.61 364 3 15760

OGA Benchmark Results

Model Warmup Reps Prompt Len Gen Tokens TTFT (ms) TPS Peak Mem (GB) GPU Mem (GB)
gpt-oss-20b-webgpu-int4-rtn-block-32 1 5 128 128 177.0 80.8 1.33 13.57
Llama-3.1-8B-awq-g128-int4-asym-fp16-onnx-dml 1 5 128 128 321.7 40.6 1.22 6.43

OGA Wheel Smoke (Python benchmark_e2e.py)

Model TTFT (ms) TPS
Llama-3.1-8B-awq-g128-int4-asym-fp16-onnx-dml 196 39.5

Run: 3440 - Commit: a5b51e3

@donghanbj

Copy link
Copy Markdown
Contributor Author

/run-test models=all

@amd-yanjunz

amd-yanjunz commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

ROCm OGA CI finished with result: UNSTABLE.

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.

2 participants