You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[HIP] [CI] [JIT] Add aiter.mqa_logits with a tuned Triton/FlyDSL table - #6185
vLLM's sparse indexer prefill calls the Triton/Gluon fp8_mqa_logits directly on gfx950. Moving it to the FlyDSL kernel from #4538 took a vLLM PR (vllm-project/vllm#59280), and so would every later switch. Like aiter.paged_mqa_logits for decode (#6140), this adds aiter.mqa_logits: the framework asks for MQA logits, and AITER picks the backend and FlyDSL variant from a tuned table, the way fused_moe does. The vLLM side is vllm-project/vllm#60294.
What it adds
mqa_logits(Q, KV, kv_scales, weights, cu_starts, cu_ends, clean_logits=True): takes the same tensors as fp8_mqa_logits and returns the same [seq_len, seq_len_kv] logits.
A tuned table keyed on (gfx, cu_num, heads, head_dim, seq_len, seq_len_kv). Both lengths are tensor sizes, so the lookup never reads device memory. A call uses the row with the largest tuned seq_len_kv not above its own, then the largest tuned seq_len not above its own; a length below every tuned one uses the smallest. Rows are looked up with the live GPU arch (get_gfx_runtime()).
Each row picks triton (the existing fp8_mqa_logits, Gluon on gfx950) or flydsl with a variant from KERNEL_VARIANTS.
A tuner. It checks every candidate against a torch reference before timing it, then re-times the three fastest interleaved and keeps the best median.
gfx950 rows for the GLM-5 indexer (H=32, D=128): 24 shapes, seq_len 256 to 8192 and seq_len_kv 4096 to 60000, limited to what vLLM produces (seq_len <= seq_len_kv, logits within the default 512 MB VLLM_SPARSE_INDEXER_MAX_LOGITS_MB).
Without a matching row it runs fp8_mqa_logits, so an empty table changes nothing. A FlyDSL row is only used where the kernel can run (gfx942/gfx950, the variant exists, native e4m3fn on gfx950); otherwise the call runs fp8_mqa_logits.
The CSVs are named like fused MoE's (tuned_mqa_logits.csv, model_configs/glm5_tuned_mqa_logits.csv). A mqa_logits_tuned name would also match paged_mqa_logits_tuned_*.csv in the model_configs glob.
Test Result
MI355X (gfx950), AITER 1a37aa008 with this change applied, Triton 3.8.0, FlyDSL 0.3.4.1.
FlyDSL wins all 24 shapes, mostly with mfma32x32x64_bkv128_r2_w4_lds3 (13 of 24).
Against Triton/Gluon, what vLLM runs on gfx950 today: -36.6% geomean, from -16.6% to -74.5%.
Every candidate matches torch (exact -inf mask, calc_diff < 1e-3); none was rejected.
op_tests/test_mqa_logits.py passes, including the live-GPU lookup check (child process started with the other arch in GPU_ARCHS), the dispatched-config check and the FlyDSL fallback.
--run_config: 24/24 within 10% on one pass, 22/24 on a second (the two smallest kernels, about 20 and 40 us, at +12%). Collision guard: OK.
With GPU_ARCHS naming another arch, the FlyDSL module builds its variant list for that arch at import, so a gfx950 FlyDSL row falls back to fp8_mqa_logits instead of failing.
Adds a new entry point, aiter.mqa_logits, for the sparse-indexer prefill. Today vLLM calls the Triton/Gluon fp8_mqa_logits directly, so every move to a faster kernel (such as the FlyDSL one) needs a vLLM PR. With this, AITER picks Triton or a FlyDSL variant per shape from a tuned table, the way fused_moe does. No existing op changes behavior: without a matching row, or when FlyDSL cannot run the row, the call runs fp8_mqa_logits as before. Strided kv_scales, cu_starts or cu_ends raise ValueError (neither backend reads their strides); a strided weights runs on Triton. The tuning CI workflow also learns the new tuner and uploads aiter/configs/model_configs/*.csv.
Validation and unverified scope
MI355X (gfx950, 256 CUs):
Tuner on 1a37aa0 + this change (FlyDSL 0.3.4.1, Triton 3.8.0): every candidate matched the torch reference (same -inf mask, calc_diff < 1e-3); FlyDSL won all 24 shapes, -36.6% geomean vs Triton/Gluon (table above).
python3 csrc/mqa_logits/mqa_logits_tune.py --run_config ...: 24/24 within 10% on one pass, 22/24 on a second (two kernels under 40 us at +12%).
python3 op_tests/test_mqa_logits.py passed at b8a6af0, including the strided-operand checks.
Unverified: 3d33634 only changes the expectation in check_dispatches_shipped_row and has not been run on a GPU yet (CI will run it). Not measured end to end in vLLM (that is vllm-project/vllm#60294). Not run on gfx942 or with the pinned FlyDSL 0.4.x. The tuning workflow change was not dispatched.
PR-specific question
operators-tuning.yaml is workflow_dispatch only, so it never runs on a pull request; only a maintainer with write access can start it, on a branch of ROCm/aiter, and fork PR code or text cannot trigger it. This PR adds no permissions, secrets or new inputs. It adds one fixed line to the tune_jobs list in op_tune.sh (a static command for the new tuner, no interpolated input) and one more path, aiter/configs/model_configs/*.csv, to the existing upload-artifact step, which keeps its 7-day retention.
Changed op tests
op_tests/test_mqa_logits.py (new): checks mqa_logits, Triton and FlyDSL (its built-in variant choice) against a torch reference on the default shapes; that the table lookup uses the live GPU (child process with another arch in GPU_ARCHS); that the shipped FlyDSL row is the config dispatched, or Triton when FlyDSL cannot run it; the FlyDSL-to-Triton fallback; and strided operands (strided weights match the reference, strided kv_scales raises). No other test covers aiter.mqa_logits.
op_tests/tuning_tests/test_config_shape_collision.py (+4): adds the tuned_mqa_logits family to the duplicate-key check across configs/ and model_configs/, which every other tuned family already has.
op_tests/tuning_tests/test_run_config.py (+9): adds the mqa_logits tuner to the shipped-row re-timing test, the same check every other tuner family has.
github-actionsBot
changed the title
[Triton][FlyDSL] Add aiter.mqa_logits with a tuned Triton/FlyDSL table
[HIP] [CI] [JIT] Add aiter.mqa_logits with a tuned Triton/FlyDSL table
Oct 6, 2026
All standard extended tests (excludes ci:atom_full)
Only add ci:atom_full for FlyDSL or Triton upgrades.
Add labels via the sidebar or gh pr edit 6185 --add-label <label>
One backend per PR:
A PR changes one kernel backend: [Triton/Gluon] (Triton and Gluon count as one), [HIP], [ASM], [CK], [OPUS] or [FlyDSL]. If the title ends up with two backend tags, split the PR -- as stacked pull requests when one part cannot merge without the other.
PR title tags & labels:
Component tags ([Triton/Gluon], [HIP], [CK], [ASM], ...) are added to the PR title and as PR labels automatically from the changed files and re-synced on every push — change-type tags like [fix]/[Perf], op tags like [MLA], and human labels (ci:*) are left untouched. Add the no-auto-title label to stop the title rewrites; labels stay in sync either way.
The reason will be displayed to describe this comment to others. Learn more.
Copilot review overview
🔵 Needs a closer look
FlyDSL compatibility checking can select a head-count-incompatible variant and raise instead of falling back to Triton.
Review effort: Balanced Findings: None
Previously missed (1)
In code that hasn't changed since last review
Validate variant head-count compatibility before custom kernel dispatch
aiter/mqa_logits.py:121
KERNEL_VARIANTS membership does not prove that a variant supports this head count. On gfx950 the registered MFMA_M=32 variants reject heads=16 in fp8_mqa_logits_kernels.py:409-420, so a custom tuned row for H=16 passes this predicate and then raises instead of taking the documented Triton fallback. Include the selected variant's head-count compatibility in this support check.
The reason will be displayed to describe this comment to others. Learn more.
🔵 Needs a closer look
Strided-weight correctness, fallback expectations, tuner failure reporting, and CI artifact retention need corrections.
0 open findings
Previously missed (4)
In code that hasn't changed since last review
Upload generated model configuration CSVs in CI
.github/scripts/op_tune.sh:22
This job writes results under aiter/configs/model_configs/, but .github/workflows/operators-tuning.yaml:116 uploads only aiter/configs/*.csv. The generated MQA table is therefore missing from the downloadable tuned-csvs artifact. Add aiter/configs/model_configs/*.csv to the workflow's upload paths so CI retains these results.
Make strided weights contiguous before FlyDSL dispatch
aiter/mqa_logits.py:161
Strided weights are passed unchanged to FlyDSL. For the shipped gfx950 row with 256 queries and 32 heads, weights = base[:, ::2] from a [256, 64] tensor is valid for Triton's stride-aware loads. However, FlyDSL's _load_row_weights uses row * H + head, and its wrapper only reshapes weights; this reads the wrong values. Make weights contiguous before the FlyDSL call to preserve the existing input contract.
Exit nonzero when tuning errors or interruptions occur
csrc/mqa_logits/mqa_logits_tune.py:282
Tuning errors can exit successfully here. If input/reference creation or finalist re-timing raises, TunerCommon.run catches the exception and calls tune_summary("Error") without adding a row to self.failed. This condition then returns normally, allowing CI to report incomplete tuning as successful. Exit nonzero for an error or interruption as well as recorded candidate failures.
Update operator expectation for FlyDSL fallback configurations
op_tests/test_mqa_logits.py:194
On a gfx950 GPU with 256 CUs, the shipped table selects FlyDSL even when that optional dependency is unavailable or its variant registry was built for another GPU_ARCHS value. The dispatcher correctly falls back to DEFAULT_CONFIG, but this assertion still expects the FlyDSL row, so the operator test rejects a supported fallback configuration. Adjust the expected dispatched config using flydsl_supports; keep the separate table-lookup check unchanged.
TunerCommon.run() catches the exception and calls tune_summary with status Error or Interrupted. With no failed row recorded, the script exited 0 and op_tune.sh reported a pass.
[P2] Allow the shipped-row check to expect a valid backend fallback. On gfx950 with 256 CUs, this assertion fails when FlyDSL is unavailable or GPU_ARCHS produces an incompatible variant registry, even though mqa_logits() correctly dispatches DEFAULT_CONFIG. Use flydsl_supports() with the same shapes and dtype as the dispatch probe to expect the tuned row only when supported, and DEFAULT_CONFIG otherwise.
The FlyDSL wrapper copies Q and KV to contiguous but only reshapes kv_scales, weights, cu_starts and cu_ends, and the kernel reads them as packed rows. A weights view with row stride 2H gave calc_diff 0.95 on the shipped (256, 4096) FlyDSL row. mqa_logits() now sends any strided one of these to Triton, which takes strides, instead of copying it; run_mqa_logits() raises ValueError for them on FlyDSL. The test checks a strided weights view against the fp32 reference.
Mock FlyDSL support for the table-to-launcher assertion
op_tests/test_mqa_logits.py:193
On gfx950 with GPU_ARCHS=gfx942, or when FlyDSL is unavailable, mqa_logits() correctly dispatches DEFAULT_CONFIG instead of the shipped FlyDSL row. This unconditional assertion then fails before the fallback and numerical checks run. Mock flydsl_supports to return true for this table-to-launcher check, restoring it afterward, and leave unsupported-backend behavior to the separate fallback test.
Triton takes the strides of weights only; it reads kv_scales, cu_starts and cu_ends as packed, like FlyDSL. The previous commit sent all four to Triton when strided, so a strided scale or window array was still misread. run_mqa_logits now raises ValueError for those three on both backends; a strided weights still runs on Triton. The test checks a kv_scales[::2] view is rejected.
The reason will be displayed to describe this comment to others. Learn more.
🔵 Needs a closer look
The GPU dispatch and tuned selections still need independent hardware validation, and the shipped-row test must account for supported fallback conditions.
No open issues 🎉
1 previously missed issue
In code that hasn't changed since last review
Avoid requiring unavailable FlyDSL in gfx950 operator test
op_tests/test_mqa_logits.py:194
On gfx950 with 256 CUs, this assertion requires FlyDSL even when it is unavailable or its registry was built for another GPU_ARCHS. The shipped row still says flydsl, but mqa_logits() correctly downgrades it to DEFAULT_CONFIG, so the operator test fails before reaching the fallback and numerical checks. Derive the expected dispatched config using the same support conditions, or skip this FlyDSL-specific assertion when the shipped variant cannot run.
PASS — current-SHA answers are present and structurally specific
Show the author's self-review answers
Behavior and intent
Adds a new entry point, `aiter.mqa_logits`, for the sparse-indexer prefill. Today vLLM calls the Triton/Gluon `fp8_mqa_logits` directly, so every move to a faster kernel (such as the FlyDSL one) needs a vLLM PR. With this, AITER picks Triton or a FlyDSL variant per shape from a tuned table, the way `fused_moe` does. No existing op changes behavior: without a matching row, or when FlyDSL cannot run the row, the call runs `fp8_mqa_logits` as before. Strided `kv_scales`, `cu_starts` or `cu_ends` raise `ValueError` (neither backend reads their strides); a strided `weights` runs on Triton. The tuning CI workflow also learns the new tuner and uploads `aiter/configs/model_configs/*.csv`.
Validation and unverified scope
MI355X (gfx950, 256 CUs):
- Tuner on 1a37aa008 + this change (FlyDSL 0.3.4.1, Triton 3.8.0): every candidate matched the torch reference (same `-inf` mask, `calc_diff < 1e-3`); FlyDSL won all 24 shapes, -36.6% geomean vs Triton/Gluon (table above).
- `python3 csrc/mqa_logits/mqa_logits_tune.py --run_config ...`: 24/24 within 10% on one pass, 22/24 on a second (two kernels under 40 us at +12%).
- `python3 op_tests/test_mqa_logits.py` passed at b8a6af0, including the strided-operand checks.
- `python3 -m unittest op_tests.tuning_tests.test_config_shape_collision.TestConfigShapeCollision.test_mqa_logits`: passed.
Unverified: 3d33634 only changes the expectation in `check_dispatches_shipped_row` and has not been run on a GPU yet (CI will run it). Not measured end to end in vLLM (that is vllm-project/vllm#60294). Not run on gfx942 or with the pinned FlyDSL 0.4.x. The tuning workflow change was not dispatched.
PR-specific question
`operators-tuning.yaml` is `workflow_dispatch` only, so it never runs on a pull request; only a maintainer with write access can start it, on a branch of ROCm/aiter, and fork PR code or text cannot trigger it. This PR adds no permissions, secrets or new inputs. It adds one fixed line to the `tune_jobs` list in `op_tune.sh` (a static command for the new tuner, no interpolated input) and one more path, `aiter/configs/model_configs/*.csv`, to the existing `upload-artifact` step, which keeps its 7-day retention.
Changed op tests
- `op_tests/test_mqa_logits.py` (new): checks `mqa_logits`, Triton and FlyDSL (its built-in variant choice) against a torch reference on the default shapes; that the table lookup uses the live GPU (child process with another arch in `GPU_ARCHS`); that the shipped FlyDSL row is the config dispatched, or Triton when FlyDSL cannot run it; the FlyDSL-to-Triton fallback; and strided operands (strided `weights` match the reference, strided `kv_scales` raises). No other test covers `aiter.mqa_logits`.
- `op_tests/tuning_tests/test_config_shape_collision.py` (+4): adds the `tuned_mqa_logits` family to the duplicate-key check across `configs/` and `model_configs/`, which every other tuned family already has.
- `op_tests/tuning_tests/test_run_config.py` (+9): adds the `mqa_logits` tuner to the shipped-row re-timing test, the same check every other tuner family has.
PR state
PASS — pull request is marked ready for review
Copilot findings
PASS — no active Copilot finding lacks a substantive author reply
Code and op-test hygiene
PASS — no committed artifact or conflict marker detected
Required CI
PASS — Black: passed
PASS — Ruff: passed
PASS — Repository dependency: passed
PASS — Aiter Test Gate: passed
Shadow mode reports what would block but keeps the status successful. Set AITER_PR_SELF_REVIEW_MODE=enforce only after reviewing real false positives.
…fx950
Ask AITER for prefill MQA logits (ROCm/aiter#6185) and let its tuned table
pick the Triton/Gluon or FlyDSL kernel, instead of calling the Triton/Gluon
fp8_mqa_logits directly. Pass clean_logits=False like the Triton call
(vllm-project#51314). With an AITER that has no aiter.mqa_logits, the existing path
runs unchanged.
Signed-off-by: Sriram Kumar <sriramkumar.kishorekumar@amd.com>
amd-sriram
added a commit
to amd-sriram/vllm
that referenced
this pull request
Nov 5, 2026
…fx950
Ask AITER for prefill MQA logits (ROCm/aiter#6185) and let its tuned table
pick the Triton/Gluon or FlyDSL kernel, instead of calling the Triton/Gluon
fp8_mqa_logits directly. Pass clean_logits=False like the Triton call
(vllm-project#51314). With an AITER that has no aiter.mqa_logits, the existing path
runs unchanged.
Signed-off-by: Sriram Kumar <sriramkumar.kishorekumar@amd.com>
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
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.
Motivation
vLLM's sparse indexer prefill calls the Triton/Gluon
fp8_mqa_logitsdirectly on gfx950. Moving it to the FlyDSL kernel from #4538 took a vLLM PR (vllm-project/vllm#59280), and so would every later switch. Likeaiter.paged_mqa_logitsfor decode (#6140), this addsaiter.mqa_logits: the framework asks for MQA logits, and AITER picks the backend and FlyDSL variant from a tuned table, the wayfused_moedoes. The vLLM side is vllm-project/vllm#60294.What it adds
mqa_logits(Q, KV, kv_scales, weights, cu_starts, cu_ends, clean_logits=True): takes the same tensors asfp8_mqa_logitsand returns the same[seq_len, seq_len_kv]logits.(gfx, cu_num, heads, head_dim, seq_len, seq_len_kv). Both lengths are tensor sizes, so the lookup never reads device memory. A call uses the row with the largest tunedseq_len_kvnot above its own, then the largest tunedseq_lennot above its own; a length below every tuned one uses the smallest. Rows are looked up with the live GPU arch (get_gfx_runtime()).triton(the existingfp8_mqa_logits, Gluon on gfx950) orflydslwith avariantfromKERNEL_VARIANTS.seq_len256 to 8192 andseq_len_kv4096 to 60000, limited to what vLLM produces (seq_len <= seq_len_kv, logits within the default 512 MBVLLM_SPARSE_INDEXER_MAX_LOGITS_MB).Without a matching row it runs
fp8_mqa_logits, so an empty table changes nothing. A FlyDSL row is only used where the kernel can run (gfx942/gfx950, the variant exists, native e4m3fn on gfx950); otherwise the call runsfp8_mqa_logits.The CSVs are named like fused MoE's (
tuned_mqa_logits.csv,model_configs/glm5_tuned_mqa_logits.csv). Amqa_logits_tunedname would also matchpaged_mqa_logits_tuned_*.csvin themodel_configsglob.Test Result
MI355X (gfx950), AITER
1a37aa008with this change applied, Triton 3.8.0, FlyDSL 0.3.4.1.mfma32x32x64_bkv128_r2_w4_lds3(13 of 24).-infmask,calc_diff < 1e-3); none was rejected.op_tests/test_mqa_logits.pypasses, including the live-GPU lookup check (child process started with the other arch inGPU_ARCHS), the dispatched-config check and the FlyDSL fallback.--run_config: 24/24 within 10% on one pass, 22/24 on a second (the two smallest kernels, about 20 and 40 us, at +12%). Collision guard: OK.GPU_ARCHSnaming another arch, the FlyDSL module builds its variant list for that arch at import, so a gfx950 FlyDSL row falls back tofp8_mqa_logitsinstead of failing.python3 csrc/mqa_logits/mqa_logits_tune.py \ -i aiter/configs/model_configs/glm5_untuned_mqa_logits.csv \ -o aiter/configs/model_configs/glm5_tuned_mqa_logits.csv python3 csrc/mqa_logits/mqa_logits_tune.py --run_config aiter/configs/model_configs/glm5_tuned_mqa_logits.csv python3 op_tests/test_mqa_logits.py python3 -m unittest op_tests.tuning_tests.test_config_shape_collision.TestConfigShapeCollision.test_mqa_logitsAll 24 shapes (us, single sweep timings; FlyDSL auto = the variant
flydsl_fp8_mqa_logitspicks by itself)mfma32x32x64_bkv64_r1_w2_lds2mfma32x32x64_bkv64_r2_w2_lds3mfma32x32x64_bkv128_r2_w4_lds3mfma32x32x64_bkv128_r2_w4_lds3mfma32x32x64_bkv64_r2_w2_lds2mfma32x32x64_bkv128_r2_w4_lds3mfma32x32x64_bkv64_r2_w4_lds3mfma32x32x64_bkv128_r2_w4_lds3mfma32x32x64_bkv64_r2_w4_lds3mfma32x32x64_bkv128_r2_w4_lds3mfma32x32x64_bkv64_r2_w4_lds3mfma32x32x64_bkv128_r2_w4_lds3mfma32x32x64_bkv128_r2_w4_lds3mfma32x32x64_bkv128_r2_w4_lds3mfma32x32x64_bkv128_r2_w4_lds3mfma32x32x64_bkv128_r2_w4_lds3mfma32x32x64_bkv128_r2_w4_lds3mfma32x32x64_bkv128_r2_w4_lds2mfma32x32x64_bkv64_r2_w4_lds3mfma32x32x64_bkv128_r2_w4_lds3mfma32x32x64_bkv128_r2_w4_lds2mfma32x32x64_bkv64_r2_w4_lds3mfma32x32x64_bkv128_r2_w4_lds3mfma32x32x64_bkv128_r2_w4_lds2PR Self-Review
Reviewed revision
3d33634
Behavior and intent
Adds a new entry point,
aiter.mqa_logits, for the sparse-indexer prefill. Today vLLM calls the Triton/Gluonfp8_mqa_logitsdirectly, so every move to a faster kernel (such as the FlyDSL one) needs a vLLM PR. With this, AITER picks Triton or a FlyDSL variant per shape from a tuned table, the wayfused_moedoes. No existing op changes behavior: without a matching row, or when FlyDSL cannot run the row, the call runsfp8_mqa_logitsas before. Stridedkv_scales,cu_startsorcu_endsraiseValueError(neither backend reads their strides); a stridedweightsruns on Triton. The tuning CI workflow also learns the new tuner and uploadsaiter/configs/model_configs/*.csv.Validation and unverified scope
MI355X (gfx950, 256 CUs):
-infmask,calc_diff < 1e-3); FlyDSL won all 24 shapes, -36.6% geomean vs Triton/Gluon (table above).python3 csrc/mqa_logits/mqa_logits_tune.py --run_config ...: 24/24 within 10% on one pass, 22/24 on a second (two kernels under 40 us at +12%).python3 op_tests/test_mqa_logits.pypassed at b8a6af0, including the strided-operand checks.python3 -m unittest op_tests.tuning_tests.test_config_shape_collision.TestConfigShapeCollision.test_mqa_logits: passed.Unverified: 3d33634 only changes the expectation in
check_dispatches_shipped_rowand has not been run on a GPU yet (CI will run it). Not measured end to end in vLLM (that is vllm-project/vllm#60294). Not run on gfx942 or with the pinned FlyDSL 0.4.x. The tuning workflow change was not dispatched.PR-specific question
operators-tuning.yamlisworkflow_dispatchonly, so it never runs on a pull request; only a maintainer with write access can start it, on a branch of ROCm/aiter, and fork PR code or text cannot trigger it. This PR adds no permissions, secrets or new inputs. It adds one fixed line to thetune_jobslist inop_tune.sh(a static command for the new tuner, no interpolated input) and one more path,aiter/configs/model_configs/*.csv, to the existingupload-artifactstep, which keeps its 7-day retention.Changed op tests
op_tests/test_mqa_logits.py(new): checksmqa_logits, Triton and FlyDSL (its built-in variant choice) against a torch reference on the default shapes; that the table lookup uses the live GPU (child process with another arch inGPU_ARCHS); that the shipped FlyDSL row is the config dispatched, or Triton when FlyDSL cannot run it; the FlyDSL-to-Triton fallback; and strided operands (stridedweightsmatch the reference, stridedkv_scalesraises). No other test coversaiter.mqa_logits.op_tests/tuning_tests/test_config_shape_collision.py(+4): adds thetuned_mqa_logitsfamily to the duplicate-key check acrossconfigs/andmodel_configs/, which every other tuned family already has.op_tests/tuning_tests/test_run_config.py(+9): adds themqa_logitstuner to the shipped-row re-timing test, the same check every other tuner family has.