Visitar URL original
onnx-graphsurgeon: sparse initializers stored in raw_data load as zeros (0.6.1) or fail (main), and loaded sparse values are always float64 · Issue #4910 · NVIDIA/TensorRT · GitHub
Skip to content

onnx-graphsurgeon: sparse initializers stored in raw_data load as zeros (0.6.1) or fail (main), and loaded sparse values are always float64 #4910

Open

Description

@Anshtyagi1729

Description

SparseValues.load() in onnx_graphsurgeon/ir/tensor.py has two bugs.

1. Values and indices stored in raw_data are ignored. load() reads only the typed repeated fields (int64_data, float_data, ...). Tensors created with onnx.numpy_helper.from_array, and most exporters, store their data in raw_data, so those fields are empty.

  • On onnx-graphsurgeon 0.6.1 (PyPI), the sparse tensor silently loads as all zeros.
  • On current main, the size check added in the 11.3 release catches the empty fields, and loading fails with Sparse tensor w declares 2 indices, but stores 0.

2. The dense result is always float64. The dense buffer is created with np.zeros(...) without a dtype. For a sparse INT64 initializer this:

  • loses precision for values above 2**53 (2**60 + 1 comes back as 1.152921504606847e+18),
  • changes Constant.dtype from int64 before loading to float64 after loading,
  • makes gs.export_onnx write a DOUBLE dense initializer, which then fails ONNX type checking against its consumer.

Environment

TensorRT Version: N/A, ONNX-GraphSurgeon only. Reproduced on main (16ed063, onnx-graphsurgeon 0.6.2) and on onnx-graphsurgeon 0.6.1 from PyPI.

NVIDIA GPU: N/A

NVIDIA Driver Version: N/A

CUDA Version: N/A

CUDNN Version: N/A

Operating System: Linux

Python Version (if applicable): 3.13 (onnx 1.23.2, numpy 2.5.3)

Tensorflow Version (if applicable): N/A

PyTorch Version (if applicable): N/A

Baremetal or Container (if so, version): Container

Relevant Files

Model link: N/A, the script below builds the model directly.

Steps To Reproduce

Commands or scripts:

import numpy as np
import onnx
from onnx import helper, numpy_helper, TensorProto
import onnx_graphsurgeon as gs

dense_shape = [2, 3]

def make_model(values, indices):
    sparse = helper.make_sparse_tensor(values, indices, dense_shape)
    node = helper.make_node("Identity", ["w"], ["y"])
    graph = helper.make_graph(
        [node], "g", [],
        [helper.make_tensor_value_info("y", TensorProto.INT64, dense_shape)],
        sparse_initializer=[sparse],
    )
    return helper.make_model(graph)

# Case 1: values/indices stored in raw_data (what numpy_helper.from_array produces)
model = make_model(
    numpy_helper.from_array(np.array([7, 9], dtype=np.int64), "w"),
    numpy_helper.from_array(np.array([1, 4], dtype=np.int64), "idx"),
)
graph = gs.import_onnx(model)
try:
    print(graph.tensors()["w"].values)
except Exception as err:
    print("raw_data case:", type(err).__name__, err)

# Case 2: values stored in int64_data
model = make_model(
    helper.make_tensor("w", TensorProto.INT64, [2], [7, 2**60 + 1]),
    helper.make_tensor("idx", TensorProto.INT64, [2], [1, 4]),
)
graph = gs.import_onnx(model)
w = graph.tensors()["w"]
print("dtype before load:", w.dtype)
print("values:", w.values.ravel().tolist(), "dtype after load:", w.values.dtype)
try:
    onnx.checker.check_model(gs.export_onnx(graph), full_check=True)
    print("exported model OK")
except Exception as err:
    print("exported model invalid:", str(err).strip())

Output on onnx-graphsurgeon 0.6.1 (PyPI):

[[0. 0. 0.]
 [0. 0. 0.]]
dtype before load: int64
values: [0.0, 7.0, 0.0, 0.0, 1.152921504606847e+18, 0.0] dtype after load: float64
exported model invalid: [ShapeInferenceError] Inference error(s): (op_type:Identity): [TypeInferenceError] Inferred elem type differs from existing elem type: (11) vs (7)

Output on main:

raw_data case: OnnxGraphSurgeonException Sparse tensor w declares 2 indices, but stores 0
dtype before load: int64
values: [0.0, 7.0, 0.0, 0.0, 1.152921504606847e+18, 0.0] dtype after load: float64
exported model invalid: [ShapeInferenceError] Inference error(s): (op_type:Identity): [TypeInferenceError] Inferred elem type differs from existing elem type: (11) vs (7)

Expected: both cases load as an int64 array of shape (2, 3) with the exact values ([[0, 7, 0], [0, 9, 0]] for case 1), and the exported model passes the checker.

Full traceback for case 1 on main:

Traceback (most recent call last):
  File "repro.py", line 6, in <module>
    gs.import_onnx(helper.make_model(graph)).tensors()["w"].values
  File "onnx_graphsurgeon/ir/tensor.py", line 460, in values
    self._values = self._values.load()
  File "onnx_graphsurgeon/ir/tensor.py", line 314, in load
    G_LOGGER.critical(
  File "onnx_graphsurgeon/logger/logger.py", line 242, in critical
    raise OnnxGraphSurgeonException(message) from None  # Erase exception chain
onnx_graphsurgeon.util.exception.OnnxGraphSurgeonException: Sparse tensor w declares 2 indices, but stores 0

Have you tried the latest release?: Yes. It reproduces on the latest onnx-graphsurgeon from PyPI (0.6.1) and on current main.

Can this model run on other frameworks?: Yes. onnx.checker.check_model accepts the case 1 model, and ONNX Runtime 1.29.0 loads it and returns [[0, 7, 0], [0, 9, 0]] (saved with ir_version=10, since that ONNX Runtime version supports IR version 13 at most).

Proposed fix

Decode values and indices with onnx.numpy_helper.to_array, which handles every storage form, and allocate the dense buffer with the dtype of the values:

values_data = np.asarray(onnx.numpy_helper.to_array(self.tensor.values)).ravel()
indices_data = np.asarray(onnx.numpy_helper.to_array(self.tensor.indices)).ravel().astype(np.int64, copy=False)
...
values = np.zeros(dense_size, dtype=values_data.dtype)

The existing bounds and size checks stay as they are. I'd like to send a PR with this fix and regression tests in tests/test_importers.py.

Activity

  1. added a commit that references this issue on Nov 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions