ggml-cuda: f32 tall-skinny GEMM kernel for gfx1151 (RDNA3.5) - #74
Draft
roberteg16 wants to merge 1 commit into
Draft
ggml-cuda: f32 tall-skinny GEMM kernel for gfx1151 (RDNA3.5)#74roberteg16 wants to merge 1 commit into
roberteg16 wants to merge 1 commit into
Conversation
For f32 mul_mat where the weight is tall-skinny (K=2048, N=32) and the batch is moderate, ggml_cuda_mul_mat on gfx1151 falls through to the hipBLAS path (mmvf caps at batch 8, and f32 mmf needs MFMA/Ampere), which is far from bandwidth-bound peak for this decode shape. This adds a custom HIP kernel that keeps the (hot) activation resident in LDS and streams the (cold) weight from global memory with a backedge software pipeline, reducing the K dimension lane-parallel with a wave32 DPP tree. A new predicate/dispatch (ggml_cuda_should_use_mul_mat_f32_tall_skinny / ggml_cuda_mul_mat_f32_tall_skinny) selects a per-M configuration and routes only the validated shape to the custom path, leaving all other shapes on hipBLAS. It fires only on RDNA3.5, only for f32xf32->f32, contiguous, single-batch, K=2048, N=32. All kernel code is under #if defined(GGML_USE_HIP) so the CUDA build is unaffected (the predicate returns false there). Measured on Radeon 8060S (gfx1151) in the mixed decode regime (activation hot in L2, weight cold), vs hipBLASLt (ROCBLAS_USE_HIPBLASLT=1): N=32 wins across M=8..4096 (about 2-4x, ~68% of DRAM roofline at M=128 rising to ~100%+ at large M). Numerically verified against the CPU reference: test-backend-ops -o MUL_MAT passes for all added N=32 shapes. Co-authored-by: Claude <noreply@anthropic.com> Signed-off-by: Robert Esclapez Garcia <robert.garcia@amd.com>
roberteg16
force-pushed
the
rogarcia.gfx1151-f32-tall-skinny-gemm
branch
from
July 29, 2026 17:27
3b17350 to
f891283
Compare
roberteg16
marked this pull request as ready for review
July 29, 2026 17:28
roberteg16
marked this pull request as draft
July 29, 2026 17:33
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.
What this does
Adds a custom HIP path for f32
mul_matwith a tall-skinny weight (K=2048, N=32) on gfx1151 (Strix Halo, RDNA3.5). For this shapeggml_cuda_mul_matfalls through to hipBLAS (mmvf caps at batch 8; f32 mmf needs MFMA/Ampere), which is far below the memory-bound peak. The new kernel is 2x-4x faster than hipBLASLt across the batch range.The kernel keeps the hot activation resident in LDS and streams the cold weight from global memory with a backedge software pipeline; the K reduction is lane-parallel followed by a wave32 DPP tree reduce. A predicate/dispatch (
ggml_cuda_should_use_mul_mat_f32_tall_skinny/ggml_cuda_mul_mat_f32_tall_skinny) routes only the validated shape to the custom path: RDNA3.5, f32xf32->f32, contiguous, single-batch, K=2048, N=32. Everything else keeps its existing behavior. All device code is guarded so the CUDA build and non-RDNA3.5 HIP targets are unaffected.Benchmarks
Radeon 8060S (gfx1151), decode regime (activation hot in cache, weight cold from DRAM), vs hipBLASLt (
ROCBLAS_USE_HIPBLASLT=1). Percentages are the achieved fraction of the ~238 GiB/s DRAM roofline (>100% is legitimate: the hot activation is served from the 32 MB Infinity Cache). The APU throttles, so numbers vary by a couple of points.For M <= 8 the existing mmvf path handles the batch, so in practice the custom kernel serves M >= ~9.
Testing
test-backend-ops is extended with the new shapes (N=32 across M in {8,64,128,512,2048,4096}) in the eval and perf lists:
All added shapes report OK against the CPU f32 reference, with no regressions in the rest of the MUL_MAT suite.
End-to-end
The shape is real: Qwen3.6-35B-A3B (Q4_K_M) issues the f32 K=2048 N=32 mul_mat ~600 times per forward pass (~1.6% of total GPU time), and the kernel runs it ~3-4x faster than hipBLAS (~34 us -> ~8 us per call). End to end this is a small prefill speedup and no change to decode (batch 1, handled by mmvf). Measured with
llama-bench:-p 128is ~1.4% faster on the stable runs;-p 4096 -n 0 -d 0is ~1652 vs ~1644 t/s (~0.5%), within the +-20-33 t/s run-to-run stddev of this throttling APU. The model's runtime is dominated by its quantized expert GEMMs, so the absolute gain here is modest; workloads that lean more on f32 tall-skinny GEMMs benefit more.Scope
Deliberately narrow: it only touches the validated gfx1151 shape and falls back to hipBLAS everywhere else, so there is no risk to other backends, GPUs, or shapes.