Skip to content

Conversation

@galagam
Copy link
Contributor

@galagam galagam commented Dec 22, 2025

What does this PR do?

Type of change: New feature

Overview:
AutoCast runs full type inference to get the new types after adding casts. ONNX doesn't have a separate function for type inference, and it is done as part of shape inference. Shape inference is a much more complex task than type inference, especially when dynamic shapes are involved. We're seeing some shape inference related bugs in AutoCast. Typically we can WAR, but it's cumbersome. A local implementation might allow users to WAR shape inference related issues. This is opt-in and marked as experimental.

Usage

python -m modelopt.onnx.autocast --onnx_path /path/to/input.onnx [options] --use_standalone_type_inference

Testing

Added use_standalone_type_inference=True to all existing PrecisionConverter tests.

Before your PR is "Ready for review"

  • Make sure you read and follow Contributor guidelines and your commits are signed.
  • Is this change backward compatible?: Yes
  • Did you write any new necessary tests?: Yes
  • Did you add or update any necessary documentation?: Yes
  • Did you update Changelog?: Yes

Additional Information

A more permanent fix would be to decouple type and shape inference in ONNX, we should invest in that when we have the resources - see onnx/onnx#7100
. This is a quick fix, which is also why it is opt-in and not the default mode.

@copy-pr-bot
Copy link

copy-pr-bot bot commented Dec 22, 2025

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.

@codecov
Copy link

codecov bot commented Dec 22, 2025

Codecov Report

❌ Patch coverage is 69.45607% with 73 lines in your changes missing coverage. Please review.
✅ Project coverage is 74.62%. Comparing base (03dc386) to head (28365ea).
⚠️ Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
modelopt/onnx/utils.py 67.94% 67 Missing ⚠️
modelopt/onnx/autocast/precisionconverter.py 82.60% 4 Missing ⚠️
modelopt/onnx/autocast/convert.py 66.66% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #719      +/-   ##
==========================================
- Coverage   74.69%   74.62%   -0.08%     
==========================================
  Files         192      192              
  Lines       18946    19169     +223     
==========================================
+ Hits        14152    14305     +153     
- Misses       4794     4864      +70     

☔ View full report in Codecov by Sentry.
📢 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.

Signed-off-by: Gal Hubara Agam <[email protected]>
@galagam galagam marked this pull request as ready for review December 25, 2025 07:39
@galagam galagam requested review from a team as code owners December 25, 2025 07:39
@galagam galagam requested review from ajrasane and gcunhase December 25, 2025 07:39
@galagam galagam changed the title Draft: AutoCast local implementation for type inference [5750013][5591945][5360813]: AutoCast local implementation for type inference Dec 25, 2025
@galagam galagam force-pushed the feat/local-type-infer branch from a659cad to 7caedc7 Compare December 25, 2025 07:51
@galagam galagam changed the title [5750013][5591945][5360813]: AutoCast local implementation for type inference [5750013][5591945][5360813]: AutoCast standalone implementation for type inference Dec 25, 2025
@ajrasane
Copy link
Contributor

ajrasane commented Jan 9, 2026

This is not related to this PR, but a shape inference issue I encountered previously. It was happening due to using strict mode in shape inference. Would it be possible to not use the strict mode and use the default mode itself?

Comment on lines +139 to +142
if use_standalone_type_inference:
model = onnx_utils.infer_types(model)
else:
model = onnx_utils.infer_shapes(model)
Copy link
Contributor

Choose a reason for hiding this comment

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

Could you create a util function for this as it is reused in multiple places?

Comment on lines +321 to +324
if not self.use_standalone_type_inference:
for idx, d in enumerate(inp.type.tensor_type.shape.dim):
if d.dim_value:
inp.type.tensor_type.shape.dim[idx].dim_param = "unk"
Copy link
Contributor

Choose a reason for hiding this comment

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

Similarly for this, can we create a util function?

return vi.type.tensor_type.elem_type
return None

def str_to_tensor_dtype(dtype_str: str) -> onnx.TensorProto.DataType:
Copy link
Contributor

Choose a reason for hiding this comment

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

We have a smaller subset of this mapping here:


Would it be possible to update/reuse this?

node_name_to_onnx = {node.name: node for node in graph.node}

# Get nodes to process (from graphsurgeon if available, otherwise from graph directly)
if gs_graph is not None:
Copy link
Contributor

Choose a reason for hiding this comment

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

Should we convert the graph back to an onnx graph to avoid this logic?

Comment on lines +867 to +868
if not inp_name:
continue
Copy link
Contributor

Choose a reason for hiding this comment

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

Do we expect any inputs with empty names?

Comment on lines +934 to +937
for attr in node.attribute:
if attr.name == "value" and attr.type == onnx.AttributeProto.TENSOR:
if attr.t.HasField("data_type"):
const_type = attr.t.data_type
Copy link
Contributor

Choose a reason for hiding this comment

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

This pattern is used in multiple places in our codebase, should we create a utility function for it?

tensor_types[init_name] = init.data_type

# Helper function to get tensor type
def get_tensor_type(tensor_name: str) -> int | None:
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we re-use _get_tensor_type() in modelopt.onnx.utils.py or, if not, move this function to modelopt.onnx.utils.py as _get_tensor_type_from_tensor_name or a variation of that?

return vi.type.tensor_type.elem_type
return None

def str_to_tensor_dtype(dtype_str: str) -> onnx.TensorProto.DataType:
Copy link
Contributor

Choose a reason for hiding this comment

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

This can be replaced by onnx_type_str_to_enum() in modelopt.onnx.utils.

break
assert const_type is not None
output_types = [const_type]
elif node.op_type == "ConstantOfShape":
Copy link
Contributor

Choose a reason for hiding this comment

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

Would this PR fix the issue in bug 5763424?

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.

3 participants