Repository navigation
feat(rocke): gfx1250 fp8 GEMM bring-up and K-loop optimization (AICK-2347) - #14707
Conversation
✅ All Checks Passed — Ready for Review
📖 Need help? See the Policy FAQ for details on every check and how to fix failures. |
Pre-commit check failed⛔ pre-commit failed Please run locally:
This repo uses |
|
🎉 All checks passed! This PR is ready for review. |
There was a problem hiding this comment.
🟡 Changes recommended
Unsafe inbounds address calculations, an unversioned public ABI change, and verification that accepts NaN outputs leave critical correctness and compatibility defects unresolved.
14 open issues
Use non-inbounds GEP for zero-extent TDM fills · New Bump binary ABI versions for struct layout changes · New Avoid inbounds GEP for clipped TDM fills · New Select an architecture-matching FP8 encoder · New Treat NaN outputs as verification mismatches · New Update parity parser for designated initializers · New Exclude source-only parity test from installed cohort · New Pass gfx1250 target to global-load lowering tests · New Fix sibling import under importlib mode · New Fix test sibling import under importlib mode · New Fix split-barrier sibling import · New Update homogeneous FP8 catalog shape expectations · New Use packaged sweep module in installed tests · New Add C++ HIP lowering for the dense MMA atom · New
What changed in this PR
Extends rocKE’s dual Python/C++ GEMM infrastructure for gfx1250 fp8/bf8 operands, adding dense WMMA support, TDM trait plumbing, and verification and tuning coverage.
Changes:
- Adds the dense K=128 FP8 WMMA atom, lane maps, catalog entries, and lowering support.
- Updates mixed-width manifests, vector loads, LDS alignment, and TDM/K-loop interfaces.
- Adds host regressions, engine-parity checks, sweep configurations, and reproducible input data.
Review validation included source inspection and a dependency-free NaN-check reproduction; project builds and tests were not run.
| File | Description |
|---|---|
| dnn-providers/hip-kernel-provider/rocke/platform/tests/test_sweep_machine_state_flush.py | Updated as part of this pull request. |
| dnn-providers/hip-kernel-provider/rocke/platform/tests/test_sweep_elf_meta.py | Updated as part of this pull request. |
| dnn-providers/hip-kernel-provider/rocke/platform/tests/test_sweep_build_pool.py | Updated as part of this pull request. |
| dnn-providers/hip-kernel-provider/rocke/platform/tests/test_memory_probe.py | Updated as part of this pull request. |
| dnn-providers/hip-kernel-provider/rocke/platform/tests/test_manifest_runner_registry.py | Updated as part of this pull request. |
| dnn-providers/hip-kernel-provider/rocke/platform/tests/test_fp8_trait_ab.py | Updated as part of this pull request. |
| dnn-providers/hip-kernel-provider/rocke/platform/tests/test_clock_probe.py | Updated as part of this pull request. |
| dnn-providers/hip-kernel-provider/rocke/platform/tests/instances/test_universal_gemm_verify.py | Updated as part of this pull request. |
| dnn-providers/hip-kernel-provider/rocke/platform/tests/instances/test_rocke_multiarch.py | Updated as part of this pull request. |
| dnn-providers/hip-kernel-provider/rocke/platform/tests/instances/test_gemm_tdm_traits_cpp_engine.py | Updated as part of this pull request. |
| dnn-providers/hip-kernel-provider/rocke/platform/tests/instances/test_gemm_tdm_ring_parity.py | Updated as part of this pull request. |
| dnn-providers/hip-kernel-provider/rocke/platform/tests/instances/test_gemm_tdm_early_refill.py | Updated as part of this pull request. |
| dnn-providers/hip-kernel-provider/rocke/platform/tests/instances/test_gemm_tdm_alternate_issuers.py | Updated as part of this pull request. |
| dnn-providers/hip-kernel-provider/rocke/platform/tests/instances/test_gemm_split_barrier.py | Updated as part of this pull request. |
| dnn-providers/hip-kernel-provider/rocke/platform/tests/instances/test_gemm_lds_budget_pad.py | Updated as part of this pull request. |
| dnn-providers/hip-kernel-provider/rocke/platform/tests/instances/parity/gfx1250_lowering_emit.py | Updated as part of this pull request. |
| dnn-providers/hip-kernel-provider/rocke/platform/tests/instances/parity/gfx1250_lowering_emit.c | Updated as part of this pull request. |
| dnn-providers/hip-kernel-provider/rocke/platform/tests/core/test_tensor_view_load_vec_dtypes.py | Updated as part of this pull request. |
| dnn-providers/hip-kernel-provider/rocke/platform/tests/core/test_tdm.py | Updated as part of this pull request. |
| dnn-providers/hip-kernel-provider/rocke/platform/tests/core/test_mma_catalog_lookup.cpp | Updated as part of this pull request. |
| dnn-providers/hip-kernel-provider/rocke/platform/tests/core/test_arch_table_engine_parity.py | Updated as part of this pull request. |
| dnn-providers/hip-kernel-provider/rocke/platform/tests/core/test_arch_mma_ssot.py | Updated as part of this pull request. |
| dnn-providers/hip-kernel-provider/rocke/platform/tests/CMakeLists.txt | Updated as part of this pull request. |
| dnn-providers/hip-kernel-provider/rocke/platform/python/rocke/run_manifest.py | Updated as part of this pull request. |
| dnn-providers/hip-kernel-provider/rocke/platform/python/rocke/instances/common/manifest_runner/gemm.py | Updated as part of this pull request. |
| dnn-providers/hip-kernel-provider/rocke/platform/python/rocke/helpers/tensor_view.py | Updated as part of this pull request. |
| dnn-providers/hip-kernel-provider/rocke/platform/python/rocke/helpers/manifest.py | Updated as part of this pull request. |
| dnn-providers/hip-kernel-provider/rocke/platform/python/rocke/examples/gfx1250/gemm_perf_fp8/fp8_data.py | Updated as part of this pull request. |
| dnn-providers/hip-kernel-provider/rocke/platform/python/rocke/examples/gfx1250/gemm_perf_fp8/configs/sq4k.json | Updated as part of this pull request. |
| dnn-providers/hip-kernel-provider/rocke/platform/python/rocke/examples/gfx1250/gemm_perf_fp8/configs/skinny.json | Updated as part of this pull request. |
| dnn-providers/hip-kernel-provider/rocke/platform/python/rocke/examples/gfx1250/gemm_perf_fp8/configs/_base.json | Updated as part of this pull request. |
| dnn-providers/hip-kernel-provider/rocke/platform/python/rocke/examples/gfx1250/gemm_perf_fp8/__init__.py | Updated as part of this pull request. |
| dnn-providers/hip-kernel-provider/rocke/platform/python/rocke/examples/common/universal_gemm_verify.py | Updated as part of this pull request. |
| dnn-providers/hip-kernel-provider/rocke/platform/python/rocke/core/lower_llvm.py | Updated as part of this pull request. |
| dnn-providers/hip-kernel-provider/rocke/platform/python/rocke/core/lower_hip.py | Updated as part of this pull request. |
| dnn-providers/hip-kernel-provider/rocke/platform/python/rocke/core/isa/backend.py | Updated as part of this pull request. |
| dnn-providers/hip-kernel-provider/rocke/platform/python/rocke/core/ir.py | Updated as part of this pull request. |
| dnn-providers/hip-kernel-provider/rocke/platform/python/rocke/core/backend.py | Updated as part of this pull request. |
| dnn-providers/hip-kernel-provider/rocke/platform/python/rocke/core/arch/target.py | Updated as part of this pull request. |
| dnn-providers/hip-kernel-provider/rocke/platform/python/rocke/core/arch/data/arch_specs.json | Updated as part of this pull request. |
| dnn-providers/hip-kernel-provider/rocke/platform/cpp/instances/common/moe_gemm_fused.cpp | Updated as part of this pull request. |
| dnn-providers/hip-kernel-provider/rocke/platform/cpp/instances/common/gemm_mma.cpp | Updated as part of this pull request. |
| dnn-providers/hip-kernel-provider/rocke/platform/cpp/instances/common/conv_implicit_gemm_conv_load_phase.cpp | Updated as part of this pull request. |
| dnn-providers/hip-kernel-provider/rocke/platform/cpp/include/rocke/tdm.h | Updated as part of this pull request. |
| dnn-providers/hip-kernel-provider/rocke/platform/cpp/include/rocke/isa_backend.h | Updated as part of this pull request. |
| dnn-providers/hip-kernel-provider/rocke/platform/cpp/include/rocke/ir.h | Updated as part of this pull request. |
| dnn-providers/hip-kernel-provider/rocke/platform/cpp/include/rocke/ir_internal.h | Updated as part of this pull request. |
| dnn-providers/hip-kernel-provider/rocke/platform/cpp/include/rocke/instance_gemm_universal.h | Updated as part of this pull request. |
| dnn-providers/hip-kernel-provider/rocke/platform/cpp/include/rocke/instance_gemm_internal.h | Updated as part of this pull request. |
| dnn-providers/hip-kernel-provider/rocke/platform/cpp/include/rocke/helper_rocke.helpers.spec.h | Updated as part of this pull request. |
| dnn-providers/hip-kernel-provider/rocke/platform/cpp/helpers/tensor_view.cpp | Updated as part of this pull request. |
| dnn-providers/hip-kernel-provider/rocke/platform/cpp/core/lower_llvm/mma.cpp | Updated as part of this pull request. |
| dnn-providers/hip-kernel-provider/rocke/platform/cpp/core/lower_llvm/mem.cpp | Updated as part of this pull request. |
| dnn-providers/hip-kernel-provider/rocke/platform/cpp/core/lower_llvm/data.cpp | Updated as part of this pull request. |
| dnn-providers/hip-kernel-provider/rocke/platform/cpp/core/lower_hip/lower_hip_mem.cpp | Updated as part of this pull request. |
| dnn-providers/hip-kernel-provider/rocke/platform/cpp/core/isa/backend.cpp | Updated as part of this pull request. |
| dnn-providers/hip-kernel-provider/rocke/platform/cpp/core/ir/ir_tile.cpp | Updated as part of this pull request. |
| dnn-providers/hip-kernel-provider/rocke/platform/cpp/core/ir/ir_flow.cpp | Updated as part of this pull request. |
| dnn-providers/hip-kernel-provider/rocke/platform/cpp/core/ir/core_types.cpp | Updated as part of this pull request. |
| dnn-providers/hip-kernel-provider/rocke/platform/cpp/core/ir/core_builder.cpp | Updated as part of this pull request. |
| dnn-providers/hip-kernel-provider/rocke/platform/cpp/core/arch/data.cpp | Updated as part of this pull request. |
| dnn-providers/hip-kernel-provider/rocke/platform/cpp/bindings/rocke_engine.cpp | Updated as part of this pull request. |
Review effort: Max
|
Addressed all 14 review items in 9d779dc, 3426581, dd02210 and 9a1e498 (replies on each thread). Byte-identity gate GREEN (88 families), ctest -L unit 34/34, and the touched test files pass standalone. One item is resolved by narrowing scope rather than as suggested: fp8/bf8 GEMM is now gfx1250-only (#4). |
|
Automated review: Model - qwen3.6:35b-a3b-coding-mtp-q4_K_M, effort: max PR #14707 — gfx1250 fp8 GEMM bring-up and K-loop optimization (jefyang1, AICK-2347) — 🔴 First-round: blocking — the LDS-alignment fix changes 8 develop fp8 configs without a re-bless, so CI's differential golden will fail at all four flavors (N1), and the case study puts device clock values into public history (N2); all 14 Copilot threads are addressed
Utility: 🟢 Positive — gfx1250 fp8 GEMM with TDM in both engines; re-bless, drop clock values. Legend: 🔴 blocking · 🟠 should-fix · 🟡 minor nit · 🟢 info/good · ⚪ retracted First-round review: a local qwen3.6 model made the independent first pass, and the orchestrator (Claude Opus 5.5) verified it. On a clean merge with develop, it ran the native build and ctest, byte identity, both golden gates, ROCm clang 24 compiles of four families and the PR's 27 test files. It re-ran the differential golden for the two failing families on develop, the merge and the head, diffed their IR and gfx950 ISA, and tested the re-bless on a scratch copy of the golden. It traced the 28 test failures to the pinned LLVM flavor with single-config lowerings and two single-file runs at COMGR's flavor. It checked each Copilot fix at head, compared the public headers with develop, simulated a merge with #14616's head, scanned the added docs and all commit messages, and read the CI jobs and the emulation log at head. The orchestrator owns this merge-worthiness call. It flags whether a closer look is needed; it is not an approval or a rejection. |
|
Automated review: Model - qwen3.6:35b-a3b-coding-mtp-q4_K_M, effort: max PR #14707 — gfx1250 fp8 GEMM bring-up and K-loop optimization (jefyang1, AICK-2347) — 🔴 Follow-up: the re-bless fixes our N1, and CI's differential golden now passes at this head; but 33 earlier commits still carry the device clock values, so this must land by squash or after a branch rewrite (N2); N3 is down to one llvm22-only test
Net-new: none. Utility: 🟢 Positive — gfx1250 fp8 GEMM with TDM in both engines; land it by squash. Legend: 🔴 blocking · 🟠 should-fix · 🟡 minor nit · 🟢 info/good · ⚪ retracted Follow-up review: a local qwen3.6 model made the independent first pass, and the orchestrator (Claude Opus 5.5) verified it. The orchestrator compared the new commit with our first-round head file by file. It diffed the differential golden key by key, against both the previous golden and our first-round scratch re-bless. It searched every commit, commit message and changed file in the PR range for the removed device values. On a clean merge with develop, it ran the native build and ctest, byte identity, both golden gates, compile checks of four families and the PR's 27 test files, then re-ran the failing test file on its own. It simulated a merge of #14616's head with |
|
Automated review: Model - qwen3.6:35b-a3b-coding-mtp-q4_K_M, effort: max PR #14707 — gfx1250 fp8 GEMM bring-up and K-loop optimization (jefyang1, AICK-2347) — 🔴 Follow-up (CI update): both Windows shards fail the PR's new
|
| Prior item | Status |
|---|---|
| Ours (10-30, the follow-up above): N2 🔴 device clock values in 33 earlier commits; N3 🟡 one llvm22-only test; ABI note 🟡 | Unchanged: no push since aa422f14 |
| Bots / CI | 🔴 At aa422f14, both Windows gfx110X hipkernelprovider shards fail rocke_pytest (103 of 104 CTests pass), and the required Multi-Arch CI Summary fails. On both shards the only failures are the three TestSweepBuildPool tests. Both Linux gfx94X shards pass (read: logs) |
| # | Sev | file:line | Finding |
|---|---|---|---|
| N4 | 🔴 | platform/tests/test_sweep_build_pool.py:56 |
The new test (42173df4) asks for mp.get_context("fork"), which Windows does not have: all three tests stop with ValueError: cannot find context for 'fork' on both gfx110X shards (read: logs). The test needs fork by design: the pool's workers must inherit the patched _build_one, and _fake_build kills its worker with signal.SIGKILL, which Windows lacks too. The sweep itself is unchanged in this respect: develop's sweep.py already uses a fork context (read) → skip the class where fork is unavailable, e.g. @unittest.skipUnless("fork" in mp.get_all_start_methods(), "needs the fork start method") |
Utility: 🟢 Positive — unchanged; land it by squash once N2 and N4 are done.
Legend: 🔴 blocking · 🟠 should-fix · 🟡 minor nit · 🟢 info/good · ⚪ retracted
CI update to the follow-up above: once the Windows shards finished, the orchestrator (Claude Opus 5.5) read both gfx110X hipkernelprovider shard logs at aa422f14, and the new test and sweep.py at head and on develop. The orchestrator owns this merge-worthiness call. This review flags whether a closer look is needed; it is not an approval or a rejection.
aa422f1 to
5cc3f5e
Compare
|
I reviewed this PR again. The following review threads are still unresolved, or comments have no author reply:
If you have already fixed these, please reply on each comment to say so and resolve the threads. |
|
Automated review: Model - qwen3.6:35b-a3b-coding-mtp-q4_K_M, effort: max PR #14707 — gfx1250 fp8 GEMM bring-up and K-loop optimization (jefyang1, AICK-2347) — 🟡 Follow-up: squash fixes N2–N4; CI running
Net-new: none. Utility: 🟢 Positive — gfx1250 fp8 GEMM with TDM and K-loop traits in both engines. Legend: 🔴 blocking · 🟠 should-fix · 🟡 minor nit · 🟢 info/good · ⚪ retracted Follow-up review: first pass by a local qwen3.6 model, verified by the orchestrator (Claude Opus 5.5). Checks: PR patch vs our last head, merge with develop, build + ctest, byte identity, goldens, 27 test files, compile, lane merge-tree, CI at head. Flags whether a closer look is needed; not an approval or rejection. |
Thanks — all addressed, now in the squashed commit 5cc3f5e: N1: the differential golden is re-recorded for moe_fused_mega_fp8[0..5] and gfx950_attention_tiled_2d[27], [31] only; --check-golden is OK in ll mode at llvm20/22/23/24 and in canonical mode. |
Both remaining items are done in 5cc3f5e: N2: the branch is squashed to a single commit on top of develop, so the history no longer contains the values, whichever merge method is used. |
N4 is fixed in 5cc3f5e: TestSweepBuildPool is skipped unless fork is in mp.get_all_start_methods(), so the Windows shards skip it, and Linux still runs all 3 tests. |
|
Thanks for the re-check on 5cc3f5e. I've replied on the three earlier reviews. The ABI merge order stays as noted: whichever of this PR and #14616 / #14706 lands second will bump ROCKE_ABI_VERSION and BINARY_ABI to the next free number and re-record gfx950_attention_tiled_2d. |
…a split barrier (#14466) JIRA ID : AICK-2347 ## Summary A fast fp8 GEMM for gfx1250 in CK Tile. This PR adds `comp_tdm_v3`, an opt-in GEMM pipeline: a 16-wave tile fed by the Tensor Data Mover (TDM), with the per-tile workgroup barrier split into arrive and wait so the WMMAs overlap the wait. At the lead shape, 4096 x 4096 x 65536 (RCR, fp8 e4m3 in, fp32 accumulate, bf16 out), it matches the fastest known gfx1250 fp8 GEMM. Everything is opt-in: existing kernels compile byte-for-byte the same. ## What's new - **`comp_tdm_v3` pipeline** (gemm): 16 waves with a waves-aware register budget; one split barrier per K tile, with B held in registers and A streamed per row slice; the A row windows built outside the K loop; TENSORcnt drained on exit. The joint barrier stays available (`kUseSplitBarrier = false`), and an early-refill policy (`RefillPoint::AfterArrive`) is available opt-in; it brings no gain at the lead shape, so it is off by default. - **Split workgroup barrier** (core): fenced, pinned `workgroup_barrier_arrive` / `_wait`. - **tile_engine**: `comp_tdm_v3` registered for `gemm_universal` (`COMPUTE_TDM_V3`, `[4,4,1]` and CShuffle for this pipeline), the fp8/bf8 32x32x128 warp tile on gfx1250, opt-in bf16 C for fp8/bf8, `-init 3` (normal) and `-init 4` (integers), and `-verify_exact`. Its targets build with the post-RA scheduler. - **Example** `53_gemm_comp_tdm_v3_fp8`: a timed benchmark and verifier for the lead shape. ## Performance Ratio to the fastest known gfx1250 fp8 GEMM at the lead shape (the rocKE kernel of rocKE PR #14707, with the split barrier and alternating TDM issuers), random data, builds interleaved sample by sample in one session on one gfx1250 host: | | Peak | Sustained | |---|---|---| | `comp_tdm_v3`, default policy | 1.008x | 1.001x | Differences of about 1% or less are within session noise, so this is parity. Every timed build was bit-exact at 2048³ and passed integer and random checks at the lead shape first. ## Scope of `comp_tdm_v3` Supported and tested: - fp8 or bf8 A and B, including mixed fp8 x bf8; bf16 C; - A row-major, B column-major, C row-major (RCR); - 16 waves (256x256x256) and 4 waves (128x128x256), warp tile 32x32x128; - the plain GEMM kernel with the CShuffle epilogue; - `k_batch = 1`. Rejected: - **Split-K.** `IsSupportedArgument` rejects `k_batch != 1`. - **Non-RCR layouts.** The pipeline has a `static_assert`, and tile_engine rejects them. The other A/B layouts spill VGPRs in the K loop at the 16-wave tile. - **Other kernels.** The multi-D, grouped and batched-contraction kernels have a `static_assert` against the pipeline's new `kPlainGemmOnly` marker. - **tile_engine.** It offers the pipeline for fp8/bf8 and `gemm_universal` only. Not in scope: bf16/fp16 A/B (they compile but are not tested), LDS padding, other C types, MX GEMM and group quant. `comp_tdm_v2` remains the TDM path for MX GEMM and group quant. ## Default behaviour changes - The new pipeline and every tile_engine rule are opt-in. No default or CI config lists `comp_tdm_v3`. - Existing kernels are byte-identical before and after this PR (gfx1250, plus gfx942 and gfx950 cases), on TheRock 10.1.0 and 10.2.0. - **One host-side change.** `UniversalGemmKernel::IsSupportedArgument` used to return `true` for every TDM pipeline right after the general k_batch checks. It now returns `IsTdmArgumentSupported(...)`, the check the multi-D, grouped, batched-contraction and MX kernels already apply: `k_batch == 1`, `K > 0`, element-aligned A/B/E. - For comp_tdm / comp_tdm_v2 / comp_tdm_pc in the plain GEMM kernel, split-K was rejected only for fp16/bf16 C. With fp32 C, k_batch > 1 passed the generic split-K check, although the TDM epilogue's tensor store overwrites the output tile; it is now rejected. A/B/E pointers must also be element-aligned, which TDM addressing requires. No test used k_batch != 1 or misaligned pointers with a TDM pipeline. - Device code is unchanged: on ROCm 10.1.0, the device ISA is identical for 235 kernels (the TDM tests, compv3 and example 53). ## Testing On TheRock 10.1.0 (CK CI compiler) and 10.2.0, gfx1250 under the rocJITsu emulator; no hardware CI exists for gfx1250 yet: - gtests for the split barrier and `comp_tdm_v3` (both barrier forms, 4x4 and 2x2 wave maps, alternating and fixed issuers, long K), bit-exact. - The example at 256 x 256 x {1024, 65536} and odd K-tile counts: bit-exact on integers, within tolerance on random data. - ISA checks: 0 in-loop scratch, VGPRs <= 256, the expected barrier and wait placement; 13 of 13 planted sync bugs caught. - Other GPU targets still parse the headers (gfx942, gfx950, gfx1201). On gfx1250 hardware, at the head of this PR: - `comp_tdm_v3` gtests: 55 of 55 short and 16 of 16 long-K passed, including bf8, mixed fp8/bf8 and the split-K rejection check. - The scratch-use check passed: 9 kernels, no scratch, no VGPR spills. Compile-only checks (ROCm 10.1.0, gfx1250): - `comp_tdm_v3` with RRR, CRR, CCR and RCC each fails on the layout `static_assert`; RCR compiles. - `comp_tdm_v3` in the multi-D, grouped and batched-contraction kernels each fails on the `kPlainGemmOnly` `static_assert`; the plain GEMM kernel compiles. - The existing multi-D, grouped and batched-contraction TDM gtests still compile, and the `comp_tdm_v3` gtests build with `-Werror -Weverything`. ## Notes - **Merge.** Squash and merge, per rocm-libraries convention. The commits form a reviewable stack; each message has a `Gate:` paragraph with its evidence. - **Not in this PR.** Dispatcher registration of `comp_tdm_v3` (and bf16 C for fp8 there) conflicts with open #13975; it follows after #13975 lands. - **Credit.** The split-barrier K-loop, the B-resident / A-streamed order and the post-RA scheduler finding are Jeffrey Yang's, from the rocKE gfx1250 fp8 GEMM (rocKE PR #14707). He co-authored several commits and authored the scope gates. ## Submission Checklist - [x] Look over the contributing guidelines at https://github.com/ROCm/TheRock/blob/main/GOVERNANCE.md#pull-requests. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Co-authored-by: Jeffrey Yang <jeffreyj.yang@amd.com> Co-authored-by: Illia Silin <Illia.Silin@amd.com> Co-authored-by: Illia Silin <98187287+illsilin@users.noreply.github.com>
…2347) Bring up the universal GEMM for 8-bit floats on gfx1250 in both engines, fed by the Tensor Data Mover (TDM), and optimise its K-loop with three opt-in traits. Inputs are fp8 x fp8 or bf8 x bf8 with a bf16 or fp16 C; fp8 runs on the 16x16x64 and the dense 16x16x128 f8f6f4 WMMA atoms, bf8 on the 16x16x64 atom. Every new trait defaults off, and the Python and C++ engines emit byte-identical LLVM IR throughout. fp8 GEMM on gfx1250 - fp8e4m3/bf8e5m2 A/B with a 16-bit C; _validate_storage splits the A/B dtype from the C dtype. fp8/bf8 A/B is accepted on gfx1250 only. - Lane maps for the K=64 fp8 atom; the dense 16x16x128 f8f6f4 atom, with both matrix formats pinned to FP8, lowered to LLVM in both engines and to HIP. - Global A/B loads use the operand's element size, so 1-byte operands get full 16-byte loads; TraitSpec.ab_load_elem_bytes overrides it for A/B comparison. - The cshuffle epilogue on the WMMA path, its staging tile typed by the C dtype. - bf8 verification encodes e5m2 inputs; the manifest runner verifies fp16 C and counts NaN outputs as mismatches. TDM in the universal GEMM - A 2D TDM descriptor builder in both engines (core/tdm.py, cpp/core/tdm.cpp, C ABI rocke/tdm.h), cross-checked field by field against the hardware layout. - tile.global_addr_of: a global address as an i64, without an inbounds GEP, so it stays defined past the end of the buffer. Appended to rocke_opcode_t. - TraitSpec.tdm / tdm_depth: 1 unpipelined, 2 ping-pong, 3+ a modular ring. K-loop traits (depth-2 TDM ping-pong) - split_barrier: the per-tile barrier split into signal and wait; the ring takes the same split. - tdm_alternate_issuers: each LDS half gets its own issuer wave pair. - tdm_early_refill: refill a half as soon as every wave has read it. Correctness fixes - LDS vector alignment is bounded by the row stride; 8-bit floats count as one byte in the LDS element map. This lowers the align of 8-bit LDS loads in moe_fused_mega_fp8[0..5] and gfx950_attention_tiled_2d[27], [31] (ISA unchanged); the differential golden is re-recorded for those families. - The LDS budget charges lds_k_pad on every row and aliases the cshuffle C tile onto the A/B pool. - The TDM ring slot parity is restored on the WMMA read path. - Four is_valid_spec gaps against upstream are closed, e.g. lds_swizzle is rejected on the WMMA path. C ABI: ROCKE_ABI_VERSION and BINARY_ABI 5 -> 6 - rocke_gemm_trait_spec_t gains tdm, tdm_depth, ab_load_elem_bytes and its _set flag, split_barrier, tdm_alternate_issuers and tdm_early_refill, which changes the layout of every GEMM spec that embeds it. Sweep harness and case study (python/rocke/examples/gfx1250/gemm_perf_fp8/) - A staged geometry and trait sweep: one inheritable traits config section, a margin-based finalist cut, machine state per run, ELF metadata on any arch; a build worker that dies no longer hangs the pool. - fp8_trait_ab.py (interleaved, verified trait A/B), wmma_roofline_probe.py (data-matched WMMA ceiling), memory_probe.py (bandwidth and TDM feed) and clock_probe.py (in-kernel clock and device health check). - gemm_perf_fp8_case_study.md and the README record the method and results. Tests - gemm_emit parity configs 13-31 and three TDM descriptor configs in gfx1250_lowering_emit; C++ unit tests rocke_test_tdm and rocke_dense_f8f6f4_hip; opcode and arch-catalog pins updated. - Python tests for TDM, the f8f6f4 atom, the traits, the probes and the sweep. TDM tests pin or require llvm23+; fork-dependent tests skip without fork. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
5cc3f5e to
d10c730
Compare
|
I reviewed this PR again. The following review threads are still unresolved, or comments have no author reply: For reassessment, the PR author should reply to top-level feedback or state that thread feedback is addressed. Before approval, top-level comments need explicit resolution from their author or that author's approval of the PR. |
Conflicts: the opcode enum and the ABI version. develop's #14448 appended tile.gpu_check_failed as opcode 230 and took binary ABI 10. Both stay as develop has them; this branch's tile.global_addr_of follows as opcode 231 (enum, the two opcode tables and test_opcode_values), and its rocke_gemm_trait_spec_t change becomes ABI 11 (ROCKE_ABI_VERSION and BINARY_ABI together).
…ments The parity test compared the binding's reads with the dict's keys, but the dict's top-level keys (name, wave_size, block_size, dtype, batch_size ...) are written by hand, so a new top-level spec field would be missing from both sides of the comparison. It now also checks that each dict carries every field of its spec, nested and top-level. It also strips C/C++ comments from the binding before looking for reads, so a commented-out read is reported as missing. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
N11: agreed. This PR keeps the The two code-quality notes on the parity test ( Merged develop ( Checks on the merge: build + ctest 61/61 (1 skip, arch-domain reproducibility), |
Thank you, replied. |
|
Automated review: Model - qwen3.6:35b-a3b-coding-mtp-q4_K_M, effort: high PR #14707 — gfx1250 fp8 GEMM bring-up and K-loop optimization (jefyang1, AICK-2347) — 🟠 Follow-up: rocke_pytest at its time limit
Utility: 🟢 Positive — parity test closes both gaps; merge renumbers opcode and ABI cleanly Legend: 🔴 blocking · 🟠 should-fix · 🟡 minor nit · 🟢 info/good · ⚪ retracted Follow-up review: first pass by a local qwen3.6 model, verified by the orchestrator (Claude Opus 5.5). Checks: the parity test against a dropped top-level key, a new spec field and |
rocke_pytest reached its CTest time limit on a CI shard. The two dead-worker tests each waited out a 5 s watchdog on the same scenario; they are one test now, with a 2 s watchdog (about a hundred times a fake build). The slow build sleeps 0.8 s under a 0.2 s watchdog instead of 1.5 s under 0.3 s. The inert-sweep tests compile two values of the trait they check instead of the config's four or five: waves_per_eu null and 4 (the pair that compiles to the same code on the tile), lds_k_pad 16 and 48. The two files take about a third of their previous time. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
N12 (
N13: noted. Whichever of this PR and #14833 lands second takes the next opcode (and ABI version) and renumbers in |
|
Automated review: Model - GLM-5.3-Flash, effort: high PR #14707 — gfx1250 fp8 GEMM bring-up and K-loop optimization (jefyang1, AICK-2347) — 🟡 Follow-up: sweep tests shortened
Utility: 🟢 Positive — timing fix confirmed; one lost test guard found by mutation Legend: 🔴 blocking · 🟠 should-fix · 🟡 minor nit · 🟢 info/good · ⚪ retracted Follow-up review: first pass by GLM-5.3-Flash (gateway), verified by the orchestrator (Claude Opus 5.5). Checks: the two sweep test files timed side by side at both heads, mutants of the build pool and the inert-sweep detector against the old and new tests, the build pool under CPU oversubscription, the previous head's gfx94X and Windows shard logs, opcode pins in both PRs, the merge with today's develop, build + ctest, byte identity ×4, goldens, differential, installed tree, compile, ABI, code quality. Flags whether a closer look is needed; not an approval or rejection. |
With two waves_per_eu values that compile to the same code, a detector that warns only when every value matches passed the test. It now sweeps null, 1 and 4 (1 changes the register budget) and checks that the warning names null and 4 without 1. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
N14 ( |
|
Merged develop ( |
|
Automated review: Model - qwen3.6:35b-a3b-coding-mtp-q4_K_M, effort: high PR #14707 — gfx1250 fp8 GEMM bring-up and K-loop optimization (jefyang1, AICK-2347) — 🟡 Follow-up: armed message out of date
Utility: 🟢 Positive — lost test guard restored, confirmed by mutation; squash message needs re-arming Legend: 🔴 blocking · 🟠 should-fix · 🟡 minor nit · 🟢 info/good · ⚪ retracted Follow-up review: first pass by qwen3.6 (local), verified by the orchestrator (Claude Opus 5.5). Checks: inert-sweep mutants against the old and new tests, both sweep files at llvm24, the |
Re-armed auto-merge after the last description edit; the squash message now says ABI 11 → 12. |
Conflict: dispatch_tests/core/test_binding.py. develop's #15004 runs the binding tests on every covered arch; this branch moved the binding to the shared rocke.numeric.bf16 codec and dropped its private _bf16_from_f32/_f32_from_bf16. The file keeps develop's arch parametrization and this branch's codec: the reference output encodes with f32_to_bf16, and the bf16 class checks the binding uses the shared codec. The round-trip and nearest-even tests it replaced are in tests/numeric/test_bf16_codec.py.
|
Merged develop (921b134). The only conflict was tests/dispatch/dispatch_tests/core/test_binding.py: #15004 runs the binding tests on every covered arch, and this PR moved the binding to the shared rocke.numeric.bf16 codec, dropping its private _bf16_from_f32/_f32_from_bf16. The resolved file keeps #15004's arch parametrization and this PR's codec: _write_reference_output encodes with f32_to_bf16, and TestBf16Encoding checks that the binding uses the shared codec and that NaN stays NaN. The round-trip and nearest-even tests it replaces are in tests/numeric/test_bf16_codec.py. ABI (12) and opcode (231) are unchanged. Checks on the merge: build + ctest 62/62 (1 skip), -L unit 58/58; byte identity GREEN ×4; golden OK ×4; the binding tests on every covered arch; the 33 changed test files 531 passed, 1 skipped (llvm22: 521 passed, 11 skipped); pre-commit clean over the PR range. |
develop's #11642 replaced the flat MMA operand fields and role enum with indexed sources (srcs[0..2]) and an independent destination in both engines, and took binary ABI 12. Conflicts: - cpp/core/arch/data.cpp, core/arch/target.py: the gfx1250 fp8/bf8 WMMA rows take #11642's indexed form; the four K=64 rows and the K=128 fp8 x fp8 row keep this branch's A/B lane maps and carrier fragment lengths (8 and 16) as srcs[0]/srcs[1]. The accumulator map is #11642's _wmma_gfx12_row_col_16x16 / lm_wmma_gfx12_src2, _dst. - core/arch/target.py: has_ab_layouts() reads srcs[0]/srcs[1].layout. - core/lower_hip.py: #11642's validate_unscaled_wmma with source_count=k // 8, so the K=128 path validates its i32x16 operands. - tests/core/gfx1250_wmma_ops.cpp: this branch's fragment and layout checks on the srcs[] fields. - core/ir.py: this branch's TDM pad encoder beside #11642's _mma_dst_frag_len. - abi.h: #11642 keeps ABI 12; this branch's rocke_gemm_trait_spec_t change becomes ABI 13 (ROCKE_ABI_VERSION and BINARY_ABI together). This branch's code that merged without a conflict moves to #11642's names too: the gfx1250 fp8 lane maps and the K=128 HIP lowering use ROCKE_MMA_ROLE_SRC0/SRC1, the GEMM validator's lane-map check reads srcs[0]/srcs[1].layout, and the fp8 fragment-layout test reads _FragInfo.srcs[i].fn / .frag_len.
|
Merged develop (5442420). #11642 (indexed MMA operands) conflicted in both engines' MMA catalogs, the HIP lowering, ir.py, the gfx1250 WMMA ops test and abi.h. The gfx1250 fp8 rows take #11642's srcs[]/dst form, with this PR's A/B lane maps as srcs[0]/srcs[1] (K=64 rows and K=128 fp8 x fp8); the K=128 HIP path uses validate_unscaled_wmma sized by K; this PR's other code moved to the new names (ROCKE_MMA_ROLE_SRC0/SRC1, srcs[i].layout, _FragInfo.srcs[i]). #11642 keeps ABI 12, so this PR is now ABI 13. Checks on the merge: build + ctest 64/64 (1 skip), -L unit 60/60; byte identity GREEN ×4; golden OK ×4; MMA/arch tests 324 passed; the 33 changed test files 531 passed, 1 skipped (llvm22: 521, 11 skipped); pre-commit clean over the PR range. |


Motivation
Bring up the universal GEMM for 8-bit floats on gfx1250 in both engines and make it fast, fed by the Tensor Data Mover (TDM). Supported inputs are fp8 x fp8 or bf8 x bf8 (A and B the same type), with a bf16 or fp16 C. fp8 runs on the 16x16x64 and 16x16x128 WMMA atoms; bf8 on the 16x16x64 atom only. The K-loop is then optimised with three opt-in traits. The work comes with a reproducible case study and the measurement tools behind it, so every result can be regenerated from the repository.
JIRA ID: AICK-2347
Technical Details
Every new trait defaults off, and the Python and C++ engines emit byte-identical LLVM IR throughout.
fp8 GEMM on gfx1250
_validate_storagesplits the A/B dtype from the C dtype; every other spec stays homogeneous.wmma_gfx1250_f32_16x16x128_fp8_fp8instruction (feat(rocke): backend completeness for every production target and dense MMA instruction #14328 lists it without A/B maps). Both maps are verified on silicon. The K=128 row counts its fragments in the 16 dword slots of its<16 x i32>carrier, as the K=64 rows do; the other fp8/bf8 pairs at K=128 keep develop's unmapped rows.TraitSpec.ab_load_elem_bytesoverrides the width so the two can be compared in one binary. f16/bf16 kernels are unchanged.c<dtype>, the fp8/bf8 path only), so fp8 with a bf16 C and with an fp16 C are two symbols; every other kernel keeps its name.TDM in the universal GEMM
tdm_descriptor_2d, which now also takes an i64 global address. Core'sencode_tdm_padding(new, both engines) turnslds_k_padinto the descriptor's pad fields, and the winograd GEMM's row skew now goes through it too.tile.global_addr_of: a global address as an i64, without aninboundsGEP, so a tile origin past the end of the buffer stays defined.TraitSpec.tdm/tdm_depth: 1 is unpipelined, 2 ping-pong, 3 or 4 a modular ring. This ports the TDM subset of feat(rocke): gfx1250 BF16 universal GEMM load-path, epilogue, and persistent-kernel levers #12658.K-loop traits (opt-in, depth-2 TDM ping-pong)
split_barrier: the per-tile barrier is split into signal and wait, so WMMAs overlap the wait. The ring (depth ≥ 3) takes the same split.tdm_alternate_issuers: each LDS half gets its own issuer wave pair, which takes the refill off the waiting waves' critical path.tdm_early_refill: refill a half as soon as every wave has read it.tdm{depth},spb,alti,erf), and the runbook Knob Catalog lists them.Measured on gfx1250 at 4096x4096x65536 (fp8e4m3 A/B, bf16 C) on the 16x16x128 atom with
fp8_trait_ab.pyat the commits that added each trait (then thef8f6f4form of the instruction; see Test Result for the rerun on the dedicated one). Each build is verified on the device before any timing (exact on integer inputs, within the bf16 rounding bound on random inputs), then the builds are timed round-robin in one process on random inputs (each sample: 25 ms idle, then 1 warmup and 3 timed launches; median of 15 samples). Ratios are medians against the depth-2 TDM ping-pong without these traits, on this branch's own kernels:split_barriertdm_alternate_issuerstdm_early_refillThe A/B is cumulative: each row adds one trait to the row above, so
tdm_alternate_issuerswas not measured on its own. Thetdm_early_refillgain depends on K: at K = 8200 it falls belowtdm_alternate_issuers(below), so it is meant for long K.These are results at this shape and geometry, not a general claim; the case study gives the full method and caveats.
Correctness fixes along the way
align 32for 16-byte accesses. This also lowers thealignof 8-bit LDS loads in eight existing configs,moe_fused_mega_fp8[0..5]andgfx950_attention_tiled_2d[27],[31]; their ISA is unchanged. The differential golden is re-recorded for those two families only (32 hashes across llvm20/22/23/24).lds_k_padon every row. On gfx1250 it also accounts for the cshuffle C tile being aliased onto the A/B pool (max, not sum); gfx942/gfx950 keep develop's sum, since no CDNA shape the max admits has run on silicon.block_size / wave_size). Countingwarp_m * warp_n * warp_kgave a validwarp_k = 2spec's B fill to a wave that is never launched, so B was never loaded. IR is unchanged for everywarp_k = 1spec.split_k,emit_sched_hintsandcshuffle_no_aliasnow reach the C++ engine throughbackend="cpp". They were dropped by the spec dict and by the binding, so the C++ engine validated and planned with their defaults;split_barrier'ssplit_krule and the gfx1250 cshuffle LDS budget depend on two of them.is_valid_specgaps against feat(rocke): gfx1250 BF16 universal GEMM load-path, epilogue, and persistent-kernel levers #12658 are closed; for example,lds_swizzleis now rejected on every WMMA target: the WMMA read path does not undo the swizzle, and gfx1151 returns wrong outputs with it as gfx1250 does.ab_load_elem_bytesmust be 1, 2, 4 or 8 and is rejected undertdm; the C++ engine rejects pipelinewmma_v1, as on develop, since it does not emit that schedule (Python keeps it); with K = 0 the TDM ring's fills start at the first K element, not one tile before it; the TDM tile origin, including a batched kernel's batch offset, is computed in i64, so an operand past 2^31 elements does not wrap.Sweep harness and case study (
python/rocke/examples/gfx1250/gemm_perf_fp8/)traitsconfig section with inheritable configs;sweep.pyderives the arch from the ISA, and the HSACO cache key includes it.build_all_instancestakes an opt-in stall watchdog (stall_timeout, default off), so a build worker that dies cannot hang a stage; the fp8 sweep turns it on. Existing callers are unchanged.fp8_trait_ab.pyshare one exact input set (fp8_data.int_operands) and one GPU-contention check (gpu_contention.py).fp8_trait_ab.py: interleaved, verified A/B of the K-loop traits;wmma_roofline_probe.py: a data-matched WMMA ceiling;memory_probe.py: bandwidth and the TDM feed floor;clock_probe.py: in-kernel clock stamps and a device health check.gemm_perf_fp8_case_study.mdand the README record the method, the results and the conclusions it retracted.Integration with develop
ROCKE_OP_TILE_GLOBAL_ADDR_OFis appended at the end ofrocke_opcode_t, after develop's newest opcode (feat(rocke): parameter facts checked on the host, GPU checks for device-only values, and a checked launcher #14448'stile.gpu_check_failed, 230), as 231, and pinned intest_opcode_values.cpp. No existing opcode value changes.f8f6f4form this branch had used, so this PR no longer adds an MMA op; the catalog pins stay at develop's 134 gfx1250 rows. The 7gemm_emitconfigs on that atom (23–28, 32) change only in the WMMA call, and their golden hashes are re-blessed for thegemmfamily alone.srcs[0..2]plus an independentdst. This PR's A/B lane maps on the gfx1250 fp8 rows (the four K=64 rows and K=128 fp8 x fp8) are itssrcs[0]andsrcs[1]layouts, in both engines.gemm_emitparity configs: develop's fp64 configs keep indices 11–12, and this branch's configs are 13–32.dispatch/gemm/binding.pyno longer carries its own bf16 codec besiderocke.numeric.bf16(the two disagreed on NaN); the binding, the manifest runner, the fp8 tools and their tests userocke.numeric.bf16. The OCP e4m3/e5m2 decode tables and exact encoders live inrocke.numeric.fp8(new, withtest_fp8_codec.py).rocke_enginebinding reads a GEMM spec dict in one place:build_specdelegates tofill_universal_spec, and each tile/trait/data field is named once, read from the flat keys overridden by the nested sub-dict. A source-only test checks that the keys the GEMM spec dicts write and the keys the binding reads match, in both directions.C ABI:
ROCKE_ABI_VERSION12 → 13rocke_gemm_trait_spec_tgains seven fields:tdm,tdm_depth,ab_load_elem_bytesand its_setflag,split_barrier,tdm_alternate_issuersandtdm_early_refill. That changes its size, and the layout of every GEMM spec that embeds it.abi.hrequires a bump for exactly this case.ROCKE_ABI_VERSION(C) andBINARY_ABI(Python bindings) move from 12 to 13 together. Version 7 was taken by feat(rocke): backend completeness for every production target and dense MMA instruction #14328 (rocke_mma_op_tgaineddst_dtype), 8 by feat(rocke): gfx1250 WMMA direct fwd: 1-D, rectangular, stride-2 views, small-K, depthwise, small-group and dilated #14835 (rocke_direct_fwd_wmma_spec_tgained fields; two direct-conv functions returnlong long), 9 by fix(rocke): scale each block-scaled GEMM output with the A scale of its own row #14843 (rocke_block_scale_gemm_spec_tlostper_input_row), 10 by fix(rocke/wgrad): stop fencing the packed fp16 split-K atomic #14907 (rocke_implicit_gemm_conv_wgrad_spec_tgainedregister_prefetch), 11 by feat(rocke): parameter facts checked on the host, GPU checks for device-only values, and a checked launcher #14448 (rocke_param_opts_tgained fields) and 12 by refactor(rocke): model indexed MMA operands #11642 (indexed MMA sources and an independent destination), all of which landed first. The bindings check that the version matches when they load the library, so a mismatched library is refused at load instead of misreading memory.tile.global_addr_ofis appended at the end of the enum.Not in this PR
KernelCandidateselects it, anddispatch/gemm/support.pyrejects specs whose A/B and C dtypes differ. The measured kernel is the hand-builtchampion_specinfp8_trait_ab.py.Test Plan
tools/check_byte_identity.py, llvm23) on the merged tree. Parity coverage added for the new paths:gemm_emitconfigs 13–32: fp8, the load-width override, the LDS pad alignment, TDM depths 1–4, cshuffle on WMMA, the dense K=128 atom, the K-loop traits (also batched) and bf8;gfx1250_lowering_emit, built by core'stdm_descriptor_2dfrom an i64 address.gemm_emitconfigs 13–32 are blessed, so CI checks their IR at llvm20/22/23/24 and in canonical mode.ctest -L unit, includingrocke_dense_fp8_k128_hip(new),rocke_gemm_universal_spec_guards(new: the validator rules this PR adds, with their reason strings),rocke_opcode_valuesandrocke_mma_catalog_lookup.rocke_arch_table_engine_parity(new CTest): the two engines' arch tables agree, run from the source tree.rocke_gemm_spec_dict_binding_parity(new CTest): the keys the universal, batched, grouped and FlatMM spec dicts write are the keysfill_universal_specand the family readers read, run from the source tree without therocke_enginebuild.Test Result
Differential golden (
run_diff.py --check-golden): passes for every family inllmode at llvm20/22/23/24 and in canonical mode. Blessinggemm_emitconfigs 13–32 adds 69 hashes; after the first develop merge, the 7 configs on the K=128 atom change 21 hashes, only in the WMMA call. Deciding the TDM batch offset once (one i64 per operand) changes the.lland canonical IR of configs 16–19 and 22–29 (36 hashes at llvm23/llvm24 and canonical), re-blessed for those configs only; their ISA is unchanged.Byte-identity gate: GREEN at llvm20, llvm22, llvm23 and llvm24 (99, 99, 98 and 98 families), with no mismatches.
Arch domain:
test_arch_domain_artifact.pypasses at llvm20/22/23/24 with no key unmeasured;check_arch_domain.pyis GREEN.After the latest develop merge,
ctest -L unit: 58 of 58 passed, includingrocke_dense_fp8_k128_hip,rocke_gemm_universal_spec_guards(27 cases) androcke_opcode_values. The fullctest: 62 of 62, one skipped (rocke_arch_domain_reproducibility), includingrocke_arch_table_engine_parityandrocke_gemm_spec_dict_binding_parity.Python host tests (the 33 test files this PR adds or changes, with the
rocke_engineextension built): 531 passed, 1 skipped. AtROCKE_LLVM_FLAVOR=llvm22: 521 passed, 11 skipped (also the TDM cases).On device: every fp8 shape and every trait arm verified, with 0 mismatches on integer inputs. The performance ratios are in Technical Details.
On device, rerun at
5d010905603(later commits add tests, docs, refactors with no IR change, a fix that changes only batched TDM kernels and validation, and the review fixes; of those, only deciding the TDM batch offset once changes the measured kernels' IR, and it leaves their machine code identical: the four measured arms and the batched variant disassemble to the same instructions before and after; the toolchain, driver and SHA are recorded with the results, outside the repository):fp8_trait_abwith all four arms, then again at a ragged K. No other GPU process at the start or end of either run. Every arm verified before timing: exact on integer inputs (5 launches), max relative error 3.7e-3 (K = 65536) and 3.1e-3 (K = 8200) on random inputs (bound 7.8e-3). K = 8200 is not a multiple of the K tile, so it exercises the partial last tile in every K-loop, early refill's included.tdm_d2, random inputssplit_barriertdm_alternate_issuerstdm_early_refillAt K = 65536 the ratios match the table in Technical Details within noise. At K = 8200 the early refill falls below
tdm_alternate_issuers, as the case study's K dependence predicts.On device, after merging develop (the GEMM now issues the dedicated K=128 instruction):
fp8_trait_abwith all four arms at K = 65536 and K = 8200. No other GPU process at the start or end. Every arm verified before timing: exact on integer inputs (5 launches), max relative error 3.7e-3 and 3.1e-3 on random inputs. The trait ratios match the runs above within run-to-run noise, andwmma_roofline_probeputs the dedicated instruction at 1.009x thef8f6f4form on the same random data.tdm_d2, random inputssplit_barriertdm_alternate_issuerstdm_early_refillOn a gfx1250 device after the review fixes (
e357d26381d):universal_gemm_verifybit-exact for fp8 on the K=128 and K=64 atoms, at a ragged 520x264x8200, for bf8, with an fp16 C and with the cshuffle epilogue;fp8_trait_abverifies all four trait arms (exact on integer inputs, 5 launches; within the bf16 rounding bound on random inputs). No other GPU process at the start or end.Submission Checklist