(self)
| 95 | self.assertTrue(torch.allclose(out_remove_v6, out_no_remove_v6)) |
| 96 | |
| 97 | def test_spec(self) -> None: |
| 98 | model = TestModel1() |
| 99 | model.eval() |
| 100 | example_inputs = model.get_example_inputs() |
| 101 | ep = torch.export.export(model, example_inputs, strict=True) |
| 102 | |
| 103 | etpm = to_edge(ep).to_executorch( |
| 104 | config=ExecutorchBackendConfig( |
| 105 | remove_view_copy=True, |
| 106 | memory_planning_pass=MemoryPlanningPass(alloc_graph_input=False), |
| 107 | ), |
| 108 | ) |
| 109 | |
| 110 | # etpm.exported_program().graph.print_tabular() |
| 111 | |
| 112 | # idx opcode name target args kwargs |
| 113 | # --- ------------- ------------------------ ---------------------------------- -------------------------------------------------- ---------------- |
| 114 | # 0 placeholder p_parameter p_parameter () {} |
| 115 | # 1 placeholder p_parameter2 p_parameter2 () {} |
| 116 | # 2 placeholder x x () {} |
| 117 | # 3 call_function aten_view_copy_default <function view at 0x7fe57bea6d40> (p_parameter, [6, 5]) {} |
| 118 | # 4 call_function aten_view_copy_default_1 <function view at 0x7fe57bea6d40> (x, [6, 5]) {} |
| 119 | # 5 call_function alloc <function alloc at 0x7fe57bea6c20> (((6, 5), torch.float32),) {} |
| 120 | # 6 call_function aten_mul_tensor aten.mul.out (aten_view_copy_default, aten_view_copy_default_1) {'out': alloc} |
| 121 | # 7 call_function aten_view_copy_default_2 <function view at 0x7fe57bea6d40> (aten_mul_tensor, [30]) {} |
| 122 | # 8 call_function alloc_1 <function alloc at 0x7fe57bea6c20> (((30,), torch.float32),) {} |
| 123 | # 9 call_function aten_mul_tensor_1 aten.mul.out (aten_view_copy_default_2, p_parameter2) {'out': alloc_1} |
| 124 | # 10 call_function alloc_2 <function alloc at 0x7fe57bea6c20> (((6, 5), torch.float32),) {} |
| 125 | # 11 call_function aten_view_copy_default_3 aten.view_copy.out (aten_mul_tensor_1, [6, 5]) {'out': alloc_2} |
| 126 | # 12 output output_1 output ((aten_view_copy_default_3,),) {} |
| 127 | |
| 128 | for node in etpm.exported_program().graph.nodes: |
| 129 | if node.name == "p_parameter": |
| 130 | # p_parameter's lifetime is extended through aten_view_copy_default (memory.view) to idx 6 |
| 131 | self.assertEqual(node.meta["spec"].lifetime, [0, 6]) |
| 132 | elif node.name == "aten_view_copy_default": |
| 133 | # aten_view_copy_default is a memory.view of p_parameter. |
| 134 | # p_parameter is a constant with storage, so we check that the view's storage matches the base |
| 135 | |
| 136 | # assert base is p_parameter |
| 137 | self.assertEqual(node.args[0].name, "p_parameter") |
| 138 | |
| 139 | # assert base is const with storage |
| 140 | self.assertTrue(node.args[0].meta["spec"].const) |
| 141 | self.assertTrue(node.args[0].meta["spec"].storage is not None) |
| 142 | self.assertTrue(node.args[0].meta["spec"].mem_id is None) |
| 143 | self.assertTrue(node.args[0].meta["spec"].mem_offset is None) |
| 144 | |
| 145 | # assert self is const with storage |
| 146 | self.assertTrue(node.meta["spec"].const) |
| 147 | self.assertTrue(node.meta["spec"].storage is not None) |
| 148 | self.assertTrue(node.meta["spec"].mem_id is None) |
| 149 | self.assertTrue(node.meta["spec"].mem_offset is None) |
| 150 | |
| 151 | # assert storage matches |
| 152 | self.assertEqual( |
| 153 | node.meta["spec"].storage, node.args[0].meta["spec"].storage |
| 154 | ) |
nothing calls this directly
no test coverage detected