Skip to content

Phase 8.4.6 — Threadgroup-tiled matmul_softmax_f32 + benchmark harness - #13

Merged
gstoner merged 1 commit into
claude/phase-8-4-4-2-fused-flash-attnfrom
claude/phase-8-4-6-perf-tiling
May 9, 2026
Merged

gstoner merged 1 commit into
claude/phase-8-4-4-2-fused-flash-attnfrom
claude/phase-8-4-6-perf-tiling

Conversation

@gstoner

@gstoner gstoner commented May 9, 2026

Copy link
Copy Markdown
Owner

Summary

Lifts the N <= 256 constraint on the Phase 8.4.3 fused matmul→softmax kernel via a threadgroup-tiled variant that allocates the score buffer in dynamic threadgroup memory. Also adds a benchmark harness comparing fused vs sequential execution paths.

Stacked on PR #12.

Scope cuts (deliberate, called out as followups)

  • Tiling for f16/bf16 — same pattern, just hasn't been replicated yet
  • Tiling for the 3-op fusion — needs both scores[N] AND out[P] in threadgroup memory; slightly different layout
  • MPSGraph baseline comparison in the benchmark — needs separate dependency setup

The point of this PR is to demonstrate the technique on one kernel cleanly. Replicating to the other dtypes/kernels is a 1-PR-each followup.

What changed

MLIR / runtime

  • New native MSL kernel matmul_softmax_tiled_f32:
    • Dynamic threadgroup memory for tg_scores[N] via [[threadgroup(0)]]
    • Two threadgroup float[32] scratch arrays for max + sum
    • Tree reduction (stride/2) — O(log T) latency
    • Cooperative loops n in [lid, N) step THREADS
  • New C symbol tessera_apple_gpu_matmul_softmax_tiled_f32 (same i64×3 + i32×3 ABI as the per-thread variant)
  • Existing tessera_apple_gpu_matmul_softmax_f32 becomes a router: per-thread for N ≤ 256 (no threadgroup overhead), tiled for larger N. Reference fallback for N > 8192.

Python

  • runtime.py: _apple_gpu_dispatch_matmul_softmax lifts the f32 upper bound to 8192. f16/bf16 stay at 256 until tiled variants land.
  • Loader gate updated to require the new tiled symbol.

Benchmarks

  • New benchmarks/apple_gpu/benchmark_fusion.py — JSON-schema-compatible harness comparing fused vs sequential paths across a shape sweep.

Tests

  • 3 new unit tests covering N=512, N=1024, and the small-N fast-path.

Test plan

  • All 2,015 unit tests pass (2,012 → 2,015, +3)
  • 15/15 Phase 8 lit fixtures pass
  • Tiled path matches numpy at rtol=1e-4 for both N=512 and N=1024
  • Benchmark harness runs end-to-end and emits JSON

PR stack

🤖 Generated with Claude Code

Lifts the N <= 256 constraint on the Phase 8.4.3 fused matmul -> softmax
kernel by adding a threadgroup-tiled variant that allocates the score
buffer in dynamic threadgroup memory. One row per threadgroup; 32 threads
cooperate on the K reduction, threadgroup-reduce max + sum, and final
write. Caps at N <= 8192 (typical device threadgroup memory bound).

Also adds a benchmark harness comparing fused vs sequential paths across
representative shapes — first concrete perf-characterization scaffolding
for the apple_gpu MSL kernels.

Scope cuts (followups):
  - Tiling for f16/bf16 variants — same pattern, just hasn't been replicated
  - Tiling for the 3-op fusion (matmul -> softmax -> matmul) — needs both
    `scores[N]` AND `out[P]` in threadgroup memory, slightly different layout
  - MPSGraph baseline comparison in the benchmark — needs a separate setup

MLIR / runtime
- New native MSL kernel matmul_softmax_tiled_f32 with threadgroup memory:
  * `tg_scores` allocated as dynamic threadgroup memory ([[threadgroup(0)]])
  * Two `threadgroup float[32]` scratch arrays for max + sum reductions
  * Cooperative loops over N step THREADS for compute, exp, write
  * Tree reduction (stride/2) for both max and sum to keep latency O(log T)
- New C symbol tessera_apple_gpu_matmul_softmax_tiled_f32 — same i64×3 + i32×3
  ABI as the per-thread variant. Reference fallback for non-Darwin.
- The existing tessera_apple_gpu_matmul_softmax_f32 entry point becomes a
  router: per-thread for N <= 256 (no threadgroup overhead), tiled for
  larger N. Reference fallback still works for N > 8192.

Python
- runtime.py: _apple_gpu_dispatch_matmul_softmax now lifts the f32
  upper bound to 8192. f16/bf16 stay at 256 until tiled variants land.
  Loader gate updated to require the new tiled symbol.
- apple_gpu_runtime_stub.cpp gets matching reference fallback so non-Darwin
  builds export the same C ABI.

Benchmarks
- benchmarks/apple_gpu/benchmark_fusion.py — Python timing harness that
  compares fused matmul_softmax vs sequential per-op pipeline across a
  shape sweep. Outputs JSON in the same schema as benchmark_gemm.py so
  tools/roofline_tools/ can ingest it. Skips on non-Darwin with a clear
  message and exits 0.

Tests
- 3 new unit tests in test_apple_backend_roadmap.py:
  * test_apple_gpu_matmul_softmax_tiled_path_executes_for_large_n —
    end-to-end @jit through tiled at N=512 and N=1024
  * test_apple_gpu_matmul_softmax_tiled_runtime_shim_exposes_symbol —
    direct ctypes ABI test for the new symbol
  * test_apple_gpu_matmul_softmax_small_n_still_uses_per_thread_path —
    pins that the router doesn't accidentally use tiled for small N

Verified on Apple Silicon (LLVM/MLIR 21, Metal active):
  2015 unit tests passing (2012 + 3 net new tiled tests);
  15/15 Phase 8 lit fixtures passing against the in-tree tessera-opt.
  Tiled path matches numpy reference at rtol=1e-4 for both N=512 and
  N=1024. Benchmark harness runs end-to-end and emits JSON.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: bb304eabcc

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Base automatically changed from claude/phase-8-4-5-attn-fusion to claude/phase-8-4-4-2-fused-flash-attn May 9, 2026 12:47
@gstoner
gstoner merged commit 3240682 into claude/phase-8-4-4-2-fused-flash-attn May 9, 2026
0 of 5 checks passed
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