|
11 | 11 | memory planning → emit → serialize via _program_to_flatbuffer. |
12 | 12 | """ |
13 | 13 |
|
| 14 | +import json |
14 | 15 | from functools import partial |
15 | | -from typing import final, List, Optional, Sequence, Tuple |
| 16 | +from typing import final, List, Tuple |
16 | 17 |
|
17 | 18 | import torch |
18 | 19 |
|
@@ -65,6 +66,8 @@ def _build_backend_inplace_ops() -> frozenset: |
65 | 66 |
|
66 | 67 |
|
67 | 68 | class _AnyOp(Verifier): |
| 69 | + # "TRAINING" is the only dialect that allows non-functional (mutating) ops. |
| 70 | + # After reinplace converts e.g. relu → relu_, the verifier must accept them. |
68 | 71 | dialect = "TRAINING" |
69 | 72 |
|
70 | 73 | def allowed_op_types(self): |
@@ -93,16 +96,17 @@ def _apply_passes(program: ExportedProgram, passes) -> ExportedProgram: |
93 | 96 |
|
94 | 97 | @final |
95 | 98 | class NativeBackend(BackendDetails): |
96 | | - # Set by NativePartitioner before preprocess is called. |
97 | | - _specialization_names: Optional[Sequence[str]] = None |
98 | | - |
99 | 99 | @classmethod |
100 | 100 | def preprocess( |
101 | 101 | cls, |
102 | 102 | program: ExportedProgram, |
103 | 103 | module_compile_spec: List[CompileSpec], |
104 | 104 | ) -> PreprocessResult: |
105 | | - names = cls._specialization_names |
| 105 | + names = None |
| 106 | + for spec in module_compile_spec: |
| 107 | + if spec.key == "native_specializations": |
| 108 | + names = json.loads(spec.value.decode("utf-8")) |
| 109 | + |
106 | 110 | if not names: |
107 | 111 | return cls._preprocess_native(program) |
108 | 112 |
|
@@ -140,22 +144,6 @@ def _preprocess_native( |
140 | 144 |
|
141 | 145 | program = _et_reinplace_pass(program, ops_to_inplace=BACKEND_INPLACE_OPS) |
142 | 146 |
|
143 | | - # reinplace may rename output nodes; fix the graph signature to match. |
144 | | - output_node = next( |
145 | | - n for n in program.graph_module.graph.nodes if n.op == "output" |
146 | | - ) |
147 | | - actual_names = [arg.name for arg in output_node.args[0] if hasattr(arg, "name")] |
148 | | - new_output_specs = [] |
149 | | - for spec, name in zip(program.graph_signature.output_specs, actual_names): |
150 | | - new_output_specs.append( |
151 | | - type(spec)( |
152 | | - kind=spec.kind, |
153 | | - arg=type(spec.arg)(name=name), |
154 | | - target=spec.target, |
155 | | - ) |
156 | | - ) |
157 | | - program._graph_signature.output_specs = new_output_specs |
158 | | - |
159 | 147 | # Re-run SpecPropPass: reinplace copies meta["val"] but not meta["spec"]. |
160 | 148 | program = _apply_passes(program, [SpecPropPass()]) |
161 | 149 |
|
@@ -212,6 +200,7 @@ def _preprocess_native( |
212 | 200 | algo_list=[greedy_memory_planning] |
213 | 201 | ) |
214 | 202 |
|
| 203 | + # Tells the emitter to use out-variant kernels for ops that support them. |
215 | 204 | program.graph_module.encounter_to_out_var_failure = True |
216 | 205 |
|
217 | 206 | program = _apply_passes( |
|
0 commit comments