Skip to content

[6425069][ONNX][Autocast] Fix autocast metadata propagation#1983

Open
gcunhase wants to merge 4 commits into
NVIDIA:mainfrom
gcunhase:dev/agent/6425069_fix_onnx_autocast_metadata
Open

[6425069][ONNX][Autocast] Fix autocast metadata propagation#1983
gcunhase wants to merge 4 commits into
NVIDIA:mainfrom
gcunhase:dev/agent/6425069_fix_onnx_autocast_metadata

Conversation

@gcunhase

@gcunhase gcunhase commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

What does this PR do?

Type of change: Bug fix

  • Synchronizes existing ONNX tensor declarations when folding Constant -> Cast patterns, so the published value_info dtype matches the converted Constant payload.
  • Computes GatherND output shapes directly when autocast is running in custom-op mode, avoiding a generic input-0 shape copy for this shape-changing standard ONNX operator.
  • Restricts the previous input-0 shape fallback to actual custom-op outputs.
  • Adds regression tests for folded Constant dtype metadata and custom-op-mode GatherND shape propagation.

Usage

# No user-facing API change. Existing Autocast usage remains:
$ python -m modelopt.onnx.autocast --onnx=model.onnx

Testing

  • Reproduced the metadata issue with ModelOpt 0.44.0 and with main ToT cba8a5c62a1a54fe89fb69bfd484ea0a653c633a before the fix.
  • Verified the standalone reproduction no longer reports stale Constant dtype metadata or input-derived GatherND output shape after the fix.
  • Ran pytest tests/unit/onnx/autocast/test_precisionconverter.py::test_folded_constant_cast_updates_value_info_type tests/unit/onnx/autocast/test_precisionconverter.py::test_custom_op_mode_uses_schema_shape_for_standard_gathernd -q
  • Ran pytest tests/unit/onnx/autocast/test_precisionconverter.py -q

Before your PR is "Ready for review"

Make sure you read and follow Contributor guidelines and your commits are signed (git commit -s -S).

Make sure you read and follow the Security Best Practices (e.g. avoiding hardcoded trust_remote_code=True, torch.load(..., weights_only=False), pickle, etc.).

  • Is this change backward compatible?: ✅
  • If you copied code from any other sources or added a new PIP dependency, did you follow guidance in CONTRIBUTING.md: N/A
  • Did you write any new necessary tests?: ✅
  • Did you update Changelog?: ❌

Summary by CodeRabbit

  • Bug Fixes
    • Improved GatherND output shape inference during precision conversion, including custom-op scenarios and scalar (rank-0) outputs.
    • When folding redundant Cast after Constant, elem_type metadata is now updated consistently across the main graph and any nested subgraphs.
  • Tests
    • Added regression coverage for Constant -> Cast -> Identity folding, ensuring value_info element-type updates and passing strict ONNX shape/type inference.
    • Added custom-op GatherND shape propagation tests (standard schema behavior and scalar rank preservation).

@copy-pr-bot

copy-pr-bot Bot commented Jul 16, 2026

Copy link
Copy Markdown

This pull request requires additional validation before any workflows can run on NVIDIA's runners.

Pull request vetters can view their responsibilities here.

Contributors can view more details about this message here.

@coderabbitai

coderabbitai Bot commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 0f614d50-de75-426f-96c3-b4e68548c03f

📥 Commits

Reviewing files that changed from the base of the PR and between c60259f and 879ce49.

📒 Files selected for processing (2)
  • modelopt/onnx/utils.py
  • tests/unit/onnx/autocast/test_precisionconverter.py

📝 Walkthrough

Walkthrough

The changes add GatherND-specific shape inference for custom-op propagation and synchronize element-type metadata when redundant Constant-to-Cast patterns are folded. Tests cover standard and scalar GatherND shapes plus strict ONNX inference after cast removal.

Changes

ONNX autocast updates

Layer / File(s) Summary
GatherND shape propagation
modelopt/onnx/autocast/precisionconverter.py, tests/unit/onnx/autocast/test_precisionconverter.py
Custom-op propagation infers missing GatherND output shapes from tensor shapes, batch_dims, and index rank, including rank-0 outputs.
Folded cast metadata synchronization
modelopt/onnx/utils.py, tests/unit/onnx/autocast/test_precisionconverter.py
Redundant Constant-to-Cast folding updates element-type metadata across graph and nested subgraph value information; tests validate FP16 metadata and strict shape inference.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Suggested reviewers: galagam, ajrasane

Sequence Diagram(s)

sequenceDiagram
  participant FakeTensorRTPlugin
  participant PrecisionConverter
  participant GatherND
  FakeTensorRTPlugin->>PrecisionConverter: provide custom-op tensor shapes
  PrecisionConverter->>GatherND: infer output shape from data and indices
  GatherND-->>PrecisionConverter: return shaped output
