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
[JIT] Check single-file tuned configs for duplicate shapes - #6365
The duplicate-shape check in update_config_files only ran when a family had
more than one table to merge. Two short-circuits kept single-table families out
of it entirely:
get_config_file returns the canonical aiter/configs/<name>.csv untouched
when model_configs/ has no matching sibling, so update_config_files is
never called.
update_config_files returns early on a one-element path list.
A family that never grows a per-model table was therefore never validated. A
lone CSV can still hold two rows with the same key, which is what happens when
a retune is appended instead of replacing the existing row.
aiter/configs/tuned_grouped_fmoe.csv was in exactly that state: two rows for gfx1250 / token=512 / model_dim=7168 / inter_dim=3072 differing only in tuning
parameters. The row was removed in #6332, but the mechanism that let it through
was not changed, so test_config_shape_collision.py::test_grouped_fmoe stayed
green throughout — it drives a resolution path that never reached the check.
6 of the 18 registered families currently resolve through this unchecked path
Technical Details
Extract the check into _dedup_or_raise and call it from both the merge path
and the single-file path, so the key derivation, the error text, and the
keep-lowest-us write-back stay in one place. env_name is threaded through,
so the newly covered paths still name the AITER_CONFIG_* variable in their
error (#6307).
Behavior
The only intended change is that a duplicate in a single-table family is now
reported instead of silently accepted. Verified by running the same ten
scenarios against main and this branch and diffing the returned path, the
merged output, the exception type, the error text, and the source write-back:
Scenario
Result
Multi-file: clean / duplicate / no untuned schema
Byte-identical
Single file: clean / missing / header-only / no untuned schema / unparseable
Byte-identical
Single file: duplicate
passed through → RuntimeError
Single file: duplicate, no us column
passed through → RuntimeError
Note for deployments: a single-table family whose CSV already contains a
duplicate will now raise from get_config_file where it previously did not.
After #6332 no in-tree family is in that state.
_Mxfp8Config.update_config_files keeps its own single-path short-circuit —
that op validates individual rows in its loader — so its behavior is unchanged.
Test Plan
The existing self-checks only drove the cross-file merge: _build_synthetic_family
always wrote a model_configs/ sibling. Since removing the duplicate row makes test_grouped_fmoe green again without proving the check runs, the new controls
use synthetic trees and do not depend on repository data:
a duplicate planted in a lone CSV must be reported
two distinct shapes in a lone CSV must not be
an unparseable lone CSV must not raise out of get_config_file; this path
previously handed the file back unread, so the parse error surfaced from the
op's own loader, and reading it for the check must not move that failure
earlier or change its type
_build_synthetic_family takes with_model_file to select the path and canonical_raw for malformed input. _run_synthetic now catches Exception
rather than RuntimeError, because pandas' ParserError is a ValueError and
would otherwise escape as a test error instead of a readable assertion.
Confirmed by mutation testing that these fail for the right reason:
Mutation
Result
Revert the single-file check
Only the planted-duplicate control fails
Keep the check, drop the parse guard
Only the unparseable-CSV control fails
test_config_shape_collision.py 25 passed; 224 passed across test_mixed_mxfp_tuning, test_tuner_infra, test_csv_validation, and test_gemm_group32_interface
ATOM accuracy suite for PR and main models from ATOM models_accuracy.json
ci:vllm
vLLM benchmark: DeepSeek-V4-Pro, MiniMax-M3-MXFP4
ci:all
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 6365 --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.
github-actionsBot
changed the title
[Config] Check single-file tuned configs for duplicate shapes
[JIT] Check single-file tuned configs for duplicate shapes
Oct 10, 2026
The duplicate-shape check only ran when a family had more than one table
to merge. Two short-circuits kept single-file families out of it
entirely: get_config_file returns the canonical CSV untouched when
model_configs/ has no sibling, and update_config_files returns early on
a one-element path list. A family that never grows a per-model table was
therefore never validated, and a lone CSV can still hold two rows with
the same key when a retune is appended instead of replacing the old row.
aiter/configs/tuned_grouped_fmoe.csv was in exactly that state: two rows
for gfx1250 token=512 model_dim=7168 inter_dim=3072 differing only in
tuning parameters. The row was removed in ROCm#6332, but the mechanism that
let it through was not, and test_grouped_fmoe stayed green throughout
because the resolution path it drives never reached the check.
Extract the check into _raise_on_duplicate_shapes and call it from both
paths, so the key derivation, the error text, and the keep-lowest-us
write-back stay in one place. env_name is threaded through, so the paths
reached for the first time still name the AITER_CONFIG_* variable.
Only the single-file duplicate case changes behavior: it is now reported
instead of silently accepted. Multi-file merges, and single files that
are clean, missing, header-only or unparseable, resolve as before.
_Mxfp8Config.update_config_files keeps its own single-path short-circuit;
that op validates individual rows in its loader, so its behavior does not
change.
Signed-off-by: yzhou103 <yzhou103@amd.com>
The self-checks only drove the cross-file merge: _build_synthetic_family
always wrote a model_configs/ sibling, so the path where a family has no
sibling and resolves to its canonical CSV directly was never exercised.
That is the path that skipped the duplicate check, which is how
tuned_grouped_fmoe.csv kept a duplicate row (removed in ROCm#6332) while
every test here was green.
Removing the row makes test_grouped_fmoe green again without proving the
check runs, so add controls that do not depend on repository data:
- a duplicate planted in a lone CSV must be reported
- two distinct shapes in a lone CSV must not be
- an unparseable lone CSV must not raise out of get_config_file, since
this path used to hand the file back unread and the parse error
surfaced from the op's own loader
_build_synthetic_family takes with_model_file to choose the path and
canonical_raw for malformed input. _run_synthetic now catches Exception
rather than RuntimeError: pandas' ParserError is a ValueError, so the
malformed case has to be observable rather than escaping as a test error.
Verified by mutation: reverting the single-file check fails only the
first, and dropping the parse guard fails only the third.
Signed-off-by: yzhou103 <yzhou103@amd.com>
The dedup write-back runs before the RuntimeError that reports the
duplicates, so a source that cannot be written replaces that diagnostic
with a bare PermissionError. That drops the dedup key and the
AITER_CONFIG_* hint precisely in a read-only install or container, which
is the environment those were added for (ROCm#6307, ROCm#5184), and
abandons any remaining source half-rewritten.
Catch OSError per source, collect the failures, and report them under
"Not updated" without counting them as updated. The resolution line now
says not every file could be rewritten when that happened, so the message
cannot claim a write that did not land.
This affected merges before and now also affects lone config files, since
those reach the same write-back.
Reported by Copilot review.
Signed-off-by: yzhou103 <yzhou103@amd.com>
Handle unreadable untuned schemas like missing files
aiter/jit/core.py:465
The single-file parse guard does not cover this untuned-schema read. With a valid lone tuned CSV but an unreadable or malformed matching untuned CSV, get_config_file now raises OSError/ParserError; before this change it returned the tuned path without touching the untuned file. Treat an unreadable untuned schema like a missing one so the duplicate check does not introduce a new runtime failure.
Conflicts:
- aiter/aot/flydsl/mxfp4_moe.py: kept. The MXFP4 tuner's --fast-scan
(#6405) precompiles its candidates with jobs_from_rows and
compile_job_batch. It stays out of the AOT build, which replays these rows
through fused_moe; its docstring and the README say so.
- aiter/jit/core.py: #6365 moved the duplicate-shape check into
_raise_on_duplicate_shapes, shared with the single-file path. Comparing
key columns as numbers, so 256 and 256.0 stay one shape, and ordering on a
numeric `us` move there with it, and the single file is read as text like
the merged ones, so a dedup rewrite keeps every cell as written.
Signed-off-by: zhimding <zhimding@amd.com>
…m#6365)
- Document that _raise_on_duplicate_shapes now runs on both single-file
and multi-file paths (previously only cross-file merges were checked)
- Note graceful OSError handling for read-only containers
- Add _raise_on_duplicate_shapes to the references section
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
The duplicate-shape check in
update_config_filesonly ran when a family hadmore than one table to merge. Two short-circuits kept single-table families out
of it entirely:
get_config_filereturns the canonicalaiter/configs/<name>.csvuntouchedwhen
model_configs/has no matching sibling, soupdate_config_filesisnever called.
update_config_filesreturns early on a one-element path list.A family that never grows a per-model table was therefore never validated. A
lone CSV can still hold two rows with the same key, which is what happens when
a retune is appended instead of replacing the existing row.
aiter/configs/tuned_grouped_fmoe.csvwas in exactly that state: two rows forgfx1250 / token=512 / model_dim=7168 / inter_dim=3072differing only in tuningparameters. The row was removed in #6332, but the mechanism that let it through
was not changed, so
test_config_shape_collision.py::test_grouped_fmoestayedgreen throughout — it drives a resolution path that never reached the check.
6 of the 18 registered families currently resolve through this unchecked path
Technical Details
Extract the check into
_dedup_or_raiseand call it from both the merge pathand the single-file path, so the key derivation, the error text, and the
keep-lowest-
uswrite-back stay in one place.env_nameis threaded through,so the newly covered paths still name the
AITER_CONFIG_*variable in theirerror (#6307).
Behavior
The only intended change is that a duplicate in a single-table family is now
reported instead of silently accepted. Verified by running the same ten
scenarios against
mainand this branch and diffing the returned path, themerged output, the exception type, the error text, and the source write-back:
RuntimeErroruscolumnRuntimeErrorNote for deployments: a single-table family whose CSV already contains a
duplicate will now raise from
get_config_filewhere it previously did not.After #6332 no in-tree family is in that state.
_Mxfp8Config.update_config_fileskeeps its own single-path short-circuit —that op validates individual rows in its loader — so its behavior is unchanged.
Test Plan
The existing self-checks only drove the cross-file merge:
_build_synthetic_familyalways wrote a
model_configs/sibling. Since removing the duplicate row makestest_grouped_fmoegreen again without proving the check runs, the new controlsuse synthetic trees and do not depend on repository data:
get_config_file; this pathpreviously handed the file back unread, so the parse error surfaced from the
op's own loader, and reading it for the check must not move that failure
earlier or change its type
_build_synthetic_familytakeswith_model_fileto select the path andcanonical_rawfor malformed input._run_syntheticnow catchesExceptionrather than
RuntimeError, because pandas'ParserErroris aValueErrorandwould otherwise escape as a test error instead of a readable assertion.
Confirmed by mutation testing that these fail for the right reason:
test_config_shape_collision.py25 passed; 224 passed acrosstest_mixed_mxfp_tuning,test_tuner_infra,test_csv_validation, andtest_gemm_group32_interfaceTest Result
Submission Checklist