Repository navigation
prefill: gfx11 F16 matrix-core routed experts (opt-in STRATA_PF_F16=1): prompt +10-14% on gfx1151 - #2020
prefill: gfx11 F16 matrix-core routed experts (opt-in STRATA_PF_F16=1): prompt +10-14% on gfx1151#2020libratechw wants to merge 2 commits into
Conversation
…-path hashes, the KL Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…A_PF_F16=1) The int8 fused expert kernels decode each weight sub-block to int8 and keep a per-block epilogue. With STRATA_PF_F16=1 on top of STRATA_PF_FUSED=1, gfx11 takes F16 kernels instead: the codes stay packed in LDS, each wave turns its own rows into F16 after the read, the int8 activations are staged once in LDS as F16, and the F16 WMMA accumulates all of K in FP32. moe_f16_common.cuh holds the work item, the staging, the WMMA loop and the two epilogues; moe_f16_kq.cu adapts gufo's paired RoutedF16GEMMKernel (97b8645f, MIT, licence text in both files) to Strata's tables, int8 activations and H for Q4_K / Q5_K gate/up and Q5_1 down; native_f16_kernel (moe_fused_iq.cu) takes IQ2_XXS / IQ2_XS / IQ2_S / IQ3_XXS / IQ3_S / IQ4_XS gate/up and Q2_0 / IQ4_NL / Q8_0 down. The K-quants also need STRATA_PF_FUSED_KQ=1; Q8_0 down does not (it has no minimum term). gfx12 keeps the int8 kernels; the device list is the same as STRATA_NAT_W11's. The K-quant kernels read the weights 16 bytes (gate/up) and 8 bytes (Q5_1 down) at a time, and the native blobs are only promised 2-byte alignment, so each of gate/up and down takes them only when the batch's blobs, offsets and row strides are aligned to that (f16kq::covers / covers_down); otherwise that half stays on its int8 kernel. gfx906, which builds the CUDA targets' sources as HIP and so not moe_f16_kq.cu, covers nothing there. The output differs from the int8 kernels' (F16 weights instead of int8 sub-blocks), so it is off by default. With STRATA_PF_F16=1 on a gfx11 device, hip_prefill_fused_iq allows 5e-3 against the int8 model and MMQ (gfx1151: 2.7e-3) and places its reference blobs 256-byte aligned so that the F16 kernels are what it checks; elsewhere the int8 limits stay. ctest hip_prefill_fused_iq_f16 runs the default pairs with the switch, hip_prefill_fused_iq_f16_kq the K-quant pairs (with STRATA_PF_FUSED_KQ=1, which the test itself sets only off Windows). Ryzen AI Max+ 395 (gfx1151, ROCm 7.14.1), on 296b59d: - hip_prefill_fused_iq, one layer, 16,384 tokens, top 10 over 512 experts, median of 3: Q4_K / Q5_1 86.4 -> 53.7 ms, Q4_K / Q8_0 85.9 -> 53.5 ms, IQ3_S / IQ4_NL 79.8 -> 58.2 ms. - this branch with and without the switch, Linux, --serve --prefill 16384 --spec 4, the section-5 switches of docs/STRIX_HALO.md with STRATA_PF_SWITCH_MIN_T=2048 (UD-Q4_K_XL also STRATA_PF_FUSED_KQ=1), 5 pairs of fresh servers, prompt tok/s (median) and the median of the pair ratios: UD-Q4_K_XL 4K 1,129 -> 1,294 (+14.4%), 32K 1,249 -> 1,422 (+13.9%); UD-IQ4_XS 4K 1,114 -> 1,269 (+13.5%), 32K 1,266 -> 1,389 (+9.9%). The UD-Q4_K_XL 32K figure was measured on an earlier version whose gfx1151 kernels, dispatch and shared header are this commit's (it lacked the gfx906 stubs and the K-quant ctest's environment); the layer times and the other three on one before the alignment check. - without the switch, the layer's output hashes (six pairs, 2,048 and 16,384 tokens; the same earlier version) are 296b59d's. - first-token KL against a run with no switches, 12 prompts of 1.5K-24K tokens, mean: UD-Q4_K_XL 0.0065 -> 0.0114, UD-IQ4_XS 0.0076 -> 0.0104; top-1 the same in 12 of 12. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…t times, first-token KL) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
0892b26 to
ae38fd5
Compare
|
Ported unchanged (all seven commits, your authorship), as an opt-in: STRATA_PF_F16=1 (and STRATA_PF_F16_KQ=1 with STRATA_PF_FUSED_KQ=1 for K-quants). We have no gfx11 matrix-core machine, so we only checked what we can: it builds for gfx1100/1103/1150/1151/1201, gfx12 keeps the int8 kernels (hip_prefill_fused_iq in both modes passes on an R9700) and the identity gate there is unchanged. The speed and KL numbers are yours; a larger prompt set and a task check from a gfx1151 would let us think about a default. |
…o1221#2020 The 32K prompt A/B and layer timings of Niko1221#2018, the GDN ctest of Niko1221#2299, and the KL and task-check runs of Niko1221#2020, on the maintainer's main. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
|
Thanks for porting this. You asked for a larger prompt set and a task check on gfx1151. I ran both on the merged build (477ac13). B is F16 off, F is F16 on ( KL vs R, 25 prompts, first-token logits
Task check (greedy, reasoning off, one run per arm): HumanEval every second problem (82, EvalPlus 0.3.1) and 30 generated reasoning tasks.
F16 was engaged: 16–17 of the 82 HumanEval responses differ between B and F. The only problem whose result flips is HumanEval/76 (F passes on Q4_K_XL, fails on IQ4_XS), so I see no one-directional degradation. The reasoning outputs are identical between B and F (0 of 30 differ), probably because those prompts are short and do not reach the F16 path, so they say nothing about F16. Each arm was run once, so I have no noise floor for single-problem differences. Per-prompt KL, per-problem grading, all responses, settings and scripts ( |
|
Thanks for the pull request. Your change is already in If part of your work did not make it in and you want it considered, open a new pull request on top of |
Title
Issue: Refs #1258
Summary
With
STRATA_PF_FUSED=1the routed experts of a prompt run on gfx11's int8 matrix cores, each weight sub-block decoded to int8with a per-block epilogue.
STRATA_PF_F16=1runs the covered formats on the F16 matrix cores instead: the codes stay packed inLDS, each wave turns its own rows into F16, and the F16 WMMA accumulates all of K in FP32. The K-quant kernels adapt gufo's
RoutedF16GEMMKernel(97b8645f, MIT; attribution and licence text at the top of both new files). The output differs from theint8 kernels', so it is off by default; gfx12 keeps the int8 kernels.
What changed
src/prefill/moe_f16_common.cuh(new): the switch, the work item, the activations staged as F16, the WMMA loop, the twoepilogues.
src/prefill/moe_f16_kq.cu/.hpp(new): Q4_K / Q5_K gate/up and Q5_1 down (withSTRATA_PF_FUSED_KQ=1). They read theweights 16 / 8 bytes at a time, so each of gate/up and down takes them only when the batch's blobs, offsets and row
strides are aligned to that (the native blobs are promised 2 bytes); otherwise that half stays on its int8 kernel. gfx906,
whose build leaves this file out, covers nothing here.
src/prefill/moe_fused_iq.cu:native_f16_kernelfor IQ2_XXS / IQ2_XS / IQ2_S / IQ3_XXS / IQ3_S / IQ4_XS gate/up and Q2_0 /IQ4_NL / Q8_0 down (through the existing 16-bit loads), and the dispatch.
tests/cuda/prefill_fused_iq_test.cpp,CMakeLists.txt: withSTRATA_PF_F16=1on a gfx11 device the test allows 5e-3against the int8 model and MMQ (measured 2.7e-3) and places the blobs 256-byte aligned, so the F16 kernels are what it
checks; elsewhere the int8 limits stay. ctest
hip_prefill_fused_iq_f16runs the default pairs with the switch,hip_prefill_fused_iq_f16_kqthe four K-quant pairs (it setsSTRATA_PF_FUSED_KQ=1too).docs/STRIX_HALO.md: what it covers, the layer and prompt times, first-token KL.Ryzen AI Max+ 395 (gfx1151, ROCm 7.14.1, Linux), on 296b59d. One layer,
hip_prefill_fused_iq, 16,384 tokens, top 10 over512 experts, median of 3:
Prompt tok/s, the branch's binary without and with
STRATA_PF_F16=1,--serve --prefill 16384 --spec 4, the section-5switches with
STRATA_PF_SWITCH_MIN_T=2048(UD-Q4_K_XL alsoSTRATA_PF_FUSED_KQ=1), a chat request of 4K / 32K tokens,fresh servers alternating, 5 pairs after dropping those with page migration or reclaim; median tok/s and the median of the
pair ratios, every pair faster:
The UD-Q4_K_XL 32K cell is of this code; the layer times and the other three cells are of an earlier head with the same
kernels (before the alignment check and the test changes). Without the switch, the layer's output hashes (six pairs, 2,048
and 16,384 tokens) are 296b59d's.
First-token KL against a run with no switches, 12 natural-text chat requests of 1.5K-24K tokens, mean (median); the fast arms
with
STRATA_PF_SWITCH_MIN_T=0; the top token is the same in 12 of 12 in every arm:STRATA_PF_F16=1F16 moves further from the default than the int8 path, so this stays opt-in. The records and scripts are in
libratechw/Strata@e5d05554,
2020/.Builds and tests:
hip_prefill_fused_iq*among them), 5 skip, and the samethree fail as on 296b59d (
ple_parity,expert_parity,pool_test).moe_fused_iq.cuandmoe_f16_kq.cucompile for gfx1012, gfx1030, gfx1100, gfx1103, gfx1150, gfx1151, gfx1200 andgfx1201 (77506be1; the head changes neither file). gfx906:
moe_fused_iq.cuno longer leaves thef16kqfunctionsundefined (it did at 77506be1); the whole gfx906 build stops earlier, at
mmq_nvfp4_w4a4.cu(ggml'svendors/cuda.h),which this branch does not touch.
test comment and the doc): builds; ctest, 117 tests: 114 pass, 2 skip, and
ple_parityfails as on 296b59d.Not run: other gfx11 cards (gfx1100-1103, gfx1150), and quality beyond the first-token KL.
🤖 Generated with Claude Code