onnx-diagnostic 0.6.1__py3-none-any.whl → 0.6.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- onnx_diagnostic/__init__.py +1 -1
- onnx_diagnostic/helpers/doc_helper.py +143 -0
- onnx_diagnostic/reference/torch_evaluator.py +141 -11
- onnx_diagnostic/reference/torch_ops/__init__.py +1 -1
- onnx_diagnostic/reference/torch_ops/_op_run.py +14 -5
- onnx_diagnostic/reference/torch_ops/access_ops.py +18 -8
- onnx_diagnostic/reference/torch_ops/binary_ops.py +2 -2
- onnx_diagnostic/reference/torch_ops/controlflow_ops.py +7 -4
- onnx_diagnostic/reference/torch_ops/generator_ops.py +4 -3
- onnx_diagnostic/reference/torch_ops/nn_ops.py +34 -14
- onnx_diagnostic/reference/torch_ops/other_ops.py +19 -19
- onnx_diagnostic/reference/torch_ops/reduce_ops.py +6 -6
- onnx_diagnostic/reference/torch_ops/sequence_ops.py +6 -6
- onnx_diagnostic/reference/torch_ops/shape_ops.py +16 -15
- onnx_diagnostic/reference/torch_ops/unary_ops.py +13 -13
- onnx_diagnostic/torch_models/test_helper.py +18 -1
- {onnx_diagnostic-0.6.1.dist-info → onnx_diagnostic-0.6.2.dist-info}/METADATA +1 -1
- {onnx_diagnostic-0.6.1.dist-info → onnx_diagnostic-0.6.2.dist-info}/RECORD +21 -20
- {onnx_diagnostic-0.6.1.dist-info → onnx_diagnostic-0.6.2.dist-info}/WHEEL +0 -0
- {onnx_diagnostic-0.6.1.dist-info → onnx_diagnostic-0.6.2.dist-info}/licenses/LICENSE.txt +0 -0
- {onnx_diagnostic-0.6.1.dist-info → onnx_diagnostic-0.6.2.dist-info}/top_level.txt +0 -0
onnx_diagnostic/__init__.py
CHANGED
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
from typing import Dict, Optional, Tuple
|
|
2
|
+
import onnx
|
|
3
|
+
import onnx.helper as oh
|
|
4
|
+
import torch
|
|
5
|
+
from ..reference.torch_ops import OpRunKernel, OpRunTensor
|
|
6
|
+
from .torch_helper import onnx_dtype_to_torch_dtype, torch_dtype_to_onnx_dtype
|
|
7
|
+
from .ort_session import InferenceSessionForTorch
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class LayerNormalizationOrt(OpRunKernel):
|
|
11
|
+
"LayerNormalization with onnxruntime"
|
|
12
|
+
|
|
13
|
+
@classmethod
|
|
14
|
+
def device_dependent(cls) -> bool:
|
|
15
|
+
"Needs device."
|
|
16
|
+
return False
|
|
17
|
+
|
|
18
|
+
def __init__(
|
|
19
|
+
self,
|
|
20
|
+
node: onnx.NodeProto,
|
|
21
|
+
version=None,
|
|
22
|
+
device: Optional[torch.device] = None,
|
|
23
|
+
verbose=0,
|
|
24
|
+
):
|
|
25
|
+
super().__init__(node, version, verbose=verbose)
|
|
26
|
+
self.axis = self.get_attribute_int(node, "axis", -1)
|
|
27
|
+
self.epsilon = self.get_attribute_float(node, "epsilon", 1e-5)
|
|
28
|
+
self.device = device
|
|
29
|
+
self.stash_type = onnx_dtype_to_torch_dtype(
|
|
30
|
+
self.get_attribute_int(node, "stash_type", onnx.TensorProto.FLOAT) # type: ignore[arg-type]
|
|
31
|
+
)
|
|
32
|
+
self.compute_std = len(node.output) > 1
|
|
33
|
+
assert not self.compute_std, (
|
|
34
|
+
f"This kernel implementation only work when only one output "
|
|
35
|
+
f"is required but {node.output} were."
|
|
36
|
+
)
|
|
37
|
+
self._cache: Dict[Tuple[int, int], onnx.ModelProto] = {}
|
|
38
|
+
self.is_cpu = torch.device("cpu") == self.device
|
|
39
|
+
|
|
40
|
+
def _make_model(self, itype: int, rank: int, has_bias: bool) -> onnx.ModelProto:
|
|
41
|
+
shape = [*["d{i}" for i in range(rank - 1)], "last"]
|
|
42
|
+
layer_model = oh.make_model(
|
|
43
|
+
oh.make_graph(
|
|
44
|
+
[
|
|
45
|
+
oh.make_node(
|
|
46
|
+
"LayerNormalization",
|
|
47
|
+
["X", "W", "B"] if has_bias else ["X", "W"],
|
|
48
|
+
["Z"],
|
|
49
|
+
axis=self.axis,
|
|
50
|
+
epsilon=self.epsilon,
|
|
51
|
+
)
|
|
52
|
+
],
|
|
53
|
+
"dummy",
|
|
54
|
+
(
|
|
55
|
+
[
|
|
56
|
+
oh.make_tensor_value_info("X", itype, shape),
|
|
57
|
+
oh.make_tensor_value_info("W", itype, ["last"]),
|
|
58
|
+
oh.make_tensor_value_info("B", itype, ["last"]),
|
|
59
|
+
]
|
|
60
|
+
if has_bias
|
|
61
|
+
else [
|
|
62
|
+
oh.make_tensor_value_info("X", itype, shape),
|
|
63
|
+
oh.make_tensor_value_info("W", itype, ["last"]),
|
|
64
|
+
]
|
|
65
|
+
),
|
|
66
|
+
[oh.make_tensor_value_info("Z", itype, shape)],
|
|
67
|
+
),
|
|
68
|
+
ir_version=9,
|
|
69
|
+
opset_imports=[oh.make_opsetid("", 18)],
|
|
70
|
+
)
|
|
71
|
+
provider = "CPUExecutionProvider" if self.is_cpu else "CUDAExecutionProvider"
|
|
72
|
+
self._provider = provider
|
|
73
|
+
return InferenceSessionForTorch(layer_model, providers=[provider])
|
|
74
|
+
|
|
75
|
+
def run(self, x, scale, bias=None):
|
|
76
|
+
itype = torch_dtype_to_onnx_dtype(x.dtype)
|
|
77
|
+
rank = len(x.shape)
|
|
78
|
+
key = itype, rank
|
|
79
|
+
if key not in self._cache:
|
|
80
|
+
self._cache[key] = self._make_model(itype, rank, bias is not None)
|
|
81
|
+
sess = self._cache[key]
|
|
82
|
+
if self.verbose:
|
|
83
|
+
print(f"[LayerNormalizationOrt] running on {self._provider!r}")
|
|
84
|
+
feeds = dict(X=x.tensor, W=scale.tensor)
|
|
85
|
+
if bias is not None:
|
|
86
|
+
feeds["B"] = bias.tensor
|
|
87
|
+
got = sess.run(None, feeds)[0]
|
|
88
|
+
return OpRunTensor(got)
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
class MatMulOrt(OpRunKernel):
|
|
92
|
+
"MatMul with onnxruntime"
|
|
93
|
+
|
|
94
|
+
@classmethod
|
|
95
|
+
def device_dependent(cls) -> bool:
|
|
96
|
+
"Needs device."
|
|
97
|
+
return False
|
|
98
|
+
|
|
99
|
+
def __init__(
|
|
100
|
+
self,
|
|
101
|
+
node: onnx.NodeProto,
|
|
102
|
+
version=None,
|
|
103
|
+
device: Optional[torch.device] = None,
|
|
104
|
+
verbose=0,
|
|
105
|
+
):
|
|
106
|
+
super().__init__(node, version, verbose=verbose)
|
|
107
|
+
self.device = device
|
|
108
|
+
self._cache: Dict[Tuple[int, int, int], onnx.ModelProto] = {}
|
|
109
|
+
self.is_cpu = torch.device("cpu") == self.device
|
|
110
|
+
|
|
111
|
+
def _make_model(self, itype: int, ranka: int, rankb: int) -> onnx.ModelProto:
|
|
112
|
+
shapea = ["a{i}" for i in range(ranka)]
|
|
113
|
+
shapeb = ["b{i}" for i in range(rankb)]
|
|
114
|
+
shapec = ["c{i}" for i in range(max(ranka, rankb))]
|
|
115
|
+
model = oh.make_model(
|
|
116
|
+
oh.make_graph(
|
|
117
|
+
[oh.make_node("MatMul", ["A", "B"], ["C"])],
|
|
118
|
+
"dummy",
|
|
119
|
+
[
|
|
120
|
+
oh.make_tensor_value_info("A", itype, shapea),
|
|
121
|
+
oh.make_tensor_value_info("B", itype, shapeb),
|
|
122
|
+
],
|
|
123
|
+
[oh.make_tensor_value_info("C", itype, shapec)],
|
|
124
|
+
),
|
|
125
|
+
ir_version=9,
|
|
126
|
+
opset_imports=[oh.make_opsetid("", 18)],
|
|
127
|
+
)
|
|
128
|
+
provider = "CPUExecutionProvider" if self.is_cpu else "CUDAExecutionProvider"
|
|
129
|
+
self._provider = provider
|
|
130
|
+
return InferenceSessionForTorch(model, providers=[provider])
|
|
131
|
+
|
|
132
|
+
def run(self, a, b):
|
|
133
|
+
itype = torch_dtype_to_onnx_dtype(a.dtype)
|
|
134
|
+
ranka, rankb = len(a.shape), len(b.shape)
|
|
135
|
+
key = itype, ranka, rankb
|
|
136
|
+
if key not in self._cache:
|
|
137
|
+
self._cache[key] = self._make_model(itype, ranka, rankb)
|
|
138
|
+
sess = self._cache[key]
|
|
139
|
+
if self.verbose:
|
|
140
|
+
print(f"[MatMulOrt] running on {self._provider!r}")
|
|
141
|
+
feeds = dict(A=a.tensor, B=b.tensor)
|
|
142
|
+
got = sess.run(None, feeds)[0]
|
|
143
|
+
return OpRunTensor(got)
|
|
@@ -9,7 +9,7 @@ from . import torch_ops
|
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
@functools.lru_cache
|
|
12
|
-
def get_kernels() -> Dict[Tuple[str, str, int], type[torch_ops.
|
|
12
|
+
def get_kernels() -> Dict[Tuple[str, str, int], type[torch_ops.OpRunKernel]]:
|
|
13
13
|
"""
|
|
14
14
|
Retrieves all the available kernels class :class:`TorchOnnxEvaluator`
|
|
15
15
|
can use. The full list is the following.
|
|
@@ -28,7 +28,7 @@ def get_kernels() -> Dict[Tuple[str, str, int], type[torch_ops.OpRun]]:
|
|
|
28
28
|
"""
|
|
29
29
|
res = {}
|
|
30
30
|
for _k, v in torch_ops.__dict__.items():
|
|
31
|
-
if isinstance(v, type) and issubclass(v, torch_ops.
|
|
31
|
+
if isinstance(v, type) and issubclass(v, torch_ops.OpRunKernel) and "_" in v.__name__:
|
|
32
32
|
name, version = v.__name__.split("_")
|
|
33
33
|
domain = getattr(v, "domain", "")
|
|
34
34
|
res[domain, name, int(version)] = v
|
|
@@ -45,6 +45,8 @@ class TorchOnnxEvaluator:
|
|
|
45
45
|
:param opsets: needed if proto is a graph
|
|
46
46
|
:param functions: known local functions
|
|
47
47
|
:param verbose: verbosity level
|
|
48
|
+
:param custom_kernels: dictionary of kernels the user can defined to overwrite
|
|
49
|
+
a specific implementation: ``("", "LayerNormalization"): CustomKernel``
|
|
48
50
|
|
|
49
51
|
The class holds the following attributes:
|
|
50
52
|
|
|
@@ -98,7 +100,10 @@ class TorchOnnxEvaluator:
|
|
|
98
100
|
result = sess.run(None, feeds)
|
|
99
101
|
print(string_type(result, with_shape=True, with_min_max=True))
|
|
100
102
|
|
|
101
|
-
|
|
103
|
+
With ``verbose=1``, the class prints out every kernel run and
|
|
104
|
+
and every result deleted along the run.
|
|
105
|
+
It shows when a result is not needed anymore. In that case,
|
|
106
|
+
it is deleted to free the memory it takes.
|
|
102
107
|
|
|
103
108
|
.. runpython::
|
|
104
109
|
:showcode:
|
|
@@ -134,8 +139,6 @@ class TorchOnnxEvaluator:
|
|
|
134
139
|
result = sess.run(None, feeds)
|
|
135
140
|
print(string_type(result, with_shape=True, with_min_max=True))
|
|
136
141
|
|
|
137
|
-
It also shows when a result is not needed anymore. In that case,
|
|
138
|
-
it is deleted to free the memory it takes.
|
|
139
142
|
The runtime can also execute the kernel the onnx model on CUDA.
|
|
140
143
|
It follows the same logic as :class:`onnxruntime.InferenceSession`:
|
|
141
144
|
``providers=["CUDAExecutionProvider"]``.
|
|
@@ -144,6 +147,115 @@ class TorchOnnxEvaluator:
|
|
|
144
147
|
identified as a shape in CPU. Some bugs may remain as torch
|
|
145
148
|
raises an exception when devices are expected to be the same.
|
|
146
149
|
The runtime was validated with model :epkg:`arnir0/Tiny-LLM`.
|
|
150
|
+
Next example shows how to replace a kernel with a different
|
|
151
|
+
one based on :epkg:`onnxruntime`.
|
|
152
|
+
|
|
153
|
+
.. runpython::
|
|
154
|
+
:showcode:
|
|
155
|
+
|
|
156
|
+
import numpy as np
|
|
157
|
+
import onnx
|
|
158
|
+
import onnx.helper as oh
|
|
159
|
+
import onnxruntime
|
|
160
|
+
import torch
|
|
161
|
+
from onnx_diagnostic.helpers import string_type
|
|
162
|
+
from onnx_diagnostic.helpers.torch_helper import onnx_dtype_to_torch_dtype
|
|
163
|
+
from onnx_diagnostic.reference import TorchOnnxEvaluator
|
|
164
|
+
from onnx_diagnostic.reference.torch_ops import OpRunKernel, OpRunTensor
|
|
165
|
+
|
|
166
|
+
TFLOAT16 = onnx.TensorProto.FLOAT16
|
|
167
|
+
|
|
168
|
+
class LayerNormalizationOrt(OpRunKernel):
|
|
169
|
+
"LayerNormalization based on onnxruntime"
|
|
170
|
+
|
|
171
|
+
def __init__(self, node: onnx.NodeProto, version=None):
|
|
172
|
+
super().__init__(node, version)
|
|
173
|
+
self.axis = self.get_attribute_int(node, "axis", -1)
|
|
174
|
+
self.epsilon = self.get_attribute_float(node, "epsilon", 1e-5)
|
|
175
|
+
self.stash_type = onnx_dtype_to_torch_dtype(
|
|
176
|
+
self.get_attribute_int(node, "stash_type", onnx.TensorProto.FLOAT)
|
|
177
|
+
)
|
|
178
|
+
self.compute_std = len(node.output) > 1
|
|
179
|
+
assert not self.compute_std, "The keren only computes the first output."
|
|
180
|
+
layer_model = oh.make_model(
|
|
181
|
+
oh.make_graph(
|
|
182
|
+
[
|
|
183
|
+
oh.make_node(
|
|
184
|
+
"LayerNormalization",
|
|
185
|
+
["X", "W", "B"],
|
|
186
|
+
["Z"],
|
|
187
|
+
axis=-1,
|
|
188
|
+
epsilon=9.999999974752427e-7,
|
|
189
|
+
)
|
|
190
|
+
],
|
|
191
|
+
"dummy",
|
|
192
|
+
[
|
|
193
|
+
oh.make_tensor_value_info("X", TFLOAT16, ["b", "c", "d"]),
|
|
194
|
+
oh.make_tensor_value_info("W", TFLOAT16, ["d"]),
|
|
195
|
+
oh.make_tensor_value_info("B", TFLOAT16, ["d"]),
|
|
196
|
+
],
|
|
197
|
+
[oh.make_tensor_value_info("Z", TFLOAT16, ["b", "c", "d"])],
|
|
198
|
+
),
|
|
199
|
+
ir_version=9,
|
|
200
|
+
opset_imports=[oh.make_opsetid("", 17)],
|
|
201
|
+
)
|
|
202
|
+
self.ort_sess = onnxruntime.InferenceSession(
|
|
203
|
+
layer_model.SerializeToString(), providers=["CUDAExecutionProvider"]
|
|
204
|
+
)
|
|
205
|
+
|
|
206
|
+
def run(self, x, scale, bias=None):
|
|
207
|
+
print(f"-- running {self.__class__.__name__}")
|
|
208
|
+
feeds = dict(X=x, W=scale)
|
|
209
|
+
if bias is not None:
|
|
210
|
+
feeds["B"] = bias
|
|
211
|
+
feeds = {k: v.tensor.detach().cpu().numpy() for k, v in feeds.items()}
|
|
212
|
+
got = self.ort_sess.run(None, feeds)[0]
|
|
213
|
+
return OpRunTensor(torch.from_numpy(got).to(x.dtype).to(x.device))
|
|
214
|
+
|
|
215
|
+
# This kernel is tested on this model.
|
|
216
|
+
model = oh.make_model(
|
|
217
|
+
oh.make_graph(
|
|
218
|
+
[
|
|
219
|
+
oh.make_node(
|
|
220
|
+
"LayerNormalization",
|
|
221
|
+
["X", "W", "B"],
|
|
222
|
+
["ln"],
|
|
223
|
+
axis=-1,
|
|
224
|
+
epsilon=9.999999974752427e-7,
|
|
225
|
+
),
|
|
226
|
+
oh.make_node(
|
|
227
|
+
"Add", ["ln", "W"], ["Z"], axis=-1, epsilon=9.999999974752427e-7
|
|
228
|
+
),
|
|
229
|
+
],
|
|
230
|
+
"dummy",
|
|
231
|
+
[
|
|
232
|
+
oh.make_tensor_value_info("X", TFLOAT16, ["b", "c", "d"]),
|
|
233
|
+
oh.make_tensor_value_info("W", TFLOAT16, ["d"]),
|
|
234
|
+
oh.make_tensor_value_info("B", TFLOAT16, ["d"]),
|
|
235
|
+
],
|
|
236
|
+
[oh.make_tensor_value_info("Z", TFLOAT16, ["b", "c", "d"])],
|
|
237
|
+
),
|
|
238
|
+
ir_version=9,
|
|
239
|
+
opset_imports=[oh.make_opsetid("", 17)],
|
|
240
|
+
)
|
|
241
|
+
|
|
242
|
+
torch_sess = TorchOnnxEvaluator(
|
|
243
|
+
model,
|
|
244
|
+
custom_kernels={("", "LayerNormalization"): LayerNormalizationOrt},
|
|
245
|
+
verbose=1,
|
|
246
|
+
)
|
|
247
|
+
feeds = dict(
|
|
248
|
+
zip(
|
|
249
|
+
torch_sess.input_names,
|
|
250
|
+
[
|
|
251
|
+
torch.rand(3, 4, 5, dtype=torch.float16),
|
|
252
|
+
torch.abs(torch.rand(5, dtype=torch.float16)),
|
|
253
|
+
torch.rand(5, dtype=torch.float16),
|
|
254
|
+
],
|
|
255
|
+
)
|
|
256
|
+
)
|
|
257
|
+
res = torch_sess.run(None, feeds)
|
|
258
|
+
print(string_type(res, with_shape=True, with_min_max=True))
|
|
147
259
|
"""
|
|
148
260
|
|
|
149
261
|
class IO:
|
|
@@ -172,13 +284,15 @@ class TorchOnnxEvaluator:
|
|
|
172
284
|
opsets: Optional[Dict[str, int]] = None,
|
|
173
285
|
local_functions: Optional[Dict[Tuple[str, str], "TorchOnnxEvaluator"]] = None,
|
|
174
286
|
verbose: int = 0,
|
|
287
|
+
custom_kernels: Optional[Dict[Tuple[str, str], type[torch_ops.OpRunKernel]]] = None,
|
|
175
288
|
):
|
|
176
289
|
self.providers = providers
|
|
177
290
|
self.constants: Dict[str, torch.Tensor] = {}
|
|
178
|
-
self.kernels: List[Optional[torch_ops.
|
|
291
|
+
self.kernels: List[Optional[torch_ops.OpRunKernel]] = []
|
|
179
292
|
self.functions = local_functions.copy() if local_functions else {}
|
|
180
293
|
self.CPU = torch.tensor([0]).to("cpu").device
|
|
181
294
|
self.verbose = verbose
|
|
295
|
+
self.custom_kernels = custom_kernels or {}
|
|
182
296
|
dev = self._on_cuda(providers)
|
|
183
297
|
if dev < 0:
|
|
184
298
|
self.default_device = self.CPU
|
|
@@ -296,9 +410,24 @@ class TorchOnnxEvaluator:
|
|
|
296
410
|
kernels = get_kernels()
|
|
297
411
|
self.kernels.clear()
|
|
298
412
|
for node in nodes:
|
|
413
|
+
kernel_kwargs = dict(verbose=max(0, self.verbose - 1))
|
|
414
|
+
opset = self.opsets[node.domain]
|
|
415
|
+
key = node.domain, node.op_type, opset
|
|
416
|
+
if key[:2] in self.custom_kernels:
|
|
417
|
+
cls = self.custom_kernels[key[:2]]
|
|
418
|
+
ags = [self.default_device] if cls.device_dependent() else []
|
|
419
|
+
kws = dict(parent=self) if cls.has_subgraphs() else {}
|
|
420
|
+
kws.update(kernel_kwargs) # type: ignore[arg-type]
|
|
421
|
+
kernel2 = cls(node, opset, *ags, **kws) # type: ignore[arg-type]
|
|
422
|
+
self.kernels.append(kernel2)
|
|
423
|
+
continue
|
|
424
|
+
|
|
299
425
|
if (node.domain, node.op_type) in self.functions:
|
|
300
426
|
kernel = torch_ops.OpRunFunction(
|
|
301
|
-
self.functions[node.domain, node.op_type],
|
|
427
|
+
self.functions[node.domain, node.op_type],
|
|
428
|
+
node,
|
|
429
|
+
self.opsets[node.domain],
|
|
430
|
+
**kernel_kwargs,
|
|
302
431
|
)
|
|
303
432
|
self.kernels.append(kernel)
|
|
304
433
|
continue
|
|
@@ -308,8 +437,6 @@ class TorchOnnxEvaluator:
|
|
|
308
437
|
self.kernels.append(None)
|
|
309
438
|
continue
|
|
310
439
|
|
|
311
|
-
opset = self.opsets[node.domain]
|
|
312
|
-
key = node.domain, node.op_type, opset
|
|
313
440
|
while key not in kernels and opset > 0:
|
|
314
441
|
opset -= 1
|
|
315
442
|
key = node.domain, node.op_type, opset
|
|
@@ -320,7 +447,8 @@ class TorchOnnxEvaluator:
|
|
|
320
447
|
cls = kernels[key]
|
|
321
448
|
ags = [self.default_device] if cls.device_dependent() else []
|
|
322
449
|
kws = dict(parent=self) if cls.has_subgraphs() else {}
|
|
323
|
-
|
|
450
|
+
kws.update(kernel_kwargs) # type: ignore[arg-type]
|
|
451
|
+
kernel2 = cls(node, opset, *ags, **kws) # type: ignore[arg-type]
|
|
324
452
|
self.kernels.append(kernel2)
|
|
325
453
|
|
|
326
454
|
def run(
|
|
@@ -438,7 +566,9 @@ class TorchOnnxEvaluator:
|
|
|
438
566
|
context: Optional[Dict[str, RuntimeValue]] = None,
|
|
439
567
|
) -> Union[torch_ops.OpRunValue, Tuple[torch_ops.OpRunValue, ...]]:
|
|
440
568
|
"""
|
|
441
|
-
Runs the ONNX model.
|
|
569
|
+
Runs the ONNX model. The signature is different.
|
|
570
|
+
This method is called by every kernel hokding a subgraph.
|
|
571
|
+
The local variables are stored in `context`.
|
|
442
572
|
|
|
443
573
|
:param args: inputs
|
|
444
574
|
:param context: local context for the execution of subgraphs
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
from typing import Any, List, Optional, Union, Tuple
|
|
1
|
+
from typing import Any, Dict, List, Optional, Union, Tuple
|
|
2
2
|
import onnx
|
|
3
3
|
import torch
|
|
4
4
|
from ...api import TensorLike
|
|
@@ -167,7 +167,7 @@ class OpRunSequence(OpRunValue):
|
|
|
167
167
|
return string_type(self.sequence, with_shape=True)
|
|
168
168
|
|
|
169
169
|
|
|
170
|
-
class
|
|
170
|
+
class OpRunKernel:
|
|
171
171
|
"""
|
|
172
172
|
Main class. Every kernel should inherit from it.
|
|
173
173
|
It does not copy the proto.
|
|
@@ -185,7 +185,13 @@ class OpRun:
|
|
|
185
185
|
"""Returns True if the kernel has subgraphs."""
|
|
186
186
|
return False
|
|
187
187
|
|
|
188
|
-
def __init__(
|
|
188
|
+
def __init__(
|
|
189
|
+
self,
|
|
190
|
+
node: onnx.NodeProto,
|
|
191
|
+
version: Optional[int] = None,
|
|
192
|
+
verbose: int = 0,
|
|
193
|
+
custom_kernels: Optional[Dict[Tuple[str, str], type]] = None,
|
|
194
|
+
):
|
|
189
195
|
assert isinstance(
|
|
190
196
|
node, onnx.NodeProto
|
|
191
197
|
), f"node must be a NodeProto but node is {type(node)}"
|
|
@@ -193,6 +199,8 @@ class OpRun:
|
|
|
193
199
|
self.domain = node.domain
|
|
194
200
|
self.input = node.input
|
|
195
201
|
self.output = node.output
|
|
202
|
+
self.verbose = verbose
|
|
203
|
+
self.custom_kernels = custom_kernels
|
|
196
204
|
if version is None:
|
|
197
205
|
name = self.__class__.__name__.split("_")
|
|
198
206
|
assert (
|
|
@@ -305,7 +313,7 @@ class OpRun:
|
|
|
305
313
|
return tuple(t.to(device) for t in tensors)
|
|
306
314
|
|
|
307
315
|
|
|
308
|
-
class OpRunFunction(
|
|
316
|
+
class OpRunFunction(OpRunKernel):
|
|
309
317
|
"""
|
|
310
318
|
Defines a kernel based on a local functions.
|
|
311
319
|
"""
|
|
@@ -315,8 +323,9 @@ class OpRunFunction(OpRun):
|
|
|
315
323
|
runtime: "onnx_diagnostic.reference.TorchOnnxEvaluator", # noqa: F821
|
|
316
324
|
node: onnx.NodeProto,
|
|
317
325
|
version: Optional[int] = None,
|
|
326
|
+
verbose: int = 0,
|
|
318
327
|
):
|
|
319
|
-
super().__init__(node, version)
|
|
328
|
+
super().__init__(node, version, verbose=verbose)
|
|
320
329
|
self.runtime = runtime
|
|
321
330
|
self.input_names = runtime.input_names
|
|
322
331
|
|
|
@@ -1,14 +1,19 @@
|
|
|
1
1
|
from typing import Optional
|
|
2
2
|
import onnx
|
|
3
3
|
import torch
|
|
4
|
-
from . import
|
|
4
|
+
from . import OpRunKernel, OpRunTensor
|
|
5
5
|
|
|
6
6
|
|
|
7
|
-
class Gather_1(
|
|
7
|
+
class Gather_1(OpRunKernel):
|
|
8
8
|
"Gather"
|
|
9
9
|
|
|
10
|
-
def __init__(
|
|
11
|
-
|
|
10
|
+
def __init__(
|
|
11
|
+
self,
|
|
12
|
+
node: onnx.NodeProto,
|
|
13
|
+
version: Optional[int] = None,
|
|
14
|
+
verbose: int = 0,
|
|
15
|
+
):
|
|
16
|
+
super().__init__(node, version, verbose=verbose)
|
|
12
17
|
axis = self.get_attribute_int(node, "axis", 0)
|
|
13
18
|
assert isinstance(axis, int), f"Unexpected value for attribute axis={axis!r}"
|
|
14
19
|
self.axis = axis
|
|
@@ -21,11 +26,16 @@ class Gather_1(OpRun):
|
|
|
21
26
|
return OpRunTensor(x.tensor[tuple(ind)])
|
|
22
27
|
|
|
23
28
|
|
|
24
|
-
class ScatterND_16(
|
|
29
|
+
class ScatterND_16(OpRunKernel):
|
|
25
30
|
"ScatterND"
|
|
26
31
|
|
|
27
|
-
def __init__(
|
|
28
|
-
|
|
32
|
+
def __init__(
|
|
33
|
+
self,
|
|
34
|
+
node: onnx.NodeProto,
|
|
35
|
+
version: Optional[int] = None,
|
|
36
|
+
verbose: int = 0,
|
|
37
|
+
):
|
|
38
|
+
super().__init__(node, version, verbose=verbose)
|
|
29
39
|
self.reduction = self.get_attribute_string(node, "reduction", "none")
|
|
30
40
|
|
|
31
41
|
def run(
|
|
@@ -54,7 +64,7 @@ class ScatterND_16(OpRun):
|
|
|
54
64
|
return OpRunTensor(output)
|
|
55
65
|
|
|
56
66
|
|
|
57
|
-
class Slice_13(
|
|
67
|
+
class Slice_13(OpRunKernel):
|
|
58
68
|
"Slice"
|
|
59
69
|
|
|
60
70
|
def run(
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
from typing import Any, Dict, Optional
|
|
2
2
|
import onnx
|
|
3
3
|
import torch
|
|
4
|
-
from . import
|
|
4
|
+
from . import OpRunKernel, OpRunTensor
|
|
5
5
|
|
|
6
6
|
|
|
7
|
-
class OpRunControlFlow(
|
|
7
|
+
class OpRunControlFlow(OpRunKernel):
|
|
8
8
|
"""Common ancestor for control flows."""
|
|
9
9
|
|
|
10
10
|
@classmethod
|
|
@@ -17,8 +17,9 @@ class OpRunControlFlow(OpRun):
|
|
|
17
17
|
node: onnx.NodeProto,
|
|
18
18
|
version: Optional[int] = None,
|
|
19
19
|
parent: Optional["onnx_diagnostic.reference.TorchOnnxEvaluator"] = None, # noqa: F821
|
|
20
|
+
verbose: int = 0,
|
|
20
21
|
):
|
|
21
|
-
super().__init__(node, version)
|
|
22
|
+
super().__init__(node, version, verbose=verbose)
|
|
22
23
|
assert (
|
|
23
24
|
parent is not None
|
|
24
25
|
), f"parent must be specified for operator {self.__class__.__name__!r}"
|
|
@@ -30,6 +31,7 @@ class OpRunControlFlow(OpRun):
|
|
|
30
31
|
opsets=parent.opsets,
|
|
31
32
|
local_functions=parent.functions,
|
|
32
33
|
verbose=parent.verbose,
|
|
34
|
+
custom_kernels=parent.custom_kernels,
|
|
33
35
|
)
|
|
34
36
|
setattr(self, att.name, rt)
|
|
35
37
|
|
|
@@ -50,8 +52,9 @@ class Loop_16(OpRunControlFlow):
|
|
|
50
52
|
node: onnx.NodeProto,
|
|
51
53
|
version: Optional[int] = None,
|
|
52
54
|
parent: Optional["onnx_diagnostic.reference.TorchOnnxEvaluator"] = None, # noqa: F821
|
|
55
|
+
verbose: int = 0,
|
|
53
56
|
):
|
|
54
|
-
super().__init__(node, version, parent)
|
|
57
|
+
super().__init__(node, version, parent, verbose=verbose)
|
|
55
58
|
self.output_index = {n: i for i, n in enumerate(self.body.output_names)}
|
|
56
59
|
self.N = len(self.body.input_names) - 2
|
|
57
60
|
self.K = len(self.body.output_names) - self.N - 1
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
from typing import Optional
|
|
2
2
|
import onnx
|
|
3
3
|
import torch
|
|
4
|
-
from . import
|
|
4
|
+
from . import OpRunKernel, OpRunTensor
|
|
5
5
|
|
|
6
6
|
|
|
7
|
-
class Range_11(
|
|
7
|
+
class Range_11(OpRunKernel):
|
|
8
8
|
"""Range"""
|
|
9
9
|
|
|
10
10
|
@classmethod
|
|
@@ -19,8 +19,9 @@ class Range_11(OpRun):
|
|
|
19
19
|
node: onnx.NodeProto,
|
|
20
20
|
version: Optional[int] = None,
|
|
21
21
|
device: Optional[torch.device] = None,
|
|
22
|
+
verbose: int = 0,
|
|
22
23
|
):
|
|
23
|
-
super().__init__(node, version)
|
|
24
|
+
super().__init__(node, version, verbose=verbose)
|
|
24
25
|
self.device = device
|
|
25
26
|
|
|
26
27
|
def run(self, starts: OpRunTensor, limit: OpRunTensor, delta: OpRunTensor) -> OpRunTensor:
|
|
@@ -2,14 +2,19 @@ from typing import Optional, Tuple
|
|
|
2
2
|
import onnx
|
|
3
3
|
import torch
|
|
4
4
|
from ...helpers.torch_helper import onnx_dtype_to_torch_dtype
|
|
5
|
-
from . import
|
|
5
|
+
from . import OpRunKernel, OpRunTensor
|
|
6
6
|
|
|
7
7
|
|
|
8
|
-
class AveragePool_11(
|
|
8
|
+
class AveragePool_11(OpRunKernel):
|
|
9
9
|
"AveragePool"
|
|
10
10
|
|
|
11
|
-
def __init__(
|
|
12
|
-
|
|
11
|
+
def __init__(
|
|
12
|
+
self,
|
|
13
|
+
node: onnx.NodeProto,
|
|
14
|
+
version: Optional[int] = None,
|
|
15
|
+
verbose: int = 0,
|
|
16
|
+
):
|
|
17
|
+
super().__init__(node, version, verbose=verbose)
|
|
13
18
|
self.auto_pad = self.get_attribute_string(node, "auto_pad", "NOTSET")
|
|
14
19
|
self.ceil_mode = bool(self.get_attribute_int(node, "ceil_mode", 0))
|
|
15
20
|
self.count_include_pad = bool(self.get_attribute_int(node, "count_include_pad", 0))
|
|
@@ -44,11 +49,16 @@ class AveragePool_11(OpRun):
|
|
|
44
49
|
)
|
|
45
50
|
|
|
46
51
|
|
|
47
|
-
class Conv_11(
|
|
52
|
+
class Conv_11(OpRunKernel):
|
|
48
53
|
"Conv"
|
|
49
54
|
|
|
50
|
-
def __init__(
|
|
51
|
-
|
|
55
|
+
def __init__(
|
|
56
|
+
self,
|
|
57
|
+
node: onnx.NodeProto,
|
|
58
|
+
version: Optional[int] = None,
|
|
59
|
+
verbose: int = 0,
|
|
60
|
+
):
|
|
61
|
+
super().__init__(node, version, verbose=verbose)
|
|
52
62
|
self.auto_pad = self.get_attribute_string(node, "auto_pad", "NOTSET")
|
|
53
63
|
self.dilations = self.get_attribute_ints(node, "dilations", None)
|
|
54
64
|
self.group = self.get_attribute_int(node, "group", 1)
|
|
@@ -108,11 +118,16 @@ class Conv_11(OpRun):
|
|
|
108
118
|
)
|
|
109
119
|
|
|
110
120
|
|
|
111
|
-
class LayerNormalization_17(
|
|
121
|
+
class LayerNormalization_17(OpRunKernel):
|
|
112
122
|
"LayerNormalization"
|
|
113
123
|
|
|
114
|
-
def __init__(
|
|
115
|
-
|
|
124
|
+
def __init__(
|
|
125
|
+
self,
|
|
126
|
+
node: onnx.NodeProto,
|
|
127
|
+
version: Optional[int] = None,
|
|
128
|
+
verbose: int = 0,
|
|
129
|
+
):
|
|
130
|
+
super().__init__(node, version, verbose=verbose)
|
|
116
131
|
self.axis = self.get_attribute_int(node, "axis", -1)
|
|
117
132
|
self.epsilon = self.get_attribute_float(node, "epsilon", 1e-5)
|
|
118
133
|
self.stash_type = onnx_dtype_to_torch_dtype(
|
|
@@ -152,11 +167,16 @@ class LayerNormalization_17(OpRun):
|
|
|
152
167
|
)
|
|
153
168
|
|
|
154
169
|
|
|
155
|
-
class Softmax_13(
|
|
170
|
+
class Softmax_13(OpRunKernel):
|
|
156
171
|
"Softmax"
|
|
157
172
|
|
|
158
|
-
def __init__(
|
|
159
|
-
|
|
173
|
+
def __init__(
|
|
174
|
+
self,
|
|
175
|
+
node: onnx.NodeProto,
|
|
176
|
+
version: Optional[int] = None,
|
|
177
|
+
verbose: int = 0,
|
|
178
|
+
):
|
|
179
|
+
super().__init__(node, version, verbose=verbose)
|
|
160
180
|
self.axis = self.get_attribute_int(node, "axis", -1)
|
|
161
181
|
assert isinstance(self.axis, int), f"Unexpected value for attribute axis={self.axis!r}"
|
|
162
182
|
# this is out of spec
|
|
@@ -169,7 +189,7 @@ class Softmax_13(OpRun):
|
|
|
169
189
|
)
|
|
170
190
|
|
|
171
191
|
|
|
172
|
-
class Tanh_6(
|
|
192
|
+
class Tanh_6(OpRunKernel):
|
|
173
193
|
"Tanh"
|
|
174
194
|
|
|
175
195
|
def run(self, data: OpRunTensor) -> OpRunTensor:
|
|
@@ -2,14 +2,14 @@ from typing import Optional
|
|
|
2
2
|
import onnx
|
|
3
3
|
import torch
|
|
4
4
|
from ...helpers.torch_helper import onnx_dtype_to_torch_dtype
|
|
5
|
-
from . import
|
|
5
|
+
from . import OpRunKernel, OpRunTensor
|
|
6
6
|
|
|
7
7
|
|
|
8
|
-
class Cast_6(
|
|
8
|
+
class Cast_6(OpRunKernel):
|
|
9
9
|
"Cast"
|
|
10
10
|
|
|
11
|
-
def __init__(self, node: onnx.NodeProto, version: Optional[int] = None):
|
|
12
|
-
super().__init__(node, version)
|
|
11
|
+
def __init__(self, node: onnx.NodeProto, version: Optional[int] = None, verbose: int = 0):
|
|
12
|
+
super().__init__(node, version, verbose=verbose)
|
|
13
13
|
to = self.get_attribute_int(node, "to", 0)
|
|
14
14
|
assert isinstance(to, int), f"Unexpected value for attribute to={to!r}"
|
|
15
15
|
self.to = onnx_dtype_to_torch_dtype(to)
|
|
@@ -20,11 +20,11 @@ class Cast_6(OpRun):
|
|
|
20
20
|
return OpRunTensor(data.tensor.to(self.to))
|
|
21
21
|
|
|
22
22
|
|
|
23
|
-
class CastLike_15(
|
|
23
|
+
class CastLike_15(OpRunKernel):
|
|
24
24
|
"Cast"
|
|
25
25
|
|
|
26
|
-
def __init__(self, node: onnx.NodeProto, version: Optional[int] = None):
|
|
27
|
-
super().__init__(node, version)
|
|
26
|
+
def __init__(self, node: onnx.NodeProto, version: Optional[int] = None, verbose: int = 0):
|
|
27
|
+
super().__init__(node, version, verbose=verbose)
|
|
28
28
|
self.saturate = self.get_attribute_int(node, "saturate", 1)
|
|
29
29
|
assert self.saturate == 1, f"saturate={self.saturate} not implemented for CastLike"
|
|
30
30
|
|
|
@@ -32,11 +32,11 @@ class CastLike_15(OpRun):
|
|
|
32
32
|
return OpRunTensor(data.tensor.to(like.tensor.dtype))
|
|
33
33
|
|
|
34
34
|
|
|
35
|
-
class Concat_1(
|
|
35
|
+
class Concat_1(OpRunKernel):
|
|
36
36
|
"Concat"
|
|
37
37
|
|
|
38
|
-
def __init__(self, node: onnx.NodeProto, version: Optional[int] = None):
|
|
39
|
-
super().__init__(node, version)
|
|
38
|
+
def __init__(self, node: onnx.NodeProto, version: Optional[int] = None, verbose: int = 0):
|
|
39
|
+
super().__init__(node, version, verbose=verbose)
|
|
40
40
|
axis = self.get_attribute_int(node, "axis", 0)
|
|
41
41
|
assert isinstance(axis, int), f"Unexpected value for attribute axis={axis!r}"
|
|
42
42
|
self.axis = axis
|
|
@@ -59,36 +59,36 @@ class Concat_1(OpRun):
|
|
|
59
59
|
return OpRunTensor(torch.cat([t.tensor.to(device) for t in data], axis=self.axis))
|
|
60
60
|
|
|
61
61
|
|
|
62
|
-
class NonZero_13(
|
|
62
|
+
class NonZero_13(OpRunKernel):
|
|
63
63
|
"NonZero"
|
|
64
64
|
|
|
65
65
|
def run(self, x: OpRunTensor) -> OpRunTensor:
|
|
66
66
|
return OpRunTensor(torch.nonzero(x.tensor).T)
|
|
67
67
|
|
|
68
68
|
|
|
69
|
-
class Tile_6(
|
|
69
|
+
class Tile_6(OpRunKernel):
|
|
70
70
|
"Tile"
|
|
71
71
|
|
|
72
72
|
def run(self, x: OpRunTensor, repeat: OpRunTensor) -> OpRunTensor:
|
|
73
73
|
return OpRunTensor(torch.tile(x.tensor, repeat.as_tuple_int))
|
|
74
74
|
|
|
75
75
|
|
|
76
|
-
class Transpose_1(
|
|
76
|
+
class Transpose_1(OpRunKernel):
|
|
77
77
|
"Transpose"
|
|
78
78
|
|
|
79
|
-
def __init__(self, node: onnx.NodeProto, version: Optional[int] = None):
|
|
80
|
-
super().__init__(node, version)
|
|
79
|
+
def __init__(self, node: onnx.NodeProto, version: Optional[int] = None, verbose: int = 0):
|
|
80
|
+
super().__init__(node, version, verbose=verbose)
|
|
81
81
|
self.perm = self.get_attribute_ints(node, "perm", None)
|
|
82
82
|
|
|
83
83
|
def run(self, data: OpRunTensor) -> OpRunTensor:
|
|
84
84
|
return OpRunTensor(torch.permute(data.tensor, self.perm))
|
|
85
85
|
|
|
86
86
|
|
|
87
|
-
class Trilu_14(
|
|
87
|
+
class Trilu_14(OpRunKernel):
|
|
88
88
|
"Trilu"
|
|
89
89
|
|
|
90
|
-
def __init__(self, node: onnx.NodeProto, version: Optional[int] = None):
|
|
91
|
-
super().__init__(node, version)
|
|
90
|
+
def __init__(self, node: onnx.NodeProto, version: Optional[int] = None, verbose: int = 0):
|
|
91
|
+
super().__init__(node, version, verbose=verbose)
|
|
92
92
|
self.upper = self.get_attribute_int(node, "upper", 1)
|
|
93
93
|
|
|
94
94
|
def run(self, data: OpRunTensor, k: Optional[OpRunTensor] = None) -> OpRunTensor:
|
|
@@ -98,7 +98,7 @@ class Trilu_14(OpRun):
|
|
|
98
98
|
return OpRunTensor(torch.tril(data.tensor, diagonal=diagonal))
|
|
99
99
|
|
|
100
100
|
|
|
101
|
-
class Where_9(
|
|
101
|
+
class Where_9(OpRunKernel):
|
|
102
102
|
"Where"
|
|
103
103
|
|
|
104
104
|
def run(self, cond: OpRunTensor, x: OpRunTensor, y: OpRunTensor) -> OpRunTensor:
|
|
@@ -2,12 +2,12 @@ from typing import Optional, Tuple
|
|
|
2
2
|
import onnx
|
|
3
3
|
import torch
|
|
4
4
|
from ...helpers.torch_helper import onnx_dtype_to_torch_dtype
|
|
5
|
-
from . import
|
|
5
|
+
from . import OpRunKernel, OpRunTensor
|
|
6
6
|
|
|
7
7
|
|
|
8
|
-
class ReduceOp(
|
|
9
|
-
def __init__(self, node: onnx.NodeProto, version: Optional[int] = None):
|
|
10
|
-
super().__init__(node, version)
|
|
8
|
+
class ReduceOp(OpRunKernel):
|
|
9
|
+
def __init__(self, node: onnx.NodeProto, version: Optional[int] = None, verbose: int = 0):
|
|
10
|
+
super().__init__(node, version, verbose=verbose)
|
|
11
11
|
self.keepdims = bool(self.get_attribute_int(node, "keepdims", 1))
|
|
12
12
|
self.noop_with_empty_axes = bool(
|
|
13
13
|
self.get_attribute_int(node, "noop_with_empty_axes", 0)
|
|
@@ -28,8 +28,8 @@ class ReduceOp(OpRun):
|
|
|
28
28
|
|
|
29
29
|
|
|
30
30
|
class ReduceOpAxes(ReduceOp):
|
|
31
|
-
def __init__(self, node: onnx.NodeProto, version: Optional[int] = None):
|
|
32
|
-
super().__init__(node, version)
|
|
31
|
+
def __init__(self, node: onnx.NodeProto, version: Optional[int] = None, verbose: int = 0):
|
|
32
|
+
super().__init__(node, version, verbose=verbose)
|
|
33
33
|
self.axes: Tuple[int, ...] = self.get_attribute_ints(node, "axes") or tuple()
|
|
34
34
|
|
|
35
35
|
|
|
@@ -2,18 +2,18 @@ from typing import Optional
|
|
|
2
2
|
import onnx
|
|
3
3
|
import torch
|
|
4
4
|
from ...helpers.torch_helper import onnx_dtype_to_torch_dtype
|
|
5
|
-
from . import
|
|
5
|
+
from . import OpRunKernel, OpRunSequence, OpRunTensor
|
|
6
6
|
|
|
7
7
|
|
|
8
|
-
class OpRunOpSequence(
|
|
8
|
+
class OpRunOpSequence(OpRunKernel):
|
|
9
9
|
"Ancestor for kernel using sequences."
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
class ConcatFromSequence_11(OpRunOpSequence):
|
|
13
13
|
"ConcatFromSequence"
|
|
14
14
|
|
|
15
|
-
def __init__(self, node: onnx.NodeProto, version: Optional[int] = None):
|
|
16
|
-
super().__init__(node, version)
|
|
15
|
+
def __init__(self, node: onnx.NodeProto, version: Optional[int] = None, verbose: int = 0):
|
|
16
|
+
super().__init__(node, version, verbose=verbose)
|
|
17
17
|
axis = self.get_attribute_int(node, "axis", None)
|
|
18
18
|
assert isinstance(axis, int), f"Unexpected value for attribute axis={axis!r}"
|
|
19
19
|
self.axis = axis
|
|
@@ -39,8 +39,8 @@ class ConcatFromSequence_11(OpRunOpSequence):
|
|
|
39
39
|
class SequenceEmpty_11(OpRunOpSequence):
|
|
40
40
|
"SqeuenceEmpty"
|
|
41
41
|
|
|
42
|
-
def __init__(self, node: onnx.NodeProto, version: Optional[int] = None):
|
|
43
|
-
super().__init__(node, version)
|
|
42
|
+
def __init__(self, node: onnx.NodeProto, version: Optional[int] = None, verbose: int = 0):
|
|
43
|
+
super().__init__(node, version, verbose=verbose)
|
|
44
44
|
self.dtype = onnx_dtype_to_torch_dtype(
|
|
45
45
|
self.get_attribute_int(node, "dtype", onnx.TensorProto.FLOAT) # type: ignore[arg-type]
|
|
46
46
|
)
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
from typing import Optional, Tuple
|
|
2
2
|
import onnx
|
|
3
3
|
import torch
|
|
4
|
-
from . import
|
|
4
|
+
from . import OpRunKernel, OpRunTensor
|
|
5
5
|
|
|
6
6
|
|
|
7
|
-
class ConstantOfShape_9(
|
|
7
|
+
class ConstantOfShape_9(OpRunKernel):
|
|
8
8
|
"ConstantOfShape"
|
|
9
9
|
|
|
10
10
|
@classmethod
|
|
@@ -19,8 +19,9 @@ class ConstantOfShape_9(OpRun):
|
|
|
19
19
|
node: onnx.NodeProto,
|
|
20
20
|
version: Optional[int] = None,
|
|
21
21
|
device: Optional[torch.device] = None,
|
|
22
|
+
verbose: int = 0,
|
|
22
23
|
):
|
|
23
|
-
super().__init__(node, version)
|
|
24
|
+
super().__init__(node, version, verbose=verbose)
|
|
24
25
|
value = self.get_attribute_tensor(node, "value")
|
|
25
26
|
if value is None:
|
|
26
27
|
value = torch.tensor([0], dtype=torch.float32)
|
|
@@ -37,7 +38,7 @@ class ConstantOfShape_9(OpRun):
|
|
|
37
38
|
)
|
|
38
39
|
|
|
39
40
|
|
|
40
|
-
class Expand_8(
|
|
41
|
+
class Expand_8(OpRunKernel):
|
|
41
42
|
"Expand"
|
|
42
43
|
|
|
43
44
|
def run(self, data: OpRunTensor, shape: OpRunTensor) -> OpRunTensor:
|
|
@@ -45,11 +46,11 @@ class Expand_8(OpRun):
|
|
|
45
46
|
return OpRunTensor(data.tensor.expand(ishape))
|
|
46
47
|
|
|
47
48
|
|
|
48
|
-
class Reshape_14(
|
|
49
|
+
class Reshape_14(OpRunKernel):
|
|
49
50
|
"Reshape"
|
|
50
51
|
|
|
51
|
-
def __init__(self, node: onnx.NodeProto, version: Optional[int] = None):
|
|
52
|
-
super().__init__(node, version)
|
|
52
|
+
def __init__(self, node: onnx.NodeProto, version: Optional[int] = None, verbose: int = 0):
|
|
53
|
+
super().__init__(node, version, verbose=verbose)
|
|
53
54
|
self.allowzero = self.get_attribute_int(node, "allowzero", 0)
|
|
54
55
|
|
|
55
56
|
def run(self, data: OpRunTensor, shape: OpRunTensor) -> OpRunTensor:
|
|
@@ -64,9 +65,9 @@ class Reshape_14(OpRun):
|
|
|
64
65
|
return OpRunTensor(data.tensor.reshape(ishape))
|
|
65
66
|
|
|
66
67
|
|
|
67
|
-
class Shape_15(
|
|
68
|
-
def __init__(self, node: onnx.NodeProto, version: Optional[int] = None):
|
|
69
|
-
super().__init__(node, version)
|
|
68
|
+
class Shape_15(OpRunKernel):
|
|
69
|
+
def __init__(self, node: onnx.NodeProto, version: Optional[int] = None, verbose: int = 0):
|
|
70
|
+
super().__init__(node, version, verbose=verbose)
|
|
70
71
|
self.start = self.get_attribute_int(node, "start", 0)
|
|
71
72
|
self.end = self.get_attribute_int(node, "end", None)
|
|
72
73
|
|
|
@@ -76,9 +77,9 @@ class Shape_15(OpRun):
|
|
|
76
77
|
return OpRunTensor(torch.tensor(sh, dtype=torch.int64), is_constant=True)
|
|
77
78
|
|
|
78
79
|
|
|
79
|
-
class Split_18(
|
|
80
|
-
def __init__(self, node: onnx.NodeProto, version: Optional[int] = None):
|
|
81
|
-
super().__init__(node, version)
|
|
80
|
+
class Split_18(OpRunKernel):
|
|
81
|
+
def __init__(self, node: onnx.NodeProto, version: Optional[int] = None, verbose: int = 0):
|
|
82
|
+
super().__init__(node, version, verbose=verbose)
|
|
82
83
|
self.axis = self.get_attribute_int(node, "axis", 0)
|
|
83
84
|
self.num_outputs = self.get_attribute_int(node, "num_outputs", None)
|
|
84
85
|
|
|
@@ -101,7 +102,7 @@ class Split_18(OpRun):
|
|
|
101
102
|
return tuple(OpRunTensor(t) for t in spl)
|
|
102
103
|
|
|
103
104
|
|
|
104
|
-
class Squeeze_13(
|
|
105
|
+
class Squeeze_13(OpRunKernel):
|
|
105
106
|
"Squeeze"
|
|
106
107
|
|
|
107
108
|
def run(self, data: OpRunTensor, axes: Optional[OpRunTensor] = None) -> OpRunTensor:
|
|
@@ -110,7 +111,7 @@ class Squeeze_13(OpRun):
|
|
|
110
111
|
return OpRunTensor(data.tensor.squeeze(axes.as_tuple_int))
|
|
111
112
|
|
|
112
113
|
|
|
113
|
-
class Unsqueeze_13(
|
|
114
|
+
class Unsqueeze_13(OpRunKernel):
|
|
114
115
|
"Unsqueeze"
|
|
115
116
|
|
|
116
117
|
def run(self, data: OpRunTensor, axes: OpRunTensor) -> OpRunTensor:
|
|
@@ -1,85 +1,85 @@
|
|
|
1
1
|
import torch
|
|
2
|
-
from . import
|
|
2
|
+
from . import OpRunKernel, OpRunTensor
|
|
3
3
|
|
|
4
4
|
|
|
5
|
-
class Abs_1(
|
|
5
|
+
class Abs_1(OpRunKernel):
|
|
6
6
|
"""Abs"""
|
|
7
7
|
|
|
8
8
|
def run(self, x: OpRunTensor) -> OpRunTensor:
|
|
9
9
|
return OpRunTensor(torch.abs(x.tensor))
|
|
10
10
|
|
|
11
11
|
|
|
12
|
-
class Cos_1(
|
|
12
|
+
class Cos_1(OpRunKernel):
|
|
13
13
|
"""Cos"""
|
|
14
14
|
|
|
15
15
|
def run(self, x: OpRunTensor) -> OpRunTensor:
|
|
16
16
|
return OpRunTensor(x.tensor.cos())
|
|
17
17
|
|
|
18
18
|
|
|
19
|
-
class Erf_9(
|
|
19
|
+
class Erf_9(OpRunKernel):
|
|
20
20
|
"""Erf"""
|
|
21
21
|
|
|
22
22
|
def run(self, x: OpRunTensor) -> OpRunTensor:
|
|
23
23
|
return OpRunTensor(x.tensor.erf())
|
|
24
24
|
|
|
25
25
|
|
|
26
|
-
class Exp_1(
|
|
26
|
+
class Exp_1(OpRunKernel):
|
|
27
27
|
"""Exp"""
|
|
28
28
|
|
|
29
29
|
def run(self, x: OpRunTensor) -> OpRunTensor:
|
|
30
30
|
return OpRunTensor(x.tensor.exp())
|
|
31
31
|
|
|
32
32
|
|
|
33
|
-
class Identity_1(
|
|
33
|
+
class Identity_1(OpRunKernel):
|
|
34
34
|
"Identity"
|
|
35
35
|
|
|
36
36
|
def run(self, x: OpRunTensor) -> OpRunTensor:
|
|
37
37
|
return OpRunTensor(x.tensor)
|
|
38
38
|
|
|
39
39
|
|
|
40
|
-
class Log_1(
|
|
40
|
+
class Log_1(OpRunKernel):
|
|
41
41
|
"""Log"""
|
|
42
42
|
|
|
43
43
|
def run(self, x: OpRunTensor) -> OpRunTensor:
|
|
44
44
|
return OpRunTensor(x.tensor.log())
|
|
45
45
|
|
|
46
46
|
|
|
47
|
-
class Neg_1(
|
|
47
|
+
class Neg_1(OpRunKernel):
|
|
48
48
|
"""Neg"""
|
|
49
49
|
|
|
50
50
|
def run(self, x: OpRunTensor) -> OpRunTensor:
|
|
51
51
|
return OpRunTensor(-x.tensor)
|
|
52
52
|
|
|
53
53
|
|
|
54
|
-
class Not_1(
|
|
54
|
+
class Not_1(OpRunKernel):
|
|
55
55
|
"""Not"""
|
|
56
56
|
|
|
57
57
|
def run(self, x: OpRunTensor) -> OpRunTensor:
|
|
58
58
|
return OpRunTensor(~x.tensor)
|
|
59
59
|
|
|
60
60
|
|
|
61
|
-
class Reciprocal_1(
|
|
61
|
+
class Reciprocal_1(OpRunKernel):
|
|
62
62
|
"""REciprocal"""
|
|
63
63
|
|
|
64
64
|
def run(self, x: OpRunTensor) -> OpRunTensor:
|
|
65
65
|
return OpRunTensor(1 / x.tensor)
|
|
66
66
|
|
|
67
67
|
|
|
68
|
-
class Sigmoid_6(
|
|
68
|
+
class Sigmoid_6(OpRunKernel):
|
|
69
69
|
"""Sqrt"""
|
|
70
70
|
|
|
71
71
|
def run(self, x: OpRunTensor) -> OpRunTensor:
|
|
72
72
|
return OpRunTensor(torch.sigmoid(x.tensor))
|
|
73
73
|
|
|
74
74
|
|
|
75
|
-
class Sin_1(
|
|
75
|
+
class Sin_1(OpRunKernel):
|
|
76
76
|
"""Sin"""
|
|
77
77
|
|
|
78
78
|
def run(self, x: OpRunTensor) -> OpRunTensor:
|
|
79
79
|
return OpRunTensor(x.tensor.sin())
|
|
80
80
|
|
|
81
81
|
|
|
82
|
-
class Sqrt_1(
|
|
82
|
+
class Sqrt_1(OpRunKernel):
|
|
83
83
|
"""Sqrt"""
|
|
84
84
|
|
|
85
85
|
def run(self, x: OpRunTensor) -> OpRunTensor:
|
|
@@ -278,6 +278,8 @@ def validate_model(
|
|
|
278
278
|
) -> Tuple[Dict[str, Union[int, float, str]], Dict[str, Any]]:
|
|
279
279
|
"""
|
|
280
280
|
Validates a model.
|
|
281
|
+
The function can also be called through the command line
|
|
282
|
+
:ref:`l-cmd-validate`.
|
|
281
283
|
|
|
282
284
|
:param model_id: model id to validate
|
|
283
285
|
:param task: task used to generate the necessary inputs,
|
|
@@ -285,7 +287,8 @@ def validate_model(
|
|
|
285
287
|
if it can be determined
|
|
286
288
|
:param do_run: checks the model works with the defined inputs
|
|
287
289
|
:param exporter: exporter the model using this exporter,
|
|
288
|
-
available list: ``export-strict``, ``export-nostrict``,
|
|
290
|
+
available list: ``export-strict``, ``export-nostrict``, ...
|
|
291
|
+
see below
|
|
289
292
|
:param do_same: checks the discrepancies of the exported model
|
|
290
293
|
:param verbose: verbosity level
|
|
291
294
|
:param dtype: uses this dtype to check the model
|
|
@@ -322,6 +325,20 @@ def validate_model(
|
|
|
322
325
|
information:
|
|
323
326
|
|
|
324
327
|
* ``PRINT_CONFIG``: prints the model configuration
|
|
328
|
+
|
|
329
|
+
The following exporters are available:
|
|
330
|
+
|
|
331
|
+
* ``export-nostrict``: run :func:`torch.export.export` (..., strict=False)
|
|
332
|
+
* ``onnx-dynamo``: run :func:`torch.onnx.export` (..., dynamo=True),
|
|
333
|
+
models can be optimized with ``optimization`` in ``("ir", "os_ort")``
|
|
334
|
+
* ``modelbuilder``: use :epkg:`ModelBuilder` to builds the onnx model
|
|
335
|
+
* ``custom``: custom exporter (see :epkg:`experimental-experiment`),
|
|
336
|
+
models can be optimized with ``optimization`` in
|
|
337
|
+
``("default", "default+onnxruntime", "default+os_ort", "default+onnxruntime+os_ort")``
|
|
338
|
+
|
|
339
|
+
The default runtime, :epkg:`onnxruntime` is used to validate a model and check the
|
|
340
|
+
exported model returns the same outputs as the original one, otherwise,
|
|
341
|
+
:class:`onnx_diagnostic.reference.TorchOnnxEvaluator` is used.
|
|
325
342
|
"""
|
|
326
343
|
assert (
|
|
327
344
|
not rewrite or patch
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
onnx_diagnostic/__init__.py,sha256=
|
|
1
|
+
onnx_diagnostic/__init__.py,sha256=P1AdnI_jw7SIojX7zxqBeAy83xQePX59KApD_RBNnOY,173
|
|
2
2
|
onnx_diagnostic/__main__.py,sha256=YmyV_Aq_ianDlHyKLHMa6h8YK3ZmFPpLVHLKjM91aCk,79
|
|
3
3
|
onnx_diagnostic/_command_lines_parser.py,sha256=WSoopSHjXWEgFvzyfGe3_c-hZoStuQPQc_k08siFuf4,19211
|
|
4
4
|
onnx_diagnostic/api.py,sha256=BhCl_yCd78N7TlVtPOHjeYv1QBEy39TjZ647rcHqLh0,345
|
|
@@ -12,6 +12,7 @@ onnx_diagnostic/helpers/args_helper.py,sha256=SRWnqC7EENg09RZlA50B_PcdiIhdbgA4C3
|
|
|
12
12
|
onnx_diagnostic/helpers/bench_run.py,sha256=CGA6VMJZMH2gDhVueT9ypNm4PMcjGrrGFYp08nhWj9k,16539
|
|
13
13
|
onnx_diagnostic/helpers/cache_helper.py,sha256=soKjyIXa7EQgALd9PAUGIKYzXlJGoLevYiQDsxoqkQ4,8349
|
|
14
14
|
onnx_diagnostic/helpers/config_helper.py,sha256=aZATKVbZuw8L56KQpwMNcqJ3Qi5OplzS_N3ETR3hmj0,3351
|
|
15
|
+
onnx_diagnostic/helpers/doc_helper.py,sha256=RLNqNrZx9NxwaryVu8NcImV9l9azEoK9OpQn3gqBxds,5328
|
|
15
16
|
onnx_diagnostic/helpers/graph_helper.py,sha256=hevQT5a7_QuriVPQcbT5qe18n99Doyl5h3-qshx1-uk,14093
|
|
16
17
|
onnx_diagnostic/helpers/helper.py,sha256=oPybQruFcVLqvqLDhjphOZ8zZU1HHJWAlABMuTkAO8A,57090
|
|
17
18
|
onnx_diagnostic/helpers/memory_peak.py,sha256=OT6mz0muBbBZY0pjgW2_eCk_lOtFRo-5w4jFo2Z6Kok,6380
|
|
@@ -25,7 +26,7 @@ onnx_diagnostic/reference/__init__.py,sha256=nrd09rRuwMDBCPTSZ6kSKZXp1W9W_ExO1t9
|
|
|
25
26
|
onnx_diagnostic/reference/evaluator.py,sha256=RzNzjFDeMe-4X51Tb22N6aagazY5ktNq-mRmPcfY5EU,8848
|
|
26
27
|
onnx_diagnostic/reference/ort_evaluator.py,sha256=OaWMREF8fuJwimmONpIjQ6WxQT1X2roDsdJsgR8H_Cg,24853
|
|
27
28
|
onnx_diagnostic/reference/quantized_tensor.py,sha256=5u67uS2uGacdMD5VYCbpojNjiesDlV_kO0fAJ0vUWGE,1098
|
|
28
|
-
onnx_diagnostic/reference/torch_evaluator.py,sha256=
|
|
29
|
+
onnx_diagnostic/reference/torch_evaluator.py,sha256=ekQTYo0YPVdcM6TGRnEk0mDmGHUOwi0OpcMOWJsRvT8,26572
|
|
29
30
|
onnx_diagnostic/reference/ops/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
|
|
30
31
|
onnx_diagnostic/reference/ops/op_add_add_mul_mul.py,sha256=CXQVtgVrT066gDJFwxL4nDSY4G8r08XNu3EwhWqMapU,1521
|
|
31
32
|
onnx_diagnostic/reference/ops/op_attention.py,sha256=ThALMDF53v3QeG1bohi0bvX2o90HZhGJbbAFOtwEHPE,2027
|
|
@@ -55,18 +56,18 @@ onnx_diagnostic/reference/ops/op_skip_layer_normalization.py,sha256=oJ7fQNx2iQh9
|
|
|
55
56
|
onnx_diagnostic/reference/ops/op_slice.py,sha256=yRxfYBs8b7QezyyG9JHCD8MIJHij2qR2NNDpBmD3FJI,705
|
|
56
57
|
onnx_diagnostic/reference/ops/op_transpose_cast.py,sha256=ifef74rvh0Yvq1Zx51B4mfnISbxV9uRg9DFjkdL1_68,361
|
|
57
58
|
onnx_diagnostic/reference/ops/op_tri_matrix.py,sha256=Yn2gxAyygcwtF5Hjau9ihXDAzul0BAkdqVimVahtFBU,519
|
|
58
|
-
onnx_diagnostic/reference/torch_ops/__init__.py,sha256=
|
|
59
|
-
onnx_diagnostic/reference/torch_ops/_op_run.py,sha256=
|
|
60
|
-
onnx_diagnostic/reference/torch_ops/access_ops.py,sha256=
|
|
61
|
-
onnx_diagnostic/reference/torch_ops/binary_ops.py,sha256
|
|
62
|
-
onnx_diagnostic/reference/torch_ops/controlflow_ops.py,sha256=
|
|
63
|
-
onnx_diagnostic/reference/torch_ops/generator_ops.py,sha256=
|
|
64
|
-
onnx_diagnostic/reference/torch_ops/nn_ops.py,sha256=
|
|
65
|
-
onnx_diagnostic/reference/torch_ops/other_ops.py,sha256=
|
|
66
|
-
onnx_diagnostic/reference/torch_ops/reduce_ops.py,sha256=
|
|
67
|
-
onnx_diagnostic/reference/torch_ops/sequence_ops.py,sha256=
|
|
68
|
-
onnx_diagnostic/reference/torch_ops/shape_ops.py,sha256=
|
|
69
|
-
onnx_diagnostic/reference/torch_ops/unary_ops.py,sha256=
|
|
59
|
+
onnx_diagnostic/reference/torch_ops/__init__.py,sha256=eZ7FBYH9Ta3BC0f7BJQAnIqiebqRkCt2_T3ktpVV6iQ,1150
|
|
60
|
+
onnx_diagnostic/reference/torch_ops/_op_run.py,sha256=EEUIwfbRldEFDhULquYhk9x5ZDa9t6f2mKJ1sM__D6A,10517
|
|
61
|
+
onnx_diagnostic/reference/torch_ops/access_ops.py,sha256=Zfs5OF03PV1CqlCqKI5VV-c4MY3KyQxmO7QZksxQjX8,3274
|
|
62
|
+
onnx_diagnostic/reference/torch_ops/binary_ops.py,sha256=-KxMcCYGDTcZyOss9qU1nU0rmdyg9SdVHJQohseSTcQ,2653
|
|
63
|
+
onnx_diagnostic/reference/torch_ops/controlflow_ops.py,sha256=uOEmzbM4nR2FwZQ8UikwEaHih3yw6T24D_VLYkr5RSU,4518
|
|
64
|
+
onnx_diagnostic/reference/torch_ops/generator_ops.py,sha256=dqqFvhkazVxRUDYhO2t-Z1etqoUt30LeX-8Pb9ZcbaM,926
|
|
65
|
+
onnx_diagnostic/reference/torch_ops/nn_ops.py,sha256=TeFxQEiTezx9UUzu82ToCLUnUOU56kKv6X81RdZ8UC8,7238
|
|
66
|
+
onnx_diagnostic/reference/torch_ops/other_ops.py,sha256=FnCY60mhdrzrsiHgvN-XpFRHYUpI0gIRqxgVK5J_na0,3995
|
|
67
|
+
onnx_diagnostic/reference/torch_ops/reduce_ops.py,sha256=9gFfraPTQbe_ZEUNCUis1JSmA5dj4tSzjAOpZPJKG4Y,5102
|
|
68
|
+
onnx_diagnostic/reference/torch_ops/sequence_ops.py,sha256=3EiVKpGfN4d1Iry4hgnr3MIJyEEKUrAIDgmRGsUXXa0,2297
|
|
69
|
+
onnx_diagnostic/reference/torch_ops/shape_ops.py,sha256=pJrNR2UB4PlWl6cv4EDl1uGl8YTBUUMQkhJcsh5K4sA,4291
|
|
70
|
+
onnx_diagnostic/reference/torch_ops/unary_ops.py,sha256=E8Ys1eZsOTsucBKoXb1_Kl5LbBDygniDvW2BvN4IPMo,1708
|
|
70
71
|
onnx_diagnostic/tasks/__init__.py,sha256=5XXM-rv-Hk2gSHvqsww9DzVd9mcRifacgcPgvPCjnDM,2412
|
|
71
72
|
onnx_diagnostic/tasks/automatic_speech_recognition.py,sha256=oRoYy56M0Yv_WOcn1hJXv-R9wgHkJ8rbym7j7y8oslw,6851
|
|
72
73
|
onnx_diagnostic/tasks/feature_extraction.py,sha256=V-T5NpZ6EimOz00weWWxGfksZ9jQ5ZQyaP-mxuCEuJo,2223
|
|
@@ -95,7 +96,7 @@ onnx_diagnostic/torch_export_patches/patches/patch_torch.py,sha256=KaZ8TjDa9ATgT
|
|
|
95
96
|
onnx_diagnostic/torch_export_patches/patches/patch_transformers.py,sha256=Hf-U50vzgzJ4iUjS2LAYkbfmzCEwX80Dzvdrr-Rhlp0,26456
|
|
96
97
|
onnx_diagnostic/torch_models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
97
98
|
onnx_diagnostic/torch_models/llms.py,sha256=soyg4yC87ptGoeulJhKqw5opGmuLvH1pn_ZDXZ4Jr8E,90
|
|
98
|
-
onnx_diagnostic/torch_models/test_helper.py,sha256=
|
|
99
|
+
onnx_diagnostic/torch_models/test_helper.py,sha256=32uFEZwILyOWHrj-qaNfIv4P2ySe7A0lN2WQ4eVEudA,59604
|
|
99
100
|
onnx_diagnostic/torch_models/hghub/__init__.py,sha256=vi1Q7YHdddj1soiBN42MSvJdFqe2_KUoWafHISjwOu8,58
|
|
100
101
|
onnx_diagnostic/torch_models/hghub/hub_api.py,sha256=BgM_p57Q0gT9GOhdrmOYcnbuTTzCWp80jS4OQqWwFhs,9990
|
|
101
102
|
onnx_diagnostic/torch_models/hghub/hub_data.py,sha256=885wKyZkdM-Qp5Sg6C9Ol1dxigmA8FYAko-Ys08sppo,8096
|
|
@@ -107,8 +108,8 @@ onnx_diagnostic/torch_models/untrained/llm_tiny_llm.py,sha256=7N3fGvT_4Mn4NbIo0Q
|
|
|
107
108
|
onnx_diagnostic/torch_onnx/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
108
109
|
onnx_diagnostic/torch_onnx/runtime_info.py,sha256=1g9F_Jf9AAgYQU4stbsrFXwQl-30mWlQrFbQ7val8Ps,9268
|
|
109
110
|
onnx_diagnostic/torch_onnx/sbs.py,sha256=1EL25DeYFzlBSiFG_XjePBLvsiItRXbdDrr5-QZW2mA,16878
|
|
110
|
-
onnx_diagnostic-0.6.
|
|
111
|
-
onnx_diagnostic-0.6.
|
|
112
|
-
onnx_diagnostic-0.6.
|
|
113
|
-
onnx_diagnostic-0.6.
|
|
114
|
-
onnx_diagnostic-0.6.
|
|
111
|
+
onnx_diagnostic-0.6.2.dist-info/licenses/LICENSE.txt,sha256=Vv6TXglX6Rc0d-f8aREhayhT-6PMQXEyOmI2NKlUCMc,1045
|
|
112
|
+
onnx_diagnostic-0.6.2.dist-info/METADATA,sha256=GwbmPUz9oOj_KKA_164p9H-RxNtpGz1Smn-eTJm4sGA,6643
|
|
113
|
+
onnx_diagnostic-0.6.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
114
|
+
onnx_diagnostic-0.6.2.dist-info/top_level.txt,sha256=KwNkXewmcobM3ZT1DJLVWH6ebJzA5qKg7cWqKfpGNT4,16
|
|
115
|
+
onnx_diagnostic-0.6.2.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|