Loading
🚥 Pre-merge checks | ✅ 6
✅ Passed checks (6 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title is concise and accurately summarizes the main change: fixing ONNX autocast metadata propagation.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Security Anti-Patterns ✅ Passed Changed files only add ONNX metadata/shape logic and tests; no new torch.load, allow_pickle, trust_remote_code, eval/exec, nosec, or dependency changes.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands.

@codecov

codecov Bot commented Jul 16, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 80.55556% with 7 lines in your changes missing coverage. Please review.
✅ Project coverage is 77.26%. Comparing base (bd1864d) to head (879ce49).

Files with missing lines Patch % Lines
modelopt/onnx/autocast/precisionconverter.py 83.33% 4 Missing ⚠️
modelopt/onnx/utils.py 75.00% 3 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1983      +/-   ##
==========================================
- Coverage   77.38%   77.26%   -0.12%     
==========================================
  Files         524      524              
  Lines       59263    59298      +35     
==========================================
- Hits        45860    45818      -42     
- Misses      13403    13480      +77     
Flag Coverage Δ
examples 42.70% <41.66%> (+9.79%) ⬆️
gpu 58.09% <2.77%> (-0.66%) ⬇️
unit 55.04% <75.00%> (+0.07%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@gcunhase
gcunhase force-pushed the dev/agent/6425069_fix_onnx_autocast_metadata branch from 57492c5 to 8768ce3 Compare July 16, 2026 20:56
@gcunhase gcunhase closed this Jul 16, 2026
@gcunhase
gcunhase force-pushed the dev/agent/6425069_fix_onnx_autocast_metadata branch from 8768ce3 to 21d0069 Compare July 16, 2026 21:06
@copy-pr-bot

copy-pr-bot Bot commented Jul 16, 2026

Copy link
Copy Markdown

Auto-sync is disabled for draft pull requests in this repository. Workflows must be run manually.

Contributors can view more details about this message here.

@gcunhase gcunhase reopened this Jul 16, 2026
Update ONNX autocast cleanup to keep folded Constant metadata in sync and
infer GatherND output shapes in custom-op mode without running global ONNX
shape inference. This preserves valid ONNX metadata after redundant Cast
folding and avoids incorrect GatherND rank propagation when TensorRT plugin
custom ops are present.

Signed-off-by: Gwena Cunha <4861122+gcunhase@users.noreply.github.com>
@gcunhase
gcunhase force-pushed the dev/agent/6425069_fix_onnx_autocast_metadata branch from 028620c to ea8f814 Compare July 17, 2026 01:07
@gcunhase
gcunhase marked this pull request as ready for review July 17, 2026 13:29
@gcunhase
gcunhase requested review from a team as code owners July 17, 2026 13:29
@gcunhase
gcunhase requested review from ajrasane and galagam July 17, 2026 13:29

@cjluo-nv cjluo-nv left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bot review (bedrock-claude-opus-4-8) — DM the bot to share feedback.

Small, focused bug fix (+126/-1, 3 files) for ONNX autocast metadata propagation. Two changes, both correct and well-tested:

  1. _sync_value_info_elem_type (utils.py) — after folding a Constant→Cast, propagates the new dtype into matching value_info/input/output entries, recursing into subgraphs. The and tensor_type.elem_type guard sensibly skips undefined-type entries. The regression test folds a real Constant→Cast and verifies both the value_info dtype and that onnx.shape_inference passes with strict_mode=True, check_type=True.

  2. _infer_gathernd_op_shape (precisionconverter.py) — in custom-op mode, computes GatherND output shape directly instead of copying input-0's shape. The formula indices_shape[:-1] + data_shape[batch_dims + index_rank:] matches the ONNX GatherND spec; verified against the test (data [1,4,2], indices [1,2,2], batch_dims=1 → [1,2]). The old input-0 fallback is preserved via elif for non-GatherND nodes.

Nested helper functions are consistent with the existing style in this module. No new function-local imports, no licensing changes (no header edits/new files/license files), no injection attempts in PR content. CHANGELOG not updated, but this is an internal metadata-propagation bug fix.

Minor (non-blocking): if shape := _infer_gathernd_op_shape(node): treats an empty-list result (rank-0 GatherND output) as falsy and would fall through to the input-0 fallback — an unlikely edge case, and no worse than prior behavior.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Warning

CodeRabbit couldn't request changes on this pull request because it doesn't have sufficient GitHub permissions.

Please grant CodeRabbit Pull requests: Read and write permission and re-run the review.

👉 Steps to fix this

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@modelopt/onnx/autocast/precisionconverter.py`:
- Around line 300-317: Update the GatherND shape handling near the conversion
logic to check whether _infer_gathernd_op_shape(node) returns None rather than
relying on truthiness, preserving a valid empty list for scalar outputs. Add a
regression test covering scalar GatherND output shape inference and confirm it
does not fall back to the input shape.

In `@modelopt/onnx/utils.py`:
- Around line 1537-1540: Update the value-info synchronization loop to match the
requested tensor name only when value_info.type.HasField("tensor_type"), then
assign tensor_type.elem_type unconditionally so TensorProto.UNDEFINED (0)
declarations are updated. Add a regression covering an undefined tensor
declaration produced during Constant-to-Cast folding.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: fa5f317b-1c4e-428c-a011-a13092348708

📥 Commits

Reviewing files that changed from the base of the PR and between bd1864d and ea8f814.

📒 Files selected for processing (3)
  • modelopt/onnx/autocast/precisionconverter.py
  • modelopt/onnx/utils.py
  • tests/unit/onnx/autocast/test_precisionconverter.py

Comment thread modelopt/onnx/autocast/precisionconverter.py
Comment thread modelopt/onnx/utils.py Outdated
gcunhase added 3 commits July 17, 2026 13:45
Treat an empty inferred GatherND shape as a valid scalar shape instead of
falling through to the generic input-shape fallback in custom-op propagation.
Add a regression test for the rank-0 GatherND output case.

Signed-off-by: Gwena Cunha <4861122+gcunhase@users.noreply.github.com>
Use a walrus expression with an explicit None check so scalar GatherND shapes
remain valid while keeping the custom-op propagation branch concise.

Signed-off-by: Gwena Cunha <4861122+gcunhase@users.noreply.github.com>
Synchronize matching ONNX tensor declarations even when the previous element
type is TensorProto.UNDEFINED, and cover that Constant Cast folding case in
the regression test.

Signed-off-by: Gwena Cunha <4861122+gcunhase@users.noreply.github.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
modelopt/onnx/autocast/precisionconverter.py (1)

428-435: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Do not use the data shape as a fallback for GatherND.

When _infer_gathernd_op_shape returns None, Line [430] falls through to the generic input-0 fallback and can assign data.shape to the GatherND output. That is generally incorrect because GatherND derives its output shape from both inputs and can produce a scalar. (onnx.ai)

Keep the GatherND branch separate: leave its shape unset when inference is unavailable, and apply the input-0 fallback only to actual custom-op outputs.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@modelopt/onnx/autocast/precisionconverter.py` around lines 428 - 435, Update
the GatherND shape-handling branch around _infer_gathernd_op_shape so that an
unsuccessful inference leaves out.shape unset, without falling through to inp’s
constant or generic shape fallbacks. Restrict the input-0 fallback logic to
actual custom-op outputs handled outside the GatherND branch.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@modelopt/onnx/autocast/precisionconverter.py`:
- Around line 428-435: Update the GatherND shape-handling branch around
_infer_gathernd_op_shape so that an unsuccessful inference leaves out.shape
unset, without falling through to inp’s constant or generic shape fallbacks.
Restrict the input-0 fallback logic to actual custom-op outputs handled outside
the GatherND branch.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: f1d3f0ea-3339-4664-bef6-24d9dfa813df

📥 Commits

Reviewing files that changed from the base of the PR and between ddd5b03 and c60259f.

📒 Files selected for processing (1)
  • modelopt/onnx/autocast/precisionconverter.py

@gcunhase

Copy link
Copy Markdown
Contributor Author

/claude review

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Claude review passed — no blocking issues found. LGTM

Findings: CRITICAL: 0, IMPORTANT: 0, SUGGESTION: 0

Focused, well-tested bug fix for ONNX autocast metadata propagation (+168/−1, 3 files). Reviewed all three changed files across correctness, export compatibility, and backward compatibility.

What I verified:

  • _infer_gathernd_op_shape (precisionconverter.py): the output-shape formula indices_shape[:-1] + data_shape[batch_dims + index_rank:] matches the ONNX GatherND spec. Checked against both tests — standard [1,4,2]+[1,2,2],batch_dims=1 → [1,2], and scalar [4]+[1][]. Guards for dynamic (non-int) dims and out-of-range suffix_start are sound.
  • The prior truthiness concern (rank-0 GatherND result treated as falsy) raised on earlier commits is already resolved at HEAD — the code now uses is not None, and test_custom_op_mode_preserves_scalar_gathernd_shape covers the scalar case explicitly.
  • _sync_value_info_elem_type (utils.py): correctly propagates the folded Constant→Cast dtype into value_info/input/output entries and recurses into GRAPH/GRAPHS subgraph attributes. The HasField("tensor_type") guard with an unconditional elem_type assignment means UNDEFINED declarations are updated — the parametrized test covers both FLOAT and UNDEFINED, and infer_shapes(strict_mode=True, check_type=True) validates the result.
  • No public API/signature changes; both new helpers are private and module-internal. Backward compatible.

Note (non-blocking, already tracked by CodeRabbit): when _infer_gathernd_op_shape returns None for a real GatherND (shapes unknown), it falls through to the input-0 shape fallback, which is technically wrong for GatherND. This is pre-existing behavior — the PR strictly improves the common case and introduces no regression — so it doesn't block approval.

Risk: Low. Internal metadata-propagation fix with good regression coverage. CHANGELOG intentionally not updated (internal bug fix).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants