Test memory planning for torch.map operations.
(self)
| 1165 | class TestMap(unittest.TestCase): |
| 1166 | |
| 1167 | def test_map(self) -> None: |
| 1168 | """Test memory planning for torch.map operations.""" |
| 1169 | |
| 1170 | eager_module = MapModel().eval() |
| 1171 | inputs = eager_module.get_random_inputs() |
| 1172 | |
| 1173 | # Export and convert to edge |
| 1174 | graph_module = ( |
| 1175 | to_edge(export(eager_module, inputs, strict=True)) |
| 1176 | .exported_program() |
| 1177 | .graph_module |
| 1178 | ) |
| 1179 | |
| 1180 | # Apply memory planning. |
| 1181 | mem_algo = MemoryPlanningAlgorithmSuite(algo_list=[naive]) |
| 1182 | graph_module = PassManager( |
| 1183 | passes=[ |
| 1184 | SpecPropPass(), |
| 1185 | ToOutVarPass(), |
| 1186 | ], |
| 1187 | )(graph_module).graph_module |
| 1188 | mem_planning_pass = MemoryPlanningPass( |
| 1189 | mem_algo, |
| 1190 | alloc_graph_input=True, |
| 1191 | alloc_graph_output=True, |
| 1192 | alloc_mutable_buffers=True, |
| 1193 | ) |
| 1194 | graph_module = mem_planning_pass.run(graph_module).graph_module |
| 1195 | |
| 1196 | # Verify memory planning results |
| 1197 | verifier = Verifier( |
| 1198 | graph_module, |
| 1199 | alloc_graph_input=True, |
| 1200 | alloc_graph_output=True, |
| 1201 | alloc_mutable_buffers=True, |
| 1202 | ) |
| 1203 | verifier.verify_graph_input_output() |
| 1204 | verifier.verify_storage_reuse(allow_lifetime_and_storage_overlap=False) |
| 1205 | |
| 1206 | map_nodes = graph_module.graph.find_nodes( |
| 1207 | op="call_function", target=torch.ops.higher_order.map_impl |
| 1208 | ) |
| 1209 | assert len(map_nodes) == 1 |
| 1210 | map_fn_node = map_nodes[0].args[0] |
| 1211 | self.assertEqual(map_fn_node.op, "get_attr") |
| 1212 | map_fn = getattr(graph_module, map_fn_node.target) |
| 1213 | |
| 1214 | map_lifetime = map_nodes[0].meta.get("spec", None)[0].lifetime[0] |
| 1215 | |
| 1216 | # Check that there is no storage overlap between nodes of the outer program and submodule of map. |
| 1217 | for outer_spec in _get_specs(graph_module): |
| 1218 | for inner_spec in _get_specs(map_fn): |
| 1219 | self.assertFalse( |
| 1220 | verifier.has_overlap( |
| 1221 | outer_spec.lifetime, [map_lifetime, map_lifetime] |
| 1222 | ) |
| 1223 | and (verifier.storage_overlap(outer_spec, inner_spec)), |
| 1224 | f"Outer spec {outer_spec.shape=} {outer_spec.dtype=} {outer_spec.lifetime=} and inner spec {inner_spec} have storage overlap", |
nothing calls this directly
no test coverage detected