CastCast rewrite changes rounding for DOUBLE inputs by removing the FLOAT intermediate

オープン
#3,204 コメント 0 件 リアクション 0 件 担当者 0 名 GitHub で見る

メンテナーはふだん 2 日以内に返信

@itsrayeedscodespace がすでに取り組んでいます。

2026年11月12日 から。

  • #3205 @itsrayeedscodespace による — オープン

評価

難易度
3/5
見積もり時間
1〜2日
初心者へのやさしさ
35/100
issue の種類
バグ
明瞭さ
明確に書かれている
活発さ
停滞
技術スタック
python

調査の方向性

Find the CastCast rewrite rule in onnxscript.rewriter.rules.common and read how it determines whether the intermediate cast can be removed. Add focused tests for the reported DOUBLE rounding boundary and for supported mixed precision source types, then run the relevant rewrite tests. Done means the rewrite preserves both casts for DOUBLE or unknown source types while still collapsing the supported combinations; an open linked pull request already addresses this issue.

索引モデルが issue の本文から書いたものです。

説明

Description

The CastCast rewrite checks the intermediate/output dtype pair but ignores the source dtype. It currently treats both Cast(Cast(X, FLOAT), FLOAT16) and Cast(Cast(X, FLOAT), BFLOAT16) as equivalent to a direct cast for every source type.

That is not true for wider sources: rounding to FLOAT can land exactly on a lower-precision midpoint, so the second rounding can differ from a direct cast. This silently changes valid model outputs.

Reproduction

Reproduced locally on main f51083c, Python 3.12.16, macOS arm64, using the ONNX reference evaluator:

import numpy as np
import onnx
import onnx.reference
import onnx_ir as ir
from onnxscript.rewriter.rules.common import _basic_rules

h = onnx.helper
model = h.make_model(
    h.make_graph(
        [
            h.make_node("Cast", ["X"], ["M"], to=onnx.TensorProto.FLOAT),
            h.make_node("Cast", ["M"], ["Y"], to=onnx.TensorProto.FLOAT16),
        ],
        "rounding",
        [h.make_tensor_value_info("X", onnx.TensorProto.DOUBLE, [1])],
        [h.make_tensor_value_info("Y", onnx.TensorProto.FLOAT16, [1])],
    ),
    opset_imports=[h.make_opsetid("", 18)],
    ir_version=10,
)
rewritten = ir.from_proto(model)
print(_basic_rules.cast_cast_rule.apply_to_model(rewritten))  # 1
feeds = {"X": np.array([1.00048828125 + 2**-30], dtype=np.float64)}
for candidate in (model, ir.to_proto(rewritten)):
    y = onnx.reference.ReferenceEvaluator(candidate).run(None, feeds)[0]
    print(y, y.view(np.uint16))

Original: [1.] [15360]
Rewritten: [1.001] [15361]

NumPy independently gives the same distinction for x.astype(np.float32).astype(np.float16) versus x.astype(np.float16).

This is semantic correctness evidence from the reference evaluator, not a GPU/performance claim. In my local ONNX Runtime CPU check, both graphs returned the lower value; that runtime result does not independently demonstrate this rewrite's numerical difference.

Proposed fix

Restrict elimination to source dtypes for which widening to FLOAT is exact, retaining the intended mixed-precision cases (FLOAT, FLOAT16 and BFLOAT16). Preserve both casts for DOUBLE, unproven source types, or missing source-type information. Add exact-result tests around rounding boundaries plus positive tests that the supported mixed-precision combinations still collapse.

I checked open PRs and searched issues/PRs for CastCast and cast rounding/precision; I did not find a competing fix for this source-type guard.

主要言語
Python
スター
456
フォーク
159
平均マージ
3日 5時間
マージ済み PR(30日)
23

環境構築

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

microsoft/onnxscript のほかの issue

microsoft/onnxscript の issue をすべて見る

似ている issue

Python の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。