Skip to content

Conversation

@arkq
Copy link
Contributor

@arkq arkq commented Oct 13, 2025

This commit refactors the tensorinfo structure to be easier to use on the Python side. Instead of exporting C dimension array which needs to be trimmed on the Python side, now it exports Python tuple with length equal to tensor rank. Also, the entire structure is designed to be immutable to improve the understanding of the API concept - altering the info structure will not change the tensor.

The new tensorinfo structure consists of a data type and the tensor shape. The data type is a dedicated type exposed by the native Python library. It provides a direct mapping between numpy data type and the internal NNFW data type. Additionally, it allows to expose all internal data types (quantized types) which was not possible with previous approach - there is no 1:1 mapping between C++ types and NNFW types.

New usage:

>>> import onert
>>> onert.
onert.bool          onert.dtype(        onert.float32       onert.int32         onert.native        onert.qint8         onert.tensorinfo(
onert.common        onert.experimental  onert.infer         onert.int64         onert.qint16sym     onert.quint8        onert.uint8
>>> ti = onert.tensorinfo(onert.float32, [5, 7, 9, 2])
>>> ti
<tensorinfo dtype=onert.float32 shape=(5, 7, 9, 2)>
>>> ti.
ti.dtype  ti.rank   ti.shape
>>> ti.rank
4
>>> ti.shape = [3, 5, 2, 3]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: property of 'tensorinfo' object has no setter
>>> ti.dtype.dtype  # numpy dtype
dtype('float32')
>>>

ONE-DCO-1.0-Signed-off-by: Arkadiusz Bokowy a.bokowy@samsung.com

arkq added 2 commits October 8, 2025 10:08
This commit removes unused and broken tensorinfo() function from the
common Python module.

  >>> import onert
  >>> onert.tensorinfo()
  Traceback (most recent call last):
    File ".../onert/common/basesession.py", line 189, in tensorinfo
      return infer.nnfw_tensorinfo()
             ^^^^^^^^^^^^^^^^^^^^^
  AttributeError: module 'onert.native.libnnfw_api_pybind.infer' has no attribute 'nnfw_tensorinfo'

Removing this function allows to properly use the native tensorinfo
structure from the onert top level module.

  >>> import onert
  >>> onert.tensorinfo()
  <onert.native.libnnfw_api_pybind.tensorinfo object at 0x7601fe0916f0>

ONE-DCO-1.0-Signed-off-by: Arkadiusz Bokowy <a.bokowy@samsung.com>
This commit refactors the tensorinfo structure to be easier to use on
the Python side. Instead of exporting C dimension array which needs to
be trimmed on the Python side, now it exports Python tuple with length
equal to tensor rank. Also, the entire structure is designed to be
immutable to improve the understanding of the API concept - altering
the info structure will not change the tensor.

The new tensorinfo structure consists of a data type and the tensor
shape. The data type is a dedicated type exposed by the native Python
library. It provides a direct mapping between numpy data type and the
internal NNFW data type. Additionally, it allows to expose all internal
data types (quantized types) which was not possible with previous
approach - there is no 1:1 mapping between C++ types and NNFW types.

ONE-DCO-1.0-Signed-off-by: Arkadiusz Bokowy <a.bokowy@samsung.com>
@arkq
Copy link
Contributor Author

arkq commented Oct 13, 2025

This is still work in progress (hence a draft PR), because I'm investigating the possibility to improve the shape type which right now is a simple vector of integers. The problem with that approach is the magic value -1 for dynamic dimension which is not ideal. Better approach would be to have a dedicated types for a single dimension (with possibility to check for valid values, e.g. dimension can be dynamic within a range) and a shape. From the Python point of view it would be best to derivate the dimension type from int class dim(int):, but it's not that easy to export such type via pybind11...

Anyway, what do you mean (in general) about such refactoring for the tensorinfo?

@ragmani
Copy link
Contributor

ragmani commented Oct 13, 2025

It might be better not to expose the C++ tensorinfo binding directly, but instead provide a dedicated Python TensorInfo class. That gives us more flexibility to define Python-friendly semantics (immutability, validation, nicer shape handling) while still converting to/from the native object when needed.

Regarding shape, rather than a custom dim type, a simpler and more natural approach on the Python side is to accept tuples or numpy arrays and normalize None to -1 for dynamic dims. This keeps the API consistent with NumPy/PyTorch conventions and avoids extra complexity.

Example:

def _normalize_shape(shape):
    if isinstance(shape, np.ndarray):
        shape = shape.tolist()
    shp = tuple(-1 if d is None else int(d) for d in shape)
    if len(shp) == 0 or any((d < -1 or d == 0) for d in shp):
        raise ValueError("invalid shape")
    return shp

class TensorInfo:
    def __init__(self, dtype, shape):
        self.dtype = dtype
        self.shape = _normalize_shape(shape)

    ...
# Usage
shape = sess.get_inputs_tensorinfo()[0].shape

This way users always work with a clean Python TensorInfo class, while the native binding stays behind the scenes as an implementation detail.

@arkq
Copy link
Contributor Author

arkq commented Oct 13, 2025

It might be better not to expose the C++ tensorinfo binding directly, but instead provide a dedicated Python TensorInfo class.

And what about the data types? The numpy data types do not have quantized types. Should we expose these in a similar way pytorch does it - using our own types i.e. onert.dtype instead of np.dtype (just like in this draft PR)?

@ragmani
Copy link
Contributor

ragmani commented Oct 13, 2025

And what about the data types? The numpy data types do not have quantized types. Should we expose these in a similar way pytorch does it - using our own types i.e. onert.dtype instead of np.dtype (just like in this draft PR)?

I actually hadn’t considered the data types enough, but you’re right. Since numpy doesn’t cover quantized types, we can’t rely on np.dtype alone. For that reason I think having our own onert.dtype makes sense. That way we can cleanly represent both standard types (float32, int32, etc.) and quantized types (qint8, quint8, …).

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.

2 participants