Test memory planning for torch.map operations.
(self)
| 1225 | ) |
| 1226 | |
| 1227 | def test_multi_map(self) -> None: |
| 1228 | """Test memory planning for torch.map operations.""" |
| 1229 | |
| 1230 | eager_module = MultiMapModel().eval() |
| 1231 | inputs = eager_module.get_random_inputs() |
| 1232 | |
| 1233 | # Export and convert to edge |
| 1234 | graph_module = ( |
| 1235 | to_edge(export(eager_module, inputs, strict=True)) |
| 1236 | .exported_program() |
| 1237 | .graph_module |
| 1238 | ) |
| 1239 | |
| 1240 | # Apply memory planning. |
| 1241 | mem_algo = MemoryPlanningAlgorithmSuite(algo_list=[naive]) |
| 1242 | graph_module = PassManager( |
| 1243 | passes=[ |
| 1244 | SpecPropPass(), |
| 1245 | ToOutVarPass(), |
| 1246 | ], |
| 1247 | )(graph_module).graph_module |
| 1248 | mem_planning_pass = MemoryPlanningPass( |
| 1249 | mem_algo, |
| 1250 | alloc_graph_input=True, |
| 1251 | alloc_graph_output=True, |
| 1252 | alloc_mutable_buffers=True, |
| 1253 | ) |
| 1254 | graph_module = mem_planning_pass.run(graph_module).graph_module |
| 1255 | |
| 1256 | # Verify memory planning results |
| 1257 | verifier = Verifier( |
| 1258 | graph_module, |
| 1259 | alloc_graph_input=True, |
| 1260 | alloc_graph_output=True, |
| 1261 | alloc_mutable_buffers=True, |
| 1262 | ) |
| 1263 | verifier.verify_graph_input_output() |
| 1264 | verifier.verify_storage_reuse(allow_lifetime_and_storage_overlap=False) |
| 1265 | |
| 1266 | # Check that bufsizes are [0, 320]: |
| 1267 | # 1. 48 (3 * 16 bytes) for map body, |
| 1268 | # 2. 64 * 4 (4 * 16 bytes) input0/map outputs, and |
| 1269 | # 3. 16 bytes for input1. |
| 1270 | self.assertEqual(graph_module.meta["non_const_buffer_sizes"], [0, 320]) |
| 1271 | for map_node in graph_module.graph.find_nodes( |
| 1272 | op="call_function", target=torch.ops.higher_order.map_impl |
| 1273 | ): |
| 1274 | map_fn_node = map_node.args[0] |
| 1275 | self.assertEqual(map_fn_node.op, "get_attr") |
| 1276 | map_fn = getattr(graph_module, map_fn_node.target) |
| 1277 | self.assertEqual(map_fn.meta["non_const_buffer_sizes"], [0, 48]) |
| 1278 | |
| 1279 | # Check there is no lifetime and storage overlap between nodes of the outer program and submodule of map. |
| 1280 | for map_node in graph_module.graph.find_nodes( |
| 1281 | op="call_function", target=torch.ops.higher_order.map_impl |
| 1282 | ): |
| 1283 | map_fn_node = map_node.args[0] |
| 1284 | self.assertEqual(map_fn_node.op, "get_attr") |
nothing calls this directly
no test coverage detected