Repository navigation
HIP: run Qwen3-8B's BF16 projections on a gfx12 WMMA tile - #2034
Conversation
|
Thanks @laudney. This is a clear, careful PR, and the per-projection check on real operands is exactly what a sum-order Everything checks out on our side:
On the decision you raised: please make WMMA opt-in. Have Two smaller asks:
|
|
Thanks @ashhart. All three asks are in, as two new commits on top (no force-push):
Checks after the change: |
The maintainer made ashhart#2034's gfx12 WMMA tile opt-in, so the rerank speed it gives now needs --policy matrix=on while the default keeps the dot2 tile. The CHANGELOG entry and the reranker recipe's speed row name the flag beside the 1.00 s figure and mark dot2 as the default.
|
Thanks @laudney, all three asks are in.
This is ready from our side. It lands after #1978, which needs a small rebase: main has since added the |
775339d to
c47f369
Compare
The maintainer made ashhart#2034's gfx12 WMMA tile opt-in, so the rerank speed it gives now needs --policy matrix=on while the default keeps the dot2 tile. The CHANGELOG entry and the reranker recipe's speed row name the flag beside the 1.00 s figure and mark dot2 as the default.
|
Restacked on #1978's rebased head |
cdbbdef to
958f492
Compare
The BF16 dense products of Qwen3-8B run at about 25 TFLOPS on the dot2 tile on gfx1201: a new tile runs them on gfx12's WMMA, with two block geometries picked by size (equal bytes, each output's k products added in k order), its own bound, kernel tests against float64 and a hip-dense-tune timing step; every caller names its tile and stays on dot2, so nothing serves the WMMA tile yet.
The WMMA tile sums in another order than dot2, so it is a new kernel with its own bound, not a replaces entry: each geometry is registered on its own (fp32 and BF16 out) at the served shapes and both blocks' edges, with depth k and the k 2^-126 floor, and gate 5 records the gfx1201 counts from ROCm 10.1 (not served on the other chips).
Qwen3-8B's BF16 projections ran on the dot2 tile on gfx1201: they now run on the WMMA tile under matrix=auto and on (the dense kernels take the policy's matrix choice at load), matrix=off keeps dot2's bits, other chips keep dot2, and qwen3, whose products are all BF16 dense ones, is admitted with matrix=on on gfx12 while the families on MLX affine tiles keep that refusal.
A reduction-order change needs a per-projection FP64 comparison: the GPU checks take TF_QWEN3_MATRIX into the launcher's choices, and a new check feeds layer 0's real operands, copied out of the forward by layerInputs, through both tiles for each projection class; the BF16 outputs the engine writes must be within 1% of dot2's against float64, and the fp32 errors are printed for the record.
gfx12 now serves Qwen3-8B's BF16 projections on the WMMA tile by default, with other arithmetic than dot2: the embedding recipe names the tile, its contract, the matrix choices and the GPU checks' TF_QWEN3_MATRIX, and adds WMMA's receipts beside dot2's (distances, widths, projections, speed); the CHANGELOG states the change and its precision trade.
The qwen3 prompt pass added the attention output to the residual and then normed it in two launches: residualRms does both in one launch with the same bits, so Qwen3-Embedding-8B's responses stay byte-equal and 100 short inputs take about 1% less time on an R9700.
The maintainer's review of the WMMA tile asked for an opt-in: its fp32 sums sit 8 to 41 times further from float64 than the dot2 chain's, and a change that makes the default output less exact needs one. Kernels.serving now picks WMMA only for matrix=on, so matrix=auto keeps the dot2 tile and its bits on gfx12 as on every other chip. The embedding recipe puts the matrix=on serve line next to its speed and accuracy rows, the CHANGELOG entry states the opt-in, and both say that gfx1200 builds the tile but is unmeasured.
The maintainer asked for a planted control beside the WMMA tile's contract registration, so the sums gate is shown to catch a WMMA tile that sums less exactly than it declares. The tile takes its 16-deep step as a template parameter, the served fp32 one by default, and the controls' code object adds tf_ctl_wmma12_bf16_sum: the small block with each step through gfx12's BF16-accumulating WMMA. The contract registers it on gfx12 as a control of gate 4, launched with the dense launcher's arguments through gemmWith, and it goes red there; the served kernels' records stay current.
4dea6b7 to
6f99765
Compare
|
Thank you @laudney. This is merged into main with your commits under your own name, so you're listed as a TensorFold contributor. It ships in the next release, credited to you in the changelog and the release notes. |
The maintainer made ashhart#2034's gfx12 WMMA tile opt-in, so the rerank speed it gives now needs --policy matrix=on while the default keeps the dot2 tile. The CHANGELOG entry and the reranker recipe's speed row name the flag beside the 1.00 s figure and mark dot2 as the default.
The maintainer made ashhart#2034's gfx12 WMMA tile opt-in, so the rerank speed it gives now needs --policy matrix=on while the default keeps the dot2 tile. The CHANGELOG entry and the reranker recipe's speed row name the flag beside the 1.00 s figure and mark dot2 as the default.
The maintainer made ashhart#2034's gfx12 WMMA tile opt-in, so the rerank speed it gives now needs --policy matrix=on while the default keeps the dot2 tile. The CHANGELOG entry and the reranker recipe's speed row name the flag beside the 1.00 s figure and mark dot2 as the default.
The maintainer made #2034's gfx12 WMMA tile opt-in, so the rerank speed it gives now needs --policy matrix=on while the default keeps the dot2 tile. The CHANGELOG entry and the reranker recipe's speed row name the flag beside the 1.00 s figure and mark dot2 as the default.
Part of #1977. Stacked on #1978 (the Qwen3 dense HIP core); until #1978 lands, this diff also shows its commits. The reranker numbers need #1981's route.
On RDNA4 (gfx12), Qwen3-8B's BF16 projections can run on a new WMMA tile, opt-in with
--policy matrix=on. The defaultmatrix=autokeeps the dot2 tile and its bits.--policy matrix=on, this PR)check, #1978's 1× limits): worst distance at width 4096 / 1024 / 32Arithmetic rule (CONTRIBUTING). WMMA changes the sum order, and gfx12's WMMA sums each 16-product step less precisely than the dot2 chain: the fp32 sums are 8 to 41 times further from float64 on Qwen3-8B's real layer-0 operands. The BF16 outputs the engine writes are as close as dot2's, and both models pass their oracles. On review, WMMA is opt-in: only
--policy matrix=onserves it, so the default output keeps dot2's bits. gfx1200 builds the same tile but is unmeasured: no run, and no gate 5 record (the records cover gfx1201).Why
The BF16 projections are nearly all of a Qwen3-8B prompt pass. On the dot2 tile they reach 22 to 30 TFLOPS. The WMMA tile reaches 45 to 67 at 276 rows and 86 to 99 at 2,048 rows. With it, embeddings come within 18% of SGLang. The reranker's remaining gap is one pass per document (about 276 rows each); packing a request's documents into one pass is the next step, separately.
What this changes
zig/kernels/hip/tiles/wmma12_gemm.hpp: y = x · Wᵀ for BF16 x and BF16 W with fp32 accumulators on__builtin_amdgcn_wmma_f32_16x16x16_bf16_w32_gfx12(layout checked against the CPU). Two block geometries, a 16 x 64 block (K steps of 64) for few rows or narrow outputs and a 128 x 128 block (K 32, band launch order) above; the launcher picks by size (shapeOf). Both add each output's products in k order, 16 a step, so a row's bytes depend on neither m nor the geometry; the kernel tests check that at every row count around the thresholds. It traps on chips without gfx12 WMMA.ononly, dot2 underautoandoffand on every other chip. Only qwen3 loads BF16 dense weights, so no other family's bits change.matrix=onis admitted on gfx12 for qwen3 (all its products have the tile); the MLX-affine families keep the refusal.zig/tests/hip/contract_dense_wmma12.zigregisters each geometry, fp32 and BF16 out, as a new kernel (not areplacesentry): depth k plus a k 2⁻¹²⁶ floor, the served Qwen3-8B shapes and both blocks' edges; gate-5 records for gfx1201 from ROCm 10.1. Its planted control,tf_ctl_wmma12_bf16_sumin the controls' code object, is the small block with each step through gfx12's BF16-accumulating WMMA (the tile takes its step as a template parameter, the served fp32 one by default); gate 4 catches it.hip-dense-tunetimes both tiles at the served shapes. The qwen3 GPU checks takeTF_QWEN3_MATRIX, andprojection_test.zigcompares both tiles on layer 0's real operands, whichlayerInputscopies out of the forward (Taps, null in serving).matrix=onserve line beside its tables, gfx1200 unmeasured),docs/kernel-contract.md, and the CHANGELOG.Checks
zig build test -Dhip=true: 518/518 steps. Lean: no new findings (424, the base's).hip-kernel-test125/127 (2 skipped);hip-kernel-contracton gfx1201: 64 kernels pass gates 1-4, 6 controls red as planted (the WMMA one among them); the 2 limit problems are upstream'stf_sum_partialsrecords, as on the base.hip-kernel-contract-limits: the WMMA and control records current; its 11 problems aretf_sum_partials,tf_sum_partials_actandtf_moe_combine_gate, stale on the base since upstream's 74f1625.qwen3-hip-gpu-testundermatrix=onandoff: the embedding and reranker checks and the projection comparison pass (the WMMA numbers above equal underon).