onnxscript 0.1.0__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.
- onnxscript/__init__.py +131 -0
- onnxscript/_framework_apis/__init__.py +3 -0
- onnxscript/_framework_apis/torch_2_5.py +117 -0
- onnxscript/_framework_apis/torch_2_6.py +45 -0
- onnxscript/_internal/__init__.py +0 -0
- onnxscript/_internal/analysis.py +229 -0
- onnxscript/_internal/ast_utils.py +64 -0
- onnxscript/_internal/autocast.py +250 -0
- onnxscript/_internal/deprecation.py +78 -0
- onnxscript/_internal/param_manipulation.py +148 -0
- onnxscript/_internal/runtime_typing.py +43 -0
- onnxscript/_internal/utils.py +99 -0
- onnxscript/_internal/version_utils.py +118 -0
- onnxscript/_legacy_ir/__init__.py +341 -0
- onnxscript/_legacy_ir/visitor.py +937 -0
- onnxscript/_thirdparty/asciichartpy.py +313 -0
- onnxscript/backend/__init__.py +2 -0
- onnxscript/backend/onnx_backend.py +303 -0
- onnxscript/backend/onnx_export.py +885 -0
- onnxscript/converter.py +1470 -0
- onnxscript/evaluator.py +619 -0
- onnxscript/function_libs/tools/torch_lib/deduce_type_constraints.py +403 -0
- onnxscript/function_libs/tools/torch_lib/generate_aten_signatures.py +333 -0
- onnxscript/function_libs/tools/torch_lib/generate_prims_signatures.py +331 -0
- onnxscript/function_libs/torch_lib/__init__.py +12 -0
- onnxscript/function_libs/torch_lib/_constants.py +5 -0
- onnxscript/function_libs/torch_lib/_flags.py +58 -0
- onnxscript/function_libs/torch_lib/graph_building/__init__.py +56 -0
- onnxscript/function_libs/torch_lib/graph_building/_graph_building_ir.py +723 -0
- onnxscript/function_libs/torch_lib/graph_building/_graph_building_torch.py +1125 -0
- onnxscript/function_libs/torch_lib/ops/__init__.py +27 -0
- onnxscript/function_libs/torch_lib/ops/common.py +80 -0
- onnxscript/function_libs/torch_lib/ops/core.py +8935 -0
- onnxscript/function_libs/torch_lib/ops/fft.py +385 -0
- onnxscript/function_libs/torch_lib/ops/linalg.py +399 -0
- onnxscript/function_libs/torch_lib/ops/nested.py +25 -0
- onnxscript/function_libs/torch_lib/ops/nn.py +2713 -0
- onnxscript/function_libs/torch_lib/ops/prims.py +850 -0
- onnxscript/function_libs/torch_lib/ops/quantized_decomposed.py +63 -0
- onnxscript/function_libs/torch_lib/ops/sparse.py +23 -0
- onnxscript/function_libs/torch_lib/ops/special.py +387 -0
- onnxscript/function_libs/torch_lib/ops/vision.py +25 -0
- onnxscript/function_libs/torch_lib/registration.py +151 -0
- onnxscript/function_libs/torch_lib/tensor_typing.py +74 -0
- onnxscript/ir/__init__.py +153 -0
- onnxscript/ir/_convenience.py +447 -0
- onnxscript/ir/_core.py +3119 -0
- onnxscript/ir/_display.py +49 -0
- onnxscript/ir/_enums.py +163 -0
- onnxscript/ir/_graph_comparison.py +23 -0
- onnxscript/ir/_io.py +97 -0
- onnxscript/ir/_linked_list.py +276 -0
- onnxscript/ir/_metadata.py +44 -0
- onnxscript/ir/_name_authority.py +72 -0
- onnxscript/ir/_polyfill.py +25 -0
- onnxscript/ir/_protocols.py +598 -0
- onnxscript/ir/_schemas.py +548 -0
- onnxscript/ir/_tape.py +120 -0
- onnxscript/ir/_type_casting.py +106 -0
- onnxscript/ir/convenience.py +32 -0
- onnxscript/ir/external_data.py +396 -0
- onnxscript/ir/passes/__init__.py +33 -0
- onnxscript/ir/passes/_pass_infra.py +172 -0
- onnxscript/ir/serde.py +1620 -0
- onnxscript/ir/tensor_adapters.py +122 -0
- onnxscript/ir/traversal.py +82 -0
- onnxscript/irbuilder.py +542 -0
- onnxscript/main.py +167 -0
- onnxscript/onnx_opset/__init__.py +232 -0
- onnxscript/onnx_opset/_impl/opset1.py +4100 -0
- onnxscript/onnx_opset/_impl/opset10.py +1227 -0
- onnxscript/onnx_opset/_impl/opset11.py +4013 -0
- onnxscript/onnx_opset/_impl/opset12.py +1078 -0
- onnxscript/onnx_opset/_impl/opset13.py +3924 -0
- onnxscript/onnx_opset/_impl/opset14.py +999 -0
- onnxscript/onnx_opset/_impl/opset15.py +604 -0
- onnxscript/onnx_opset/_impl/opset16.py +1255 -0
- onnxscript/onnx_opset/_impl/opset17.py +561 -0
- onnxscript/onnx_opset/_impl/opset18.py +1803 -0
- onnxscript/onnx_opset/_impl/opset19.py +1942 -0
- onnxscript/onnx_opset/_impl/opset2.py +218 -0
- onnxscript/onnx_opset/_impl/opset20.py +675 -0
- onnxscript/onnx_opset/_impl/opset21.py +1976 -0
- onnxscript/onnx_opset/_impl/opset22.py +2588 -0
- onnxscript/onnx_opset/_impl/opset3.py +199 -0
- onnxscript/onnx_opset/_impl/opset4.py +77 -0
- onnxscript/onnx_opset/_impl/opset5.py +84 -0
- onnxscript/onnx_opset/_impl/opset6.py +944 -0
- onnxscript/onnx_opset/_impl/opset7.py +1243 -0
- onnxscript/onnx_opset/_impl/opset8.py +444 -0
- onnxscript/onnx_opset/_impl/opset9.py +1485 -0
- onnxscript/onnx_opset/_impl/opset_ai_onnx_ml1.py +974 -0
- onnxscript/onnx_opset/_impl/opset_ai_onnx_ml2.py +112 -0
- onnxscript/onnx_opset/_impl/opset_ai_onnx_ml3.py +308 -0
- onnxscript/onnx_opset/_impl/opset_ai_onnx_ml4.py +129 -0
- onnxscript/onnx_opset/_impl/opset_ai_onnx_ml5.py +158 -0
- onnxscript/onnx_opset/_impl/opset_ai_onnx_preview_training1.py +577 -0
- onnxscript/onnx_types.py +229 -0
- onnxscript/optimizer/__init__.py +39 -0
- onnxscript/optimizer/_constant_folding.py +1083 -0
- onnxscript/optimizer/_inliner.py +312 -0
- onnxscript/optimizer/_legacy/_optimizer.py +98 -0
- onnxscript/optimizer/_legacy/_remove_unused_proto.py +144 -0
- onnxscript/optimizer/_legacy/_simple_function_folding.py +243 -0
- onnxscript/optimizer/_legacy/constant_folding.py +293 -0
- onnxscript/optimizer/_legacy/evaluator.py +439 -0
- onnxscript/optimizer/_optimizer.py +61 -0
- onnxscript/optimizer/_remove_unused.py +106 -0
- onnxscript/optimizer/_remove_unused_function.py +72 -0
- onnxscript/py.typed +1 -0
- onnxscript/rewriter/__init__.py +56 -0
- onnxscript/rewriter/_ir_utils.py +111 -0
- onnxscript/rewriter/broadcast_to_matmul.py +180 -0
- onnxscript/rewriter/cast_constant_of_shape.py +50 -0
- onnxscript/rewriter/collapse_slices.py +141 -0
- onnxscript/rewriter/erfgelu.py +27 -0
- onnxscript/rewriter/function_rule.py +232 -0
- onnxscript/rewriter/gemm_to_matmul_add.py +21 -0
- onnxscript/rewriter/generic_pattern.py +700 -0
- onnxscript/rewriter/llama_rule_sets.py +287 -0
- onnxscript/rewriter/no_op.py +56 -0
- onnxscript/rewriter/onnxruntime/__init__.py +50 -0
- onnxscript/rewriter/onnxruntime/bfloat16_utils/bfloat16_converter.py +99 -0
- onnxscript/rewriter/onnxruntime/fused_matmul_rule_sets.py +177 -0
- onnxscript/rewriter/onnxruntime/group_normalization_merge_silu.py +64 -0
- onnxscript/rewriter/onnxruntime/instance_to_group_normalization.py +155 -0
- onnxscript/rewriter/onnxruntime/softmax.py +63 -0
- onnxscript/rewriter/onnxruntime/transformers/__init__.py +21 -0
- onnxscript/rewriter/onnxruntime/transformers/biassplitgelu.py +31 -0
- onnxscript/rewriter/onnxruntime/transformers/fastgelu.py +29 -0
- onnxscript/rewriter/onnxruntime/transformers/layernorm.py +47 -0
- onnxscript/rewriter/onnxruntime/transformers/multihead_attention.py +715 -0
- onnxscript/rewriter/ort_fusions/__init__.py +9 -0
- onnxscript/rewriter/ort_fusions/_core.py +28 -0
- onnxscript/rewriter/ort_fusions/_smollm_1.py +253 -0
- onnxscript/rewriter/ort_fusions/_smollm_2.py +467 -0
- onnxscript/rewriter/ort_fusions/_test_models.py +122 -0
- onnxscript/rewriter/ort_fusions/_test_utils.py +42 -0
- onnxscript/rewriter/ort_fusions/cos_sin_cache.py +154 -0
- onnxscript/rewriter/ort_fusions/gqa.py +156 -0
- onnxscript/rewriter/ort_fusions/mha.py +198 -0
- onnxscript/rewriter/ort_fusions/rms_normalization.py +95 -0
- onnxscript/rewriter/ort_fusions/rotary_embedding.py +64 -0
- onnxscript/rewriter/ort_fusions/sdpa.py +75 -0
- onnxscript/rewriter/ort_fusions/skip_normalization.py +46 -0
- onnxscript/rewriter/pattern.py +1714 -0
- onnxscript/rewriter/testing.py +77 -0
- onnxscript/sourceinfo.py +59 -0
- onnxscript/tensor.py +227 -0
- onnxscript/testing/__init__.py +482 -0
- onnxscript/tools/__init__.py +4 -0
- onnxscript/tools/benchmark/__init__.py +23 -0
- onnxscript/tools/benchmark/benchmark_helpers.py +783 -0
- onnxscript/tools/benchmark/benchmark_run.py +140 -0
- onnxscript/tools/benchmark/export_model.py +207 -0
- onnxscript/tools/benchmark/export_model_batch.py +146 -0
- onnxscript/tools/memory_peak.py +244 -0
- onnxscript/tools/training_helper.py +50 -0
- onnxscript/tools/transformers_models/__init__.py +190 -0
- onnxscript/tools/transformers_models/llama.py +168 -0
- onnxscript/tools/transformers_models/mistral.py +238 -0
- onnxscript/tools/transformers_models/phi.py +248 -0
- onnxscript/tools/transformers_models/phi3.py +259 -0
- onnxscript/type_annotation.py +281 -0
- onnxscript/utils/__init__.py +0 -0
- onnxscript/utils/evaluation_utils.py +56 -0
- onnxscript/utils/timing_utils.py +33 -0
- onnxscript/utils/utils.py +84 -0
- onnxscript/values.py +790 -0
- onnxscript/version_converter/__init__.py +21 -0
- onnxscript/version_converter/_version_converter.py +314 -0
- onnxscript-0.1.0.dist-info/LICENSE +21 -0
- onnxscript-0.1.0.dist-info/METADATA +370 -0
- onnxscript-0.1.0.dist-info/RECORD +176 -0
- onnxscript-0.1.0.dist-info/WHEEL +5 -0
- onnxscript-0.1.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
# Copyright (c) Microsoft Corporation.
|
|
2
|
+
# Licensed under the MIT License.
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import ClassVar
|
|
6
|
+
|
|
7
|
+
import onnx.numpy_helper
|
|
8
|
+
|
|
9
|
+
import onnxscript.ir as ir
|
|
10
|
+
import onnxscript.rewriter._ir_utils as ir_utils
|
|
11
|
+
import onnxscript.rewriter.no_op as no_op
|
|
12
|
+
import onnxscript.rewriter.pattern as orp
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class CastIdentity(orp.RewriteRuleAsClass):
|
|
16
|
+
"""Replaces ``Cast(., to=to)`` by ``Identity`` if possible."""
|
|
17
|
+
|
|
18
|
+
@classmethod
|
|
19
|
+
def pattern(cls, op, x, to):
|
|
20
|
+
return op.Cast(x, to=to)
|
|
21
|
+
|
|
22
|
+
@classmethod
|
|
23
|
+
def rewrite(cls, op, x: ir.Value, to: ir.Attr):
|
|
24
|
+
return op.Identity(x)
|
|
25
|
+
|
|
26
|
+
@classmethod
|
|
27
|
+
def check(cls, context, x, to) -> bool:
|
|
28
|
+
return x.dtype == to.value
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class CastCast(orp.RewriteRuleAsClass):
|
|
32
|
+
"""Replaces ``Cast(Cast(X, ...), to=to)`` by ``Cast(X, to=to)``."""
|
|
33
|
+
|
|
34
|
+
_allowed_tensor_types: ClassVar = {
|
|
35
|
+
onnx.TensorProto.FLOAT,
|
|
36
|
+
onnx.TensorProto.FLOAT16,
|
|
37
|
+
onnx.TensorProto.BFLOAT16,
|
|
38
|
+
onnx.TensorProto.DOUBLE,
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
@classmethod
|
|
42
|
+
def pattern(cls, op, x, to, to_ignored):
|
|
43
|
+
return op.Cast(op.Cast(x, to=to_ignored), to=to)
|
|
44
|
+
|
|
45
|
+
@classmethod
|
|
46
|
+
def check(cls, context, x: ir.Value, to: ir.Attr, to_ignored: ir.Attr) -> bool:
|
|
47
|
+
return (
|
|
48
|
+
to.value in cls._allowed_tensor_types
|
|
49
|
+
and to_ignored.value in cls._allowed_tensor_types
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
@classmethod
|
|
53
|
+
def rewrite(cls, op, x: ir.Value, to: ir.Attr, to_ignored: ir.Attr):
|
|
54
|
+
return op.Cast(x, to=to)
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
class ExpandIdentity(orp.RewriteRuleAsClass):
|
|
58
|
+
"""Replaces ``Expand(..., shape)`` by ``Identity`` if possible."""
|
|
59
|
+
|
|
60
|
+
@classmethod
|
|
61
|
+
def pattern(cls, op, x, shape):
|
|
62
|
+
return op.Expand(x, shape)
|
|
63
|
+
|
|
64
|
+
@classmethod
|
|
65
|
+
def rewrite(cls, op, x: ir.Value, shape: ir.Value):
|
|
66
|
+
return op.Identity(x)
|
|
67
|
+
|
|
68
|
+
@classmethod
|
|
69
|
+
def check(cls, context, x, shape) -> bool:
|
|
70
|
+
if shape.const_value is None:
|
|
71
|
+
# Shape is not a constant and cannot be guessed.
|
|
72
|
+
return False
|
|
73
|
+
if (x_shape := x.shape) is None:
|
|
74
|
+
# We don't know the shape of the input
|
|
75
|
+
return False
|
|
76
|
+
return x_shape.dims == tuple(shape.const_value.numpy().tolist())
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
class ReshapeReshape(orp.RewriteRuleAsClass):
|
|
80
|
+
"""Replaces ``Reshape(Reshape(X, ...), shape)`` by ``Reshape(X, shape)``.
|
|
81
|
+
The pattern matches only if second reshape reshapes into a shape
|
|
82
|
+
with positive values.
|
|
83
|
+
"""
|
|
84
|
+
|
|
85
|
+
@classmethod
|
|
86
|
+
def pattern(cls, op, x, shape_ignored, shape):
|
|
87
|
+
return op.Reshape(op.Reshape(x, shape_ignored), shape)
|
|
88
|
+
|
|
89
|
+
@classmethod
|
|
90
|
+
def rewrite(cls, op, x: ir.Value, shape_ignored: ir.Value, shape: ir.Value):
|
|
91
|
+
return op.Reshape(x, shape)
|
|
92
|
+
|
|
93
|
+
@classmethod
|
|
94
|
+
def check(cls, context, x, shape_ignored, shape) -> bool:
|
|
95
|
+
if shape_ignored.const_value is None or shape.const_value is None:
|
|
96
|
+
return False
|
|
97
|
+
if shape.const_value.numpy().min() <= 0:
|
|
98
|
+
return False
|
|
99
|
+
return True
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
class SlicesSplit(orp.RewriteRuleAsClass):
|
|
103
|
+
"""Replaces ``Slice(x, ...), Slice(x, ...)``
|
|
104
|
+
by ``Split(x, ...)`` if possible.
|
|
105
|
+
"""
|
|
106
|
+
|
|
107
|
+
@classmethod
|
|
108
|
+
def pattern(cls, op, x, begin0, end0, axes0, begin1, end1, axes1):
|
|
109
|
+
return op.Slice(x, begin0, end0, axes0), op.Slice(x, begin1, end1, axes1)
|
|
110
|
+
|
|
111
|
+
@classmethod
|
|
112
|
+
def check(cls, context, x, begin0, end0, axes0, begin1, end1, axes1) -> bool:
|
|
113
|
+
if (
|
|
114
|
+
axes0.const_value is None
|
|
115
|
+
or axes1.const_value is None
|
|
116
|
+
or axes0.const_value.numpy().tolist() != axes1.const_value.numpy().tolist()
|
|
117
|
+
):
|
|
118
|
+
return False
|
|
119
|
+
axes = axes0.const_value.numpy().tolist()
|
|
120
|
+
if len(axes) != 1:
|
|
121
|
+
return False
|
|
122
|
+
if x.shape:
|
|
123
|
+
rk = len(x.shape)
|
|
124
|
+
else:
|
|
125
|
+
rk = x.rank
|
|
126
|
+
if axes[0] != -1 and axes[0] != rk - 1:
|
|
127
|
+
return False
|
|
128
|
+
if (
|
|
129
|
+
begin0.const_value is None
|
|
130
|
+
or end0.const_value is None
|
|
131
|
+
or begin1.const_value is None
|
|
132
|
+
or end1.const_value is None
|
|
133
|
+
):
|
|
134
|
+
return False
|
|
135
|
+
if begin0.const_value.numpy().tolist() != [0]:
|
|
136
|
+
return False
|
|
137
|
+
e0, b1, e1 = (
|
|
138
|
+
end0.const_value.numpy().tolist(),
|
|
139
|
+
begin1.const_value.numpy().tolist(),
|
|
140
|
+
end1.const_value.numpy().tolist(),
|
|
141
|
+
)
|
|
142
|
+
if e0[0] != b1[0]:
|
|
143
|
+
return False
|
|
144
|
+
shape = x.shape
|
|
145
|
+
if shape is None:
|
|
146
|
+
return False
|
|
147
|
+
last_dim = shape[-1]
|
|
148
|
+
if not isinstance(last_dim, int):
|
|
149
|
+
return False
|
|
150
|
+
if last_dim != e1[0]:
|
|
151
|
+
return False
|
|
152
|
+
if last_dim // 2 != b1[0]:
|
|
153
|
+
return False
|
|
154
|
+
return True
|
|
155
|
+
|
|
156
|
+
@classmethod
|
|
157
|
+
def rewrite(cls, op, x, begin0, end0, axes0, begin1, end1, axes1):
|
|
158
|
+
return op.Split(x, num_outputs=2, axis=-1, _outputs=2)
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
class TransposeIdentity(orp.RewriteRuleAsClass):
|
|
162
|
+
"""Replaces ``Transpose(. perm=perm)``
|
|
163
|
+
when the permutation is identity.
|
|
164
|
+
"""
|
|
165
|
+
|
|
166
|
+
@classmethod
|
|
167
|
+
def pattern(cls, op, x, perm):
|
|
168
|
+
return op.Transpose(x, perm=perm)
|
|
169
|
+
|
|
170
|
+
@classmethod
|
|
171
|
+
def check(cls, context, x: ir.Value, perm: ir.Attr) -> bool:
|
|
172
|
+
if isinstance(perm, ir.RefAttr):
|
|
173
|
+
return False
|
|
174
|
+
if perm.type == ir.AttributeType.INTS:
|
|
175
|
+
if perm.value == list(range(len(perm.value))):
|
|
176
|
+
return True
|
|
177
|
+
return False
|
|
178
|
+
|
|
179
|
+
@classmethod
|
|
180
|
+
def rewrite(cls, op, x: ir.Value, perm: ir.Attr):
|
|
181
|
+
return op.Identity(x)
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
class TransposeTranspose(orp.RewriteRuleAsClass):
|
|
185
|
+
"""Replaces ``Transpose(Transpose(., perm=perm1), perm=perm2)``
|
|
186
|
+
when both permutations are inverse.
|
|
187
|
+
"""
|
|
188
|
+
|
|
189
|
+
@classmethod
|
|
190
|
+
def pattern(cls, op, x, perm1, perm2):
|
|
191
|
+
return op.Transpose(op.Transpose(x, perm=perm1), perm=perm2)
|
|
192
|
+
|
|
193
|
+
@classmethod
|
|
194
|
+
def check(cls, context, x: ir.Value, perm1: ir.Attr, perm2: ir.Attr) -> bool:
|
|
195
|
+
if isinstance(perm1, ir.RefAttr) or isinstance(perm2, ir.RefAttr):
|
|
196
|
+
return False
|
|
197
|
+
return True
|
|
198
|
+
|
|
199
|
+
@classmethod
|
|
200
|
+
def _apply_transpose(cls, perm: tuple[int, ...], on: list[int]) -> list[int]:
|
|
201
|
+
assert len(perm) == len(on), "length mismatch"
|
|
202
|
+
res = [-1 for i in on]
|
|
203
|
+
for i, p in enumerate(perm):
|
|
204
|
+
res[i] = on[p]
|
|
205
|
+
return res
|
|
206
|
+
|
|
207
|
+
@classmethod
|
|
208
|
+
def _apply_transposes(
|
|
209
|
+
cls, perms: list[tuple[int, ...]], on: list[int] | None = None
|
|
210
|
+
) -> list[int]:
|
|
211
|
+
if on is None:
|
|
212
|
+
on = list(range(len(perms[0])))
|
|
213
|
+
for p in perms:
|
|
214
|
+
on = cls._apply_transpose(p, on)
|
|
215
|
+
return on
|
|
216
|
+
|
|
217
|
+
@classmethod
|
|
218
|
+
def rewrite(cls, op, x: ir.Value, perm1: ir.Attr, perm2: ir.Attr):
|
|
219
|
+
first = list(range(len(perm1.value)))
|
|
220
|
+
last = cls._apply_transposes([perm1.value, perm2.value])
|
|
221
|
+
if first == last:
|
|
222
|
+
return op.Identity(x)
|
|
223
|
+
return op.Transpose(x, perm=last)
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
class UnsqueezeUnsqueeze(orp.RewriteRuleAsClass):
|
|
227
|
+
"""Replaces ``Unsqueeze(Unsqueeze(., axes1), axes2)`` with one Unsqueeze."""
|
|
228
|
+
|
|
229
|
+
@classmethod
|
|
230
|
+
def pattern(cls, op, x, axes1, axes2):
|
|
231
|
+
return op.Unsqueeze(op.Unsqueeze(x, axes1), axes2)
|
|
232
|
+
|
|
233
|
+
@classmethod
|
|
234
|
+
def rewrite(cls, op, x: ir.Value, axes1: ir.Value, axes2: ir.Value):
|
|
235
|
+
v1 = ir_utils.get_singleton_value(axes1)
|
|
236
|
+
v2 = ir_utils.get_singleton_value(axes2)
|
|
237
|
+
axes = [v1, v2] if v1 < v2 else [v2, v1 + 1]
|
|
238
|
+
return op.Unsqueeze(x, op.Constant(value=ir.tensor(axes, dtype=ir.DataType.INT64)))
|
|
239
|
+
|
|
240
|
+
@classmethod
|
|
241
|
+
def check(cls, context, x, axes1, axes2) -> bool:
|
|
242
|
+
del context # Unused
|
|
243
|
+
del x # Unused
|
|
244
|
+
# Currently restricted to single element positive axis
|
|
245
|
+
v1 = ir_utils.get_singleton_value(axes1)
|
|
246
|
+
v2 = ir_utils.get_singleton_value(axes2)
|
|
247
|
+
if v1 is None or v2 is None:
|
|
248
|
+
return False
|
|
249
|
+
if (v1 < 0) or (v2 < 0):
|
|
250
|
+
return False
|
|
251
|
+
return True
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
cast_cast_rule = orp.make_rewrite_rule_from_class(CastCast)
|
|
255
|
+
cast_identity_rule = orp.make_rewrite_rule_from_class(CastIdentity)
|
|
256
|
+
expand_identity_rule = orp.make_rewrite_rule_from_class(ExpandIdentity)
|
|
257
|
+
reshape_reshape_rule = orp.make_rewrite_rule_from_class(ReshapeReshape)
|
|
258
|
+
slice_split_rule = orp.make_rewrite_rule_from_class(SlicesSplit, True)
|
|
259
|
+
transpose_identity_rule = orp.make_rewrite_rule_from_class(TransposeIdentity)
|
|
260
|
+
transpose_transpose_rule = orp.make_rewrite_rule_from_class(TransposeTranspose)
|
|
261
|
+
unsqueeze_unsqueeze_rule = orp.make_rewrite_rule_from_class(UnsqueezeUnsqueeze)
|
|
262
|
+
|
|
263
|
+
|
|
264
|
+
def llama_p0_rule_set() -> orp.RewriteRuleSet:
|
|
265
|
+
"""Returns a set of rules which should be applied
|
|
266
|
+
before any other one as they usually remove unnecessary computation
|
|
267
|
+
such as the multiplication by 1 or two consecutive transpose.
|
|
268
|
+
|
|
269
|
+
Returns:
|
|
270
|
+
RewriteRuleSet
|
|
271
|
+
"""
|
|
272
|
+
return orp.RewriteRuleSet(
|
|
273
|
+
[
|
|
274
|
+
no_op.mul_by_1_rule,
|
|
275
|
+
no_op.add_0_rule,
|
|
276
|
+
no_op.add_0_rule,
|
|
277
|
+
no_op.div_by_1_rule,
|
|
278
|
+
cast_cast_rule,
|
|
279
|
+
cast_identity_rule,
|
|
280
|
+
expand_identity_rule,
|
|
281
|
+
reshape_reshape_rule,
|
|
282
|
+
slice_split_rule,
|
|
283
|
+
transpose_identity_rule,
|
|
284
|
+
transpose_transpose_rule,
|
|
285
|
+
unsqueeze_unsqueeze_rule,
|
|
286
|
+
]
|
|
287
|
+
)
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# Copyright (c) Microsoft Corporation.
|
|
2
|
+
# Licensed under the MIT License.
|
|
3
|
+
from onnxscript.rewriter import pattern
|
|
4
|
+
|
|
5
|
+
# TODO: Support 1-D constant tensors
|
|
6
|
+
# https://github.com/microsoft/onnx-rewriter/issues/186
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
# Pattern to match against
|
|
10
|
+
def mul_by_1(op, x):
|
|
11
|
+
return x * 1
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def add_0(op, x):
|
|
15
|
+
return x + 0
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def sub_0(op, x):
|
|
19
|
+
return x - 0
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def div_by_1(op, x):
|
|
23
|
+
return x / 1
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def dropout_zero(op, x):
|
|
27
|
+
return op.Dropout(x, ratio=0.0)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def dropout_inference(op, x):
|
|
31
|
+
return op.Dropout(x, training_mode=False)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
# Replacement
|
|
35
|
+
def identity(op, x, **_):
|
|
36
|
+
return op.Identity(x)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
mul_by_1_rule = pattern.RewriteRule(mul_by_1, identity)
|
|
40
|
+
add_0_rule = pattern.RewriteRule(add_0, identity)
|
|
41
|
+
sub_0_rule = pattern.RewriteRule(sub_0, identity)
|
|
42
|
+
div_by_1_rule = pattern.RewriteRule(div_by_1, identity)
|
|
43
|
+
dropout_zero_rule = pattern.RewriteRule(dropout_zero, identity)
|
|
44
|
+
dropout_inference_rule = pattern.RewriteRule(dropout_inference, identity)
|
|
45
|
+
# TODO: Include Mul by 0, 0 by Mul, 0 by Div? Those would be 0s, but not no-ops
|
|
46
|
+
|
|
47
|
+
rules = pattern.RewriteRuleSet(
|
|
48
|
+
[
|
|
49
|
+
*mul_by_1_rule.commute(),
|
|
50
|
+
*add_0_rule.commute(),
|
|
51
|
+
sub_0_rule,
|
|
52
|
+
div_by_1_rule,
|
|
53
|
+
dropout_zero_rule,
|
|
54
|
+
dropout_inference_rule,
|
|
55
|
+
]
|
|
56
|
+
)
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# Copyright (c) Microsoft Corporation.
|
|
2
|
+
# Licensed under the MIT License.
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import onnx
|
|
6
|
+
|
|
7
|
+
from onnxscript.rewriter import function_rule, pattern
|
|
8
|
+
from onnxscript.rewriter import rewrite as _rewrite
|
|
9
|
+
from onnxscript.rewriter.onnxruntime import (
|
|
10
|
+
fused_matmul_rule_sets,
|
|
11
|
+
group_normalization_merge_silu,
|
|
12
|
+
instance_to_group_normalization,
|
|
13
|
+
softmax,
|
|
14
|
+
transformers,
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
ORT_FUNCTION_REWRITE_RULES = [*transformers.TRANSFORMERS_FUNCTION_REWRITE_RULES]
|
|
18
|
+
|
|
19
|
+
ORT_PATTERN_REWRITE_RULES = [
|
|
20
|
+
*softmax.rules.rules,
|
|
21
|
+
*instance_to_group_normalization.rules.rules,
|
|
22
|
+
# NOTE: group normalization merge silu should be applied after instance to group normalization
|
|
23
|
+
*group_normalization_merge_silu.rules.rules,
|
|
24
|
+
*fused_matmul_rule_sets.fused_matmul_rule_sets(),
|
|
25
|
+
]
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def rewrite(
|
|
29
|
+
model_proto: onnx.ModelProto,
|
|
30
|
+
/,
|
|
31
|
+
function_rules: list[type[function_rule.FunctionRewriteRule]] | None = None,
|
|
32
|
+
pattern_rules: list[pattern.RewriteRule] | None = None,
|
|
33
|
+
) -> onnx.ModelProto:
|
|
34
|
+
"""Rewrite the model using the given rules.
|
|
35
|
+
|
|
36
|
+
Args:
|
|
37
|
+
model_proto: The model to rewrite.
|
|
38
|
+
function_rules: The function rewrite rules to apply. If None, the default rules
|
|
39
|
+
for onnxruntime are used.
|
|
40
|
+
pattern_rules: The pattern rewrite rules to apply. If None, the default rules
|
|
41
|
+
for onnxruntime are used.
|
|
42
|
+
|
|
43
|
+
Returns:
|
|
44
|
+
The rewritten model.
|
|
45
|
+
"""
|
|
46
|
+
function_rules = function_rules or ORT_FUNCTION_REWRITE_RULES
|
|
47
|
+
pattern_rules = pattern_rules or ORT_PATTERN_REWRITE_RULES
|
|
48
|
+
return _rewrite(
|
|
49
|
+
model_proto, function_rewrite_rules=function_rules, pattern_rewrite_rules=pattern_rules
|
|
50
|
+
)
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
# Copyright (c) Microsoft Corporation.
|
|
2
|
+
# Licensed under the MIT License.
|
|
3
|
+
import logging
|
|
4
|
+
|
|
5
|
+
from onnxscript import ir
|
|
6
|
+
|
|
7
|
+
logger = logging.getLogger(__name__)
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def _convert_inputs_from_bfloat16_to_float16(value: ir.Value) -> None:
|
|
11
|
+
if value.dtype != ir.DataType.BFLOAT16:
|
|
12
|
+
return
|
|
13
|
+
value.dtype = ir.DataType.FLOAT16
|
|
14
|
+
_insert_cast_nodes_for_float16_to_bfloat16_to_inputs(value)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def _convert_outputs_from_bfloat16_to_float16(value: ir.Value) -> None:
|
|
18
|
+
if value.dtype != ir.DataType.BFLOAT16:
|
|
19
|
+
return
|
|
20
|
+
_insert_cast_nodes_for_bfloat16_to_float16_to_outputs(value)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def _insert_cast_nodes_for_float16_to_bfloat16_to_inputs(value: ir.Value) -> None:
|
|
24
|
+
user_nodes_and_indices = tuple(value.uses())
|
|
25
|
+
|
|
26
|
+
attr = ir.AttrInt64(name="to", value=ir.DataType.BFLOAT16)
|
|
27
|
+
cast = ir.Node(
|
|
28
|
+
domain="",
|
|
29
|
+
op_type="Cast",
|
|
30
|
+
inputs=[value],
|
|
31
|
+
num_outputs=1,
|
|
32
|
+
attributes=[attr],
|
|
33
|
+
)
|
|
34
|
+
cast.outputs[0].dtype = ir.DataType.BFLOAT16
|
|
35
|
+
cast.outputs[0].shape = value.shape
|
|
36
|
+
|
|
37
|
+
for node, index in tuple(value.uses()):
|
|
38
|
+
if node is cast:
|
|
39
|
+
continue
|
|
40
|
+
node.replace_input_with(index, cast.outputs[0])
|
|
41
|
+
|
|
42
|
+
# NOTE: A safer way to insert the cast node is to prepend it to the first node
|
|
43
|
+
# of the graph
|
|
44
|
+
assert user_nodes_and_indices[0][0].graph is not None, "The node should belong to a graph"
|
|
45
|
+
user_nodes_and_indices[0][0].graph[0].prepend(cast)
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def _insert_cast_nodes_for_bfloat16_to_float16_to_outputs(value: ir.Value) -> None:
|
|
49
|
+
node = value.producer()
|
|
50
|
+
index = value.index()
|
|
51
|
+
if node is None or index is None:
|
|
52
|
+
logger.warning("Output value %s has no producer or index", value)
|
|
53
|
+
return
|
|
54
|
+
|
|
55
|
+
attr = ir.AttrInt64(name="to", value=ir.DataType.FLOAT16)
|
|
56
|
+
cast = ir.Node(
|
|
57
|
+
domain="",
|
|
58
|
+
op_type="Cast",
|
|
59
|
+
inputs=[node.outputs[index]],
|
|
60
|
+
num_outputs=1,
|
|
61
|
+
attributes=[attr],
|
|
62
|
+
)
|
|
63
|
+
cast.outputs[0].dtype = ir.DataType.FLOAT16
|
|
64
|
+
cast.outputs[0].shape = node.outputs[index].shape
|
|
65
|
+
node.append(cast)
|
|
66
|
+
|
|
67
|
+
assert node.graph is not None, "Node graph should not be None"
|
|
68
|
+
# Update graph/function outputs
|
|
69
|
+
for idx, graph_or_function_output in enumerate(node.graph.outputs):
|
|
70
|
+
if graph_or_function_output == node.outputs[index]:
|
|
71
|
+
node.graph.outputs[idx] = cast.outputs[0]
|
|
72
|
+
# Swap the output name of the node with the output name of the cast node to
|
|
73
|
+
# preserve the output name in the graph
|
|
74
|
+
node.outputs[index].name, cast.outputs[0].name = (
|
|
75
|
+
cast.outputs[0].name,
|
|
76
|
+
node.outputs[index].name,
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def dtype_adapter_for_bfloat16_model(model: ir.Model) -> None:
|
|
81
|
+
"""Adapt the model datatype if it's bfloat16.
|
|
82
|
+
|
|
83
|
+
Because onnxruntime does not support bfloat16 as input/output datatype, we need to
|
|
84
|
+
convert the bfloat16 datatype to float16. This function will convert the bfloat16
|
|
85
|
+
datatype to float16 and insert Cast nodes to convert float16 to bfloat16.
|
|
86
|
+
|
|
87
|
+
Model:
|
|
88
|
+
inputs(float16) -> Cast(bfloat16) -> nodes(bfloat16) -> Cast(float16) -> outputs(float16)
|
|
89
|
+
|
|
90
|
+
TODO: Delete this function after onnxruntime supports bfloat16.
|
|
91
|
+
|
|
92
|
+
Args:
|
|
93
|
+
model: The model to adapt.
|
|
94
|
+
|
|
95
|
+
"""
|
|
96
|
+
for input in model.graph.inputs:
|
|
97
|
+
_convert_inputs_from_bfloat16_to_float16(input)
|
|
98
|
+
for output in model.graph.outputs:
|
|
99
|
+
_convert_outputs_from_bfloat16_to_float16(output)
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
# Copyright (c) Microsoft Corporation.
|
|
2
|
+
# Licensed under the MIT License.
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import ClassVar
|
|
6
|
+
|
|
7
|
+
import onnxscript.rewriter.pattern as orp
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class FusedMatMulDiv1(orp.RewriteRuleAsClass):
|
|
11
|
+
"""Replaces ``MatMul + Div`` by FusedMatMul."""
|
|
12
|
+
|
|
13
|
+
@classmethod
|
|
14
|
+
def pattern(cls, op, x, y, cst):
|
|
15
|
+
return op.Div(op.MatMul(x, y), cst)
|
|
16
|
+
|
|
17
|
+
@classmethod
|
|
18
|
+
def check(cls, context, x, y, cst) -> bool:
|
|
19
|
+
if cst.const_value is None:
|
|
20
|
+
return False
|
|
21
|
+
value = cst.const_value.numpy()
|
|
22
|
+
if value.size > 1:
|
|
23
|
+
return False
|
|
24
|
+
return True
|
|
25
|
+
|
|
26
|
+
@classmethod
|
|
27
|
+
def rewrite(cls, op, x, y, cst):
|
|
28
|
+
value = cst.const_value.numpy()
|
|
29
|
+
c = float(value[0] if value.shape == (1,) else value)
|
|
30
|
+
return op.FusedMatMul(x, y, alpha=1 / c, _domain="com.microsoft")
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class FusedMatMulDiv2(orp.RewriteRuleAsClass):
|
|
34
|
+
"""Replaces ``FusedMatMul + Div`` by FusedMatMul."""
|
|
35
|
+
|
|
36
|
+
@classmethod
|
|
37
|
+
def pattern(cls, op, x, y, cst):
|
|
38
|
+
return op.Div(op.FusedMatMul(x, y, _domain="com.microsoft"), cst)
|
|
39
|
+
|
|
40
|
+
@classmethod
|
|
41
|
+
def check(cls, context, x, y, cst) -> bool:
|
|
42
|
+
if cst.const_value is None:
|
|
43
|
+
return False
|
|
44
|
+
if cst.const_value.numpy().size > 1:
|
|
45
|
+
return False
|
|
46
|
+
return True
|
|
47
|
+
|
|
48
|
+
@classmethod
|
|
49
|
+
def rewrite(cls, op, x, y, cst):
|
|
50
|
+
value = cst.const_value.numpy()
|
|
51
|
+
c = float(value[0] if value.shape == (1,) else value)
|
|
52
|
+
node = list(x.uses())[0][0] # noqa: RUF015
|
|
53
|
+
|
|
54
|
+
kwargs = {}
|
|
55
|
+
alpha = node.attributes.get("alpha", None)
|
|
56
|
+
kwargs["alpha"] = alpha.value / c if alpha else 1.0 / c
|
|
57
|
+
for name in ["transA", "transB", "transBatchA", "transBatchB"]:
|
|
58
|
+
att = node.attributes.get(name)
|
|
59
|
+
if att:
|
|
60
|
+
kwargs[name] = att.value
|
|
61
|
+
return op.FusedMatMul(x, y, **kwargs, _domain="com.microsoft")
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
class _TransposeMatMulBase(orp.RewriteRuleAsClass):
|
|
65
|
+
_pos: ClassVar = 1
|
|
66
|
+
|
|
67
|
+
@classmethod
|
|
68
|
+
def check(cls, context, x, y) -> bool:
|
|
69
|
+
perm = list((x if cls._pos == 1 else y).uses())[0][0].attributes["perm"].value # noqa: RUF015
|
|
70
|
+
expected_perm = list(range(len(perm)))
|
|
71
|
+
expected_perm[-2], expected_perm[-1] = expected_perm[-1], expected_perm[-2]
|
|
72
|
+
return perm == expected_perm
|
|
73
|
+
|
|
74
|
+
@classmethod
|
|
75
|
+
def rewrite(cls, op, x, y):
|
|
76
|
+
node = list((x if cls._pos == 2 else y).uses())[0][0] # noqa: RUF015
|
|
77
|
+
kwargs = {}
|
|
78
|
+
for name in ["alpha", "transA", "transB", "transBatchA", "transBatchB"]:
|
|
79
|
+
att = node.attributes.get(name)
|
|
80
|
+
if att:
|
|
81
|
+
kwargs[name] = att.value
|
|
82
|
+
name = "transA" if cls._pos == 1 else "transB"
|
|
83
|
+
kwargs[name] = 1 - kwargs.get(name, 0)
|
|
84
|
+
return op.FusedMatMul(x, y, **kwargs, _domain="com.microsoft")
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
class TransposeMatMul1(_TransposeMatMulBase):
|
|
88
|
+
"""Replaces ``Transpose + (Fused)MatMul`` by FusedMatMul."""
|
|
89
|
+
|
|
90
|
+
@classmethod
|
|
91
|
+
def pattern(cls, op, x, y):
|
|
92
|
+
return op.MatMul(op.Transpose(x), y)
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
class TransposeFusedMatMul1(TransposeMatMul1):
|
|
96
|
+
"""Replaces ``Transpose + (Fused)MatMul`` by FusedMatMul."""
|
|
97
|
+
|
|
98
|
+
@classmethod
|
|
99
|
+
def pattern(cls, op, x, y):
|
|
100
|
+
return op.FusedMatMul(op.Transpose(x), y, _domain="com.microsoft")
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
class TransposeMatMul2(_TransposeMatMulBase):
|
|
104
|
+
"""Replaces ``Transpose + (Fused)MatMul`` by FusedMatMul."""
|
|
105
|
+
|
|
106
|
+
_pos: ClassVar = 2
|
|
107
|
+
|
|
108
|
+
@classmethod
|
|
109
|
+
def pattern(cls, op, x, y):
|
|
110
|
+
return op.MatMul(x, op.Transpose(y))
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
class TransposeFusedMatMul2(TransposeMatMul2):
|
|
114
|
+
"""Replaces ``Transpose + (Fused)MatMul`` by FusedMatMul."""
|
|
115
|
+
|
|
116
|
+
@classmethod
|
|
117
|
+
def pattern(cls, op, x, y):
|
|
118
|
+
return op.FusedMatMul(x, op.Transpose(y), _domain="com.microsoft")
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
class MatMulTranspose(orp.RewriteRuleAsClass):
|
|
122
|
+
"""Replaces ``MatMul + Transpose`` by FusedMatMul."""
|
|
123
|
+
|
|
124
|
+
@classmethod
|
|
125
|
+
def pattern(cls, op, x, y):
|
|
126
|
+
return op.Transpose(op.MatMul(x, y))
|
|
127
|
+
|
|
128
|
+
@classmethod
|
|
129
|
+
def check(cls, context, x, y) -> bool:
|
|
130
|
+
matmul = list(x.uses())[0][0] # noqa: RUF015
|
|
131
|
+
transpose = list(matmul.outputs[0].uses())[0][0] # noqa: RUF015
|
|
132
|
+
perm = transpose.attributes["perm"].value
|
|
133
|
+
expected_perm = list(range(len(perm)))
|
|
134
|
+
expected_perm[-2], expected_perm[-1] = expected_perm[-1], expected_perm[-2]
|
|
135
|
+
return perm == expected_perm
|
|
136
|
+
|
|
137
|
+
@classmethod
|
|
138
|
+
def rewrite(cls, op, x, y):
|
|
139
|
+
node = list(x.uses())[0][0] # noqa: RUF015
|
|
140
|
+
kwargs = {}
|
|
141
|
+
for name in ["alpha", "transA", "transB", "transBatchA", "transBatchB"]:
|
|
142
|
+
att = node.attributes.get(name)
|
|
143
|
+
if att:
|
|
144
|
+
kwargs[name] = att.value
|
|
145
|
+
for name in ["transA", "transB"]:
|
|
146
|
+
kwargs[name] = 1 - kwargs.get(name, 0)
|
|
147
|
+
return op.FusedMatMul(y, x, **kwargs, _domain="com.microsoft")
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
class FusedMatMulTranspose(MatMulTranspose):
|
|
151
|
+
"""Replaces ``MatMul + Transpose`` by FusedMatMul."""
|
|
152
|
+
|
|
153
|
+
@classmethod
|
|
154
|
+
def pattern(cls, op, x, y):
|
|
155
|
+
return op.Transpose(op.FusedMatMul(x, y, _domain="com.microsoft"))
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
def fused_matmul_rule_sets() -> orp.RewriteRuleSet:
|
|
159
|
+
"""Returns a set of rules introducting onnxruntime contrib obs.
|
|
160
|
+
This requires onnxruntime to run the model after
|
|
161
|
+
it is rewritten.
|
|
162
|
+
|
|
163
|
+
Returns:
|
|
164
|
+
RewriteRuleSet
|
|
165
|
+
"""
|
|
166
|
+
return orp.RewriteRuleSet(
|
|
167
|
+
[
|
|
168
|
+
orp.make_rewrite_rule_from_class(FusedMatMulDiv1, True),
|
|
169
|
+
orp.make_rewrite_rule_from_class(FusedMatMulDiv2, True),
|
|
170
|
+
orp.make_rewrite_rule_from_class(FusedMatMulTranspose, True),
|
|
171
|
+
orp.make_rewrite_rule_from_class(MatMulTranspose, True),
|
|
172
|
+
orp.make_rewrite_rule_from_class(TransposeMatMul1, True),
|
|
173
|
+
orp.make_rewrite_rule_from_class(TransposeFusedMatMul1, True),
|
|
174
|
+
orp.make_rewrite_rule_from_class(TransposeMatMul2, True),
|
|
175
|
+
orp.make_rewrite_rule_from_class(TransposeFusedMatMul2, True),
|
|
176
|
+
]
|
|
177
|
+
)
|