Skip to content

Rewriter: fix cast_constant_of_shape for values outside the target range - #3153

Open
Lim Jooyoung (mmporong) wants to merge 1 commit into
microsoft:mainfrom
mmporong:cast-constant-of-shape-out-of-range
Open

Lim Jooyoung (mmporong) wants to merge 1 commit into
microsoft:mainfrom
mmporong:cast-constant-of-shape-out-of-range

Conversation

@mmporong

Copy link
Copy Markdown

fused_cast_constant_of_shape reads the ConstantOfShape value with .item() and builds the new tensor from that Python scalar. When the value does not fit the Cast target type, NumPy 2 raises OverflowError (for example 300 or -1 cast to UINT8, or 200 cast to INT8), so rewriter.rewrite() and optimizer.optimize() fail on the whole model. Cast itself runs fine on such a graph: ONNX Runtime turns 300 into 44 and -1 into 255.

This casts the NumPy array (astype to the target dtype) instead of going through a Python scalar, so the fused constant holds the same value that Cast produces. np.errstate(invalid="ignore") keeps NumPy from warning on float values outside an integer range. Values inside the range are unchanged.

This touches the replacement function only; open PR #3145 adds a check to the same rule for string targets and reference attributes, so the two do not overlap in code.

Testing:

  • New parametrized test in _cast_constant_of_shape_test.py (int32 300 -> UINT8, int32 -1 -> UINT8, int64 200 -> INT8) checks that the rule applies and that the fused value equals the NumPy cast. All three raise OverflowError on main and pass with this change.
  • onnxscript/rewriter/rules/common: 352 passed, 1 skipped (349 before, plus the 3 new cases).
  • Outside the test suite, I compared ONNX Runtime (CPU) outputs of the model before and after the rewrite for 8 cases, including float to integer (-1.5 -> UINT8, 3.7 -> INT32, 1e10 -> INT32), 70000 -> INT16 and 2.5 -> FLOAT16. All 8 match.
  • ruff check and ruff format --check (0.15.8, from the lintrunner requirements) pass on both files. I did not run the full lintrunner (mypy, etc.).

fused_cast_constant_of_shape converted the scalar with .item() and built
a new tensor from the Python value, which raises OverflowError for values
outside the target range (for example 300 or -1 cast to UINT8), so the
whole rewrite or optimize pass failed. Cast the numpy array instead,
which wraps the value the same way the Cast op does at runtime.

This branch has not been deployed

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

Labels

None yet

Projects

Development

Successfully merging this pull request may close these issues.

1 participant