Port GEMM/MoE/conv kernels to the layout API - #913
Draft
coderfeli wants to merge 5 commits into
Draft
Conversation
Remove buffer_ops; port the epilogue scale_a/scale_b (load_epi_operands) addressing to the layout API. Perf-parity confirmed (median-of-7, within gfx950 noise); cold-correct across fp8/int8/fp16/bf16/fp4/fp6/a8w8 + fused-epilogue modes + ragged-M. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
MMA phase via in-kernel make_tiled_mma; g2s + s2r LDS swizzle expressed as crd2idx over make_composed_layout(SwizzleType) (prologue-hoisted, ISA-identical hot loop). Direct-DMA BufferCopyLDS and split-16@64 pack kept (repo idiom). Scheduler-sensitive paths (interleaved AGPR s2r, StoreC) left manual by design, ISA-verified. fp8_gemm_utils.py untouched. Perf parity, cold both preshuffle modes. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
gemm2 A-LDS read uses make_composed_layout(SwizzleType)+crd2idx (bit-for-bit vs the manual XOR mask), covering all gemm2 variants incl a8w4 e2e stage-2. gemm1 read left manual with ISA evidence: prologue-hoisted crd2idx is op-count-identical yet ~5.5-11% slower from instruction-scheduling sensitivity. Cold 6/6 variants + 228/0 e2e; perf parity (fp4 1280.7, a8w4 828.4). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
im2col gather -> make_buffer_tensor + logical_divide + BufferCopyLDS128b with flat element index and OOB->sentinel padding; BIG_IN (>2GB) paths via make_buffer_ptr(rebased, num_records_bytes). fp8: Mfma16x16x128 -> in-kernel make_mma_atom(MFMA_Scale)+fx.gemm, split-16@64 pack kept. Cold: bf16 26/26; fp8 6/7 (1 case is a pre-existing main bug, not this port). BIG_IN is compile-validated (no >2GB test). Perf no-regression (median-of-7). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
coderfeli
marked this pull request as draft
July 27, 2026 14:58
Cut verbose per-port rationale/ISA-evidence comments (~88 -> ~29 added lines) to terse one-liners; code byte-identical (comments-only). black+ruff clean. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Ports four GEMM / MoE / conv kernel families from manual buffer/byte-offset addressing to the FlyDSL layout API (the
examples/04-preshuffle_gemm.pyidiom:make_buffer_tensor+flat_divide+partition_S/D,make_composed_layout(SwizzleType)for LDS swizzle,make_tiled_mma/fx.gemm,crd2idxfor swizzled offsets). Each port is cold-correct (FLYDSL_RUNTIME_ENABLE_CACHE=0) and perf-neutral (median-of-7 on gfx950, within clock noise).moe_gemm_2stageis intentionally not in this PR (separate WIP).Ports
gemm/preshuffle_gemm.py—buffer_opsremoved; epilogue scale addressing on the layout API. Cold: fp8/int8/fp16/bf16/fp4/fp6/a8w8 + fused-epilogue modes + ragged-M. Perf parity (8192³ fp8 ~2237 TFLOPS, independently re-measured).gemm/fp8_gemm_8wave.py+fp8_gemm_4wave.py— MMA via in-kernelmake_tiled_mma; g2s + s2r LDS swizzle via prologue-hoistedcrd2idxovermake_composed_layout(SwizzleType(3,4,4))(hot-loop ISA identical). Direct-DMABufferCopyLDS+ split-16@64 pack kept (repo idiom).fp8_gemm_utils.pyuntouched.moe/mxfp_moe/gemm2.py— A-LDS read on real layout algebra (make_composed_layout(SwizzleType)+crd2idx, bit-for-bit vs the manual XOR), all gemm2 variants incl. a8w4 e2e stage-2. Cold 6/6 + 228/0 e2e; perf parity (fp4 1280.7, a8w4 828.4 TFLOPS).conv/conv3d_implicit.py+conv3d_implicit_fp8.py— im2col gather viamake_buffer_tensor/logical_divide/BufferCopyLDS128b(flat element index, OOB→sentinel); BIG_IN (>2GB) viamake_buffer_ptr(rebased, num_records_bytes); fp8 MMA via in-kernelmake_mma_atom(MFMA_Scale). Cold: bf16 26/26.Documented "manual by necessity" (kept, with ISA evidence)
A few hot-loop sites are left manual on purpose — the layout-API form is op-count-identical but perturbs the tuned instruction schedule:
mxfp_moegemm1 read: prologue-hoistedcrd2idxis op-identical yet ~5.5% (fp4) / ~11% (fp8) slower (instruction-scheduling sensitivity). Documented in-code.fp8_4waveinterleaved AGPR s2r (~1.3%); direct-DMA op stays inline-asm (no register fragment; matchespreshuffle_gemm.py::dma_a_to_lds); StoreC (final store, needs full wave-decomp, ~0 payoff).Caveats
test_conv3d_implicit_fp8.py [1-96-4-8-9-96-1-1]cold flakiness (C=96 partial-K split-K, rel_err ~0.3075) reproduces onmain.Test plan
🤖 Generated with Claude Code