onnx-diagnostic 0.6.1__py3-none-any.whl → 0.6.3__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/_command_lines_parser.py +24 -3
- onnx_diagnostic/doc.py +46 -0
- onnx_diagnostic/helpers/doc_helper.py +163 -0
- onnx_diagnostic/helpers/model_builder_helper.py +3 -0
- onnx_diagnostic/helpers/onnx_helper.py +291 -7
- 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_export_patches/patch_module_helper.py +1 -0
- onnx_diagnostic/torch_models/test_helper.py +34 -12
- {onnx_diagnostic-0.6.1.dist-info → onnx_diagnostic-0.6.3.dist-info}/METADATA +1 -1
- {onnx_diagnostic-0.6.1.dist-info → onnx_diagnostic-0.6.3.dist-info}/RECORD +26 -25
- {onnx_diagnostic-0.6.1.dist-info → onnx_diagnostic-0.6.3.dist-info}/WHEEL +0 -0
- {onnx_diagnostic-0.6.1.dist-info → onnx_diagnostic-0.6.3.dist-info}/licenses/LICENSE.txt +0 -0
- {onnx_diagnostic-0.6.1.dist-info → onnx_diagnostic-0.6.3.dist-info}/top_level.txt +0 -0
|
@@ -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, verbose=0):
|
|
172
|
+
super().__init__(node, version, verbose=verbose)
|
|
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
|
|