[Bug][TOPI][Relax] ArgMin returns -1 for a nonempty tensor of largest finite values
维护者通常 1 天内回复
还没有人认领这个 Issue。
评估
调研方向
The bug is in MakeArgminReducer in include/tvm/topi/reduction.h, which initializes the index to -1 and the value to the max identity, so the sentinel can win the first-index tie when the input equals that identity. Run the attached repro.py to confirm that the largest-finite and +Inf cases return -1 while the adjacent-finite control returns 0. Done means those cases return 0, the control still passes, and a regression test covers the tie.
由索引模型根据 Issue 内容生成。
描述
Summary
ArgMin(axis=0, select_last_index=0) of three identical FLOAT32 maximum finite values returns -1. Index 0 is the required first minimum. Replacing the values with the immediately adjacent lower finite value returns 0. The script also checks an all-positive-infinity input, which returns -1 in TVM.
Environment
Linux x86_64 CPU/LLVM; Python 3.12.3; TVM 0.28.dev0; LLVM 18.1.3; ONNX 1.22.0; NumPy 2.5.4; ONNX Runtime 1.29.0 (CPUExecutionProvider).
The installed TVM binary's exact build source revision is UNKNOWN. Source links are a separate static inspection of main at 70ec7d5bf20326ef301ee3f06eb6aed51760331d; that revision was not built or executed for this report.
Loaded binary SHA256 identities:
libtvm_ffi.so:12072d0ccd9d5cb2c6dac80d42f4217ab50dbf795db03197000614a7a770a816libtvm_compiler.so:574a573fe994e5eda7352ddd8d685e64e45c7934bdeeaab57a5a272a77792ab1libtvm_runtime.so:4175916fc0ce6266c912629d2255094b94087425c6ab53ffd5e004d4c292c828libtvm_runtime_extra.so:79c93351fca12dd7851964890cea7da65dd2b2e0e64e5c28bfed56c878b70817
Expected and observed behavior
Largest finite: expected [0], TVM [-1]. Adjacent finite control: expected [0], TVM [0]. All +Inf: expected [0], TVM [-1].
ArgMin-13 selects the first occurrence by default. A nonempty three-element input must yield an index in [0,3). NumPy, ONNX ReferenceEvaluator and unoptimized ORT CPU return 0. The primary finite witness contains no NaN or infinity.
Standalone reproduction
Save this as repro.py in an LLVM-enabled TVM environment, then run:
OMP_NUM_THREADS=1 OPENBLAS_NUM_THREADS=1 MKL_NUM_THREADS=1 python repro.py
from pathlib import Path
import hashlib
import numpy as np
import onnx
import onnxruntime as ort
import tvm
from onnx import TensorProto as T, helper as h, numpy_helper as nh
from onnx.reference import ReferenceEvaluator
from tvm import relax
from tvm.relax.frontend.onnx import from_onnx
def make(nodes, inputs, outputs, initializers=(), opset=18):
model = h.make_model(h.make_graph(nodes, "repro", inputs, outputs, list(initializers)),
opset_imports=[h.make_opsetid("", opset)], ir_version=10)
onnx.checker.check_model(model, full_check=True)
return model
def tvm_run(model, feeds):
mod = from_onnx(model, keep_params_in_input=False)
names = [value.name for value in model.graph.input]
executable = relax.build(mod, target="llvm", relax_pipeline="default")
result = relax.VirtualMachine(executable, tvm.cpu())["main"](
*[tvm.runtime.tensor(feeds[name]) for name in names])
return [result.numpy()] if hasattr(result, "numpy") else [v.numpy() for v in result]
def save(label, model, feeds):
folder = Path("artifacts") / label
folder.mkdir(parents=True, exist_ok=True)
onnx.checker.check_model(model, full_check=True)
onnx.save(model, folder / "model.onnx")
np.savez(folder / "inputs.npz", **feeds)
print(label, "model_sha256", hashlib.sha256((folder / "model.onnx").read_bytes()).hexdigest())
print(label, "inputs_sha256", hashlib.sha256((folder / "inputs.npz").read_bytes()).hexdigest())
def reference(model, feeds, expected, check_ort=True):
outputs = ReferenceEvaluator(model).run(None, feeds)
for a, b in zip(outputs, expected, strict=True):
assert a.shape == b.shape and a.dtype == b.dtype, (a.shape, a.dtype, b.shape, b.dtype)
np.testing.assert_allclose(a, b, rtol=1e-5, atol=1e-6)
if check_ort:
opts = ort.SessionOptions()
opts.intra_op_num_threads = opts.inter_op_num_threads = 1
opts.graph_optimization_level = ort.GraphOptimizationLevel.ORT_DISABLE_ALL
outputs = ort.InferenceSession(model.SerializeToString(), opts,
providers=["CPUExecutionProvider"]).run(None, feeds)
for a, b in zip(outputs, expected, strict=True):
assert a.shape == b.shape and a.dtype == b.dtype
np.testing.assert_allclose(a, b, rtol=1e-5, atol=1e-6)
def error_line(error):
return type(error).__name__ + ": " + str(error).splitlines()[-1]
def same(actual, expected):
assert actual.shape == expected.shape and actual.dtype == expected.dtype
np.testing.assert_allclose(actual, expected, rtol=1e-5, atol=1e-6)
model = make([h.make_node("ArgMin", ["x"], ["y"], axis=0, keepdims=1, select_last_index=0)],
[h.make_tensor_value_info("x", T.FLOAT, [3])],
[h.make_tensor_value_info("y", T.INT64, [1])], opset=13)
largest = np.full(3, np.finfo("float32").max, dtype="float32")
for label, x in (("largest_finite", largest),
("adjacent_finite", np.nextafter(largest, np.zeros_like(largest))),
("positive_infinity", np.full(3, np.inf, dtype="float32"))):
expected = np.argmin(x, axis=0, keepdims=True).astype("int64")
save(label, model, {"x": x})
reference(model, {"x": x}, [expected])
actual = tvm_run(model, {"x": x})[0]
print(label, "expected", expected.tolist(), "TVM", actual.tolist())
if label == "adjacent_finite":
same(actual, expected)
print("adjacent finite control passed")
else:
assert actual.tolist() == [-1] and expected.tolist() == [0]
Recorded output
largest_finite expected [0] TVM [-1]
adjacent_finite expected [0] TVM [0]
adjacent finite control passed
positive_infinity expected [0] TVM [-1]
Causal isolation and related work
MakeArgminReducer initializes the index to -1 and value to max_value. Its first-index tie comparison lets the artificial index beat real indices when the input equals the identity value. The sentinel must not compete as a real input index. An infinite identity alone also leaves the all-+Inf tie case to address.
#19558 and #19671 discuss NaN compatibility in the ONNX frontend. This finite-only case reaches a reducer identity/tie invariant and yields an out-of-range index, independently of NaN ordering. It is also distinct from value-only max/min reductions using finite rather than infinite identities.
This self-contained script is a newly constructed minimal diagnostic from the same graph-testing investigation, not a byte-identical replay of an archived model. It needs only TVM, ONNX, NumPy and ONNX Runtime, downloads no files, and writes its generated models and inputs to artifacts/. The assertions check both the observed failure/wrong result and the normal controls; exit code zero means that diagnostic reproduced. No global novelty or current-main execution claim is made.
Diagnostic and artifact checksums
Reproducer SHA256: a6ffa61a17f25396fedbb9b810e091eda37528b09d411d5834ba721c757e47ae
artifacts/adjacent_finite/inputs.npz:7668fc975d5bc9a94d1e334e90ecc857d74308556f6d78973565944382eb8e68artifacts/adjacent_finite/model.onnx:f65d7dd00c6c97044e804973eabe84c00dc2b67cd535a257204ca995de810ab6artifacts/largest_finite/inputs.npz:2c5681b3f4facef395be01233dfd3baea91addd5dda537d5283cf9fff35ea22aartifacts/largest_finite/model.onnx:f65d7dd00c6c97044e804973eabe84c00dc2b67cd535a257204ca995de810ab6artifacts/positive_infinity/inputs.npz:5d993725260454f464463e0ee7841df62d36a43e96c6dc819fb909445a9bf1f3artifacts/positive_infinity/model.onnx:f65d7dd00c6c97044e804973eabe84c00dc2b67cd535a257204ca995de810ab6
I am happy to help add an in-tree regression test or check a proposed correction.
- 主要语言
- Python
- 星标
- 13.9k
- 派生
- 4k
- 平均合并
- 7 小时 59 分钟
- 30 天内合并 PR
- 159
环境准备
这个项目没有提供开发容器、Dockerfile 或贡献指南,环境需要你自己搭建:先看它的 README,通用步骤见我们的新手贡献指南。
从这里开始
- 先读完整个 Issue,再读项目的贡献指南。
- 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
- Fork 仓库,在一个分支上完成修改。
- 提交 Pull Request,并在描述里引用这个 Issue 编号。
apache/tvm 的其他 Issue
-
needs-triage type: bug
难度 2/5 1-3 小时 新手友好度 80/100
维护者通常 1 天内回复
-
[Bug] [Relax][ONNX] OneHot does not convert floating-point depth to int64可能已有人在做 @tandede 于 3 天前认领。 未关闭needs-triage type: bug
难度 2/5 1-3 小时 新手友好度 76/100
维护者通常 1 天内回复
-
needs-triage type: bug
难度 2/5 1-3 小时 新手友好度 68/100
维护者通常 1 天内回复
-
needs-triage type: bug
难度 2/5 1-3 小时 新手友好度 72/100
维护者通常 1 天内回复
-
[Bug][Relax] ReorderTakeAfterMatmul fails on vector dot products可能已有人在做 @hiyufan 于 13 天前认领。 未关闭
难度 2/5 1-3 小时 新手友好度 74/100
维护者通常 1 天内回复
相似的 Issue
-
[BUG]: Compliance rules never see Unity Catalog views as views可能已有人在做 @wagnercsantos 今天认领。 未关闭
难度 2/5 1-3 小时 新手友好度 78/100
databrickslabs/ontos#1348 ·
维护者通常 3 天内回复
-
`forum_pr_poster` action will always return `none` when checking for pre-existing feedback threads, even if a feedback thread already exists.可能已有人在做 @pgmzeta 今天认领。 未关闭E-Verified P-Major
难度 2/5 1-3 小时 新手友好度 79/100
goonstation/goonstation#28259 ·
维护者通常 2 天内回复
-
enhancement
难度 2/5 1-3 小时 新手友好度 65/100
woonstadrotterdam/monumenten#70 ·
维护者通常 15 天内回复
-
binding:python bug
难度 2/5 1-3 小时 新手友好度 82/100
维护者通常 1 天内回复
-
The Browser tab fails with a Wayland error when Open Terminal runs from a Wayland desktop session未关闭
难度 2/5 1-3 小时 新手友好度 78/100
open-webui/open-terminal#210 ·