Repository navigation
tunableop(rdna2): qualify rocm10-rocblas5.6, add the decode/MTP and 256/512-chunk grids (44 -> 139 rows) - #92
Merged
BlivionIaG merged 3 commits intoOct 16, 2026
Conversation
wsantos
force-pushed
the
tunableop/profile-rocblas-d05939967b5f
branch
from
October 12, 2026 22:35
e9b3b27 to
180e14c
Compare
The profile recorded lib_sha256 = c27e2252cc7a, a retired build. The loaded library is d05939967b5f (the system /opt/rocm/core-10.0 copy and the venv _rocm_sdk_libraries copy are byte-identical on this box). No registered profile matched, so configure_tunableop warned and fell back: WARNING: no fork rows for rocBLAS build d05939967b5f ... falling back to per-user path The rows were reachable only through the legacy rocblas-<hash>/ directory. That fallback directory is dropped here: the storage policy is one named profile per rocBLAS build, with nothing archived. Qualification ran the sanctioned pipeline (tools/rdna2_028/tunableop_rows_pipeline.sh PHASE=all -> curate_tunableop_rows.py): four GPUs tuned in parallel, heuristic/current/new measured in one session, curated with the 3% adopt and 3% drop margins. 4 new, 40 current, 26 dropped of 70 shapes -> 44 rows/rank. Lookup-hit proof: 44/44. The imported rows were not carried over: their solution IDs came from a different rocBLAS build, and solution IDs must never be reused across builds even when the version string matches. The import is preserved under `imported` in provenance.json. Honest result: the merge is close to a wash. Measured back-to-back in one session, the imported rows, the same-build capture and this curated set all land within 0.9% of each other, and all are ~4% faster than the rocBLAS heuristic on median. What this change actually fixes is that the profile could not be auto-selected at all. Caveat recorded in the README: same-session repeats agree to ~0.3% median, but the same row set drifts 5-10% across sessions, which exceeds the 3% margins. Curation is only meaningful within one session.
wsantos
force-pushed
the
tunableop/profile-rocblas-d05939967b5f
branch
from
October 12, 2026 23:17
180e14c to
9566ee5
Compare
…> 128 rows)
The 2026-10-12 campaign tuned only the prefill grid (M = 800..8192), so on this
build every M <= 32 shape fell back to rocBLAS heuristics. The canonical
rocm7.14-rocblas5.5 profile carries the decode (M <= 8) and MTP-verify
(M = 16/24/32) shapes; this profile did not. That is the gap this fills.
Built with the recipe in tunableop/README.md, service stopped, campaign written
to the sanctioned per-user location (never /tmp or the CWD):
tune_v620_fp16.py --output-root $HOME/.cache/tunableop/campaign-decode \
--batch-tokens 1 2 3 4 5 6 7 8 12 16 24 32
qualify_v620_fp16.py $HOME/.cache/tunableop/campaign-decode/rocblas-d05939967b5f
* 84/84 keys produced; 84/84 passed on devices 0-3 against FP32 references.
* Solver mix 81 Gemm_Rocblas_*, 3 Default (heuristic won for tn_4096_8,
tn_3584_7, tn_3584_8).
* Per-shape speedup over the heuristic 1.4x to 3.6x, largest on the K=320 and
K=10240 shapes (3.57x at M=16, n=10240, k=320).
Merged into the build's folder (one folder per rocBLAS build, per the storage
policy): 44 prefill + 84 decode/MTP = 128 rows/rank, key sets disjoint.
Lookup-hit proof re-run on the merged set: 128/128, 0 misses.
tests/tools/test_v620_tuning_coverage.py: 4 passed + 2 subtests.
Caveat recorded in provenance: these 84 rows are raw tuned, not curated -- the
prefill campaign's adopt/drop margins need a same-session
heuristic-vs-current-vs-new comparison, which was not run here.
Assisted-by: pi-coding-agent
Signed-off-by: Waldecir Santos <waldecir@gmail.com>
…6/512 chunks The coverage checker reported 7 of the 14 shapes the live config needs (block 1024, max-num-batched-tokens 2048) as missing, and the 26 prefill shapes the 2026-10-12 curation dropped had never been re-tested: tools/rdna2_028/tunableop_rows_pipeline.sh only tunes the shapes present in --shape-source, so a dropped shape is never revisited. Re-measured all 168 shapes (7 dense shapes x 12 prefill M + 84 decode/MTP) on build d05939967b5f, heuristic/current/new in one session: - The 7 live-grid holes stay holes. A fresh tune does not beat the rocBLAS heuristic on any of them, so a row there buys nothing and an explicit Default row would only silence the warning. The warning is telling the truth. - The real gap was one the checker cannot express: the live launcher sets VLLM_RDNA_DYNAMIC_PREFILL=1, whose chunk-cap ladder is RUNGS=(256,512,1024), and the scheduler sets num_new_tokens = long_prefill_token_threshold whenever more than one request is eligible. At >=4 eligible requests a 512-token chunk reaches the GEMMs and there was no row for M=256/512 at all. 11 rows added; the large-K shapes gain 4x (10240x2560 4.33 -> 1.22 ms, 336x10240 1.05 -> 0.24 ms) because the heuristic only reaches ~6 TFLOPS there where the tuned solver reaches ~22. - 2 shipped prefill rows replaced by a different, faster solver. Two more adopt decisions carried the same solver id as the shipped row (same-session noise) and were rejected. - 18 decode/MTP rows (M=2..8) measured 10-77% slower than the heuristic, but that region is launch-bound (identical shape families flip sign between M=1 and M=2, on ~14 MFLOP GEMMs timed at 80-240 us), so the decode grid is left byte-identical and the deletion is deferred to a small-M measurement. 139 rows/rank = 55 prefill + 84 decode/MTP. 139/139 matched independent FP32 on all four devices, 139/139 lookup hits, 0 misses. Signed-off-by: Waldecir Santos <waldecir@gmail.com>
wsantos
added a commit
to wsantos/vllm-rdna
that referenced
this pull request
Oct 14, 2026
…-row set The full-grid re-measure landed the data but left the two row counts at 128 and omitted the campaign section. Same content as the tunableop PR (opengfx1030#92), so merging that first collapses this branch's tunableop diff. Signed-off-by: Waldecir Santos <waldecir@gmail.com>
This was referenced Oct 14, 2026
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.
Qualifies the
rocm10-rocblas5.6profile against the build this box actually loads, and then fills the two shape families it was still missing: the decode/MTP grid and the 256/512-token chunk family the live dynamic-prefill controller can put on the wire. 44 → 139 rows/rank.Why this is not duplicating an existing PR
gh pr list --repo opengfx1030/vllm-rdna --state open --search "tunableop"returns #92 (this), #35, #74, #87 and #99.changedFiles: 0— empty placeholders describing this work, not implementations. They were checked withgh issue view 74 --comments(0 comments) andgh pr list --search. followup: TunableOp rows for MTP=2 verify-batch GEMM keys (M∈{3,6,12,24}) #35's keys and more are covered below; [backlog] perf(rdna): retune the 6 TunableOp rows slower than the heuristic #74's premise is measured below.tools/rdna2_028campaign drivers. This PR uses those drivers; the two do not overlap.tunableop/commits alongside unrelated QSA/GDN HIP prefill work. Thetunableop/trees are now byte-identical (git diff --stat tunableop/is empty), so merging this PR first makes perf(rdna2): QSA/GDN HIP prefill paths vs Triton/FLA + TunableOp decode/MTP grid (implements #64) #99's tunableop portion collapse out of its diff. This PR is the one to review for the profile.1. The bug: the profile could not be auto-selected
The profile recorded
lib_sha256 = c27e2252cc7a, a retired build. The loaded library isd05939967b5f— and the system/opt/rocm/core-10.0copy and the venv_rocm_sdk_librariescopy are byte-identical on this box, so both resolve to the same build. With no matching profile,configure_tunableopwarned and fell back to the per-user path; the rows were reachable only through the legacyrocblas-<hash>/directory. Per the storage policy (one named profile per rocBLAS build, nothing archived) that fallback directory is dropped — its contents are not shipped, and it is not committed.After the fix:
The imported rows are deliberately not carried over: their solution IDs came from a different build, and IDs must never be reused across builds even when the version string matches. The import is preserved under
importedinprovenance.json.2. Decode / MTP grid (44 → 128 rows)
The 2026-10-12 campaign tuned only the prefill grid (M = 800…8192), so every M ≤ 32 shape fell back to rocBLAS heuristics on this build — while the canonical
rocm7.14-rocblas5.5profile carries the decode (M ≤ 8) and MTP-verify (M = 16/24/32) shapes.3. The whole grid re-measured, and the 256/512-token chunk family (128 → 139)
tools/rdna2/check_v620_tuning.pyreported 7 of the 14 shapes the live cache/batch config needs as missing. The live launcher resolves to--block-size 1024 --max-num-batched-tokens 2048, so the chunks that actually run are M = 1024 and 2,048. Two deliberate mechanisms had kept them missing:tools/rdna2_028/tunableop_rows_pipeline.shtunes only the shapes present in--shape-source(so the 26 prefill shapes the curation dropped were never re-tested), andcurate_tunableop_rows.pyfoldsDefaultrows intodroppedby design.All 168 shapes (7 dense
(N,K)× 12 prefill M + the 84 decode/MTP rows) were re-tuned and then measured heuristic / current / new in one session.The 7 live-grid holes stay holes. A fresh tune does not beat the heuristic by 3 % on any of them (
10240x320,4096x2560,2560x1536,3584x2560at M=1024;10240x320,512x2560,10240x2560at M=2048), so a row there buys nothing. An explicitDefaultrow would only silence the coverage warning while pinning the shape against online tuning, so the warning is left as-is — it is telling the truth.The real gap was one the checker cannot express. The launcher sets
VLLM_RDNA_DYNAMIC_PREFILL=1, whose chunk-cap ladder isRUNGS = (256, 512, 1024)withLPT_SHARED = 512;scheduler.pysetsnum_new_tokens = long_prefill_token_thresholdwhenever more than one request is eligible, so at ≥4 eligible requests a 512-token chunk reaches the GEMMs (256 at 8). There was no row for M = 256/512 at all, andcheck_v620_tuning.pytakes only--block-size/--max-num-batched-tokens, so it cannot see that family.10240x2560336x1024010240x2560512x25602560x15363584x2560The tuned solver reaches ~22 TFLOPS on the large-K shapes where the heuristic manages ~6. 11 rows added; 2 shipped prefill rows replaced by a different faster solver (
10240x2560M=1024,2560x1536M=3200).Two traps worth recording. (a) Two further "adopt" decisions carried the same solver id as the shipped row — same-session noise, not a better kernel — and were rejected: only adopt when the solver actually changes. (b) 18 decode/MTP rows (M=2..8) measured 10–77 % slower than the heuristic, which looks damning, but that region is launch-bound: identical shape families flip sign between M=1 (row 22–58 % faster) and M=2..8, on ~14 MFLOP GEMMs timed at 80–240 µs. The decode grid is left byte-identical; deleting those rows needs a small-M measurement (no per-call sync, larger reps) first. This is the answer to #74's premise for the decode side: the rows it suspects are real, but the evidence used here cannot separate them from timer noise.
Result and verification
139 rows/rank = 55 prefill + 84 decode/MTP, one validated set on all four ranks.
python tools/rdna2/qualify_v620_fp16.py <dir>assert_closeatol/rtol 0.01)tools/rdna2_028/verify_lookup_hit.sh(DEVICE=3)python -m pytest tests/tools/test_v620_tuning_coverage.py -qauto-selected for rocBLAS build d05939967b5f, lookup enabled, tuning offNote
test_v620_tuning_coverage.pyasserts the warning path, so a green test is not a completeness proof — the coverage warning for the 7 live-grid shapes is deliberate and documented.Files
tunableop/profiles.jsonlib_sha256→d05939967b5f,rows_per_rank→ 139, status,coverstunableop/README.mdtunableop/rocm10-rocblas5.6/README.mdtunableop/rocm10-rocblas5.6/provenance.jsontunableop/rocm10-rocblas5.6/tunableop_results{0..3}.csvCaveats
tunableop/README.mdsays so explicitly.[dyn-prefill] ADJUSTline confirming a 512 cap.AI assistance was used to prepare this branch and description. Submitted by a human who has reviewed the change and is accountable for it.