Lower the model to executorch and get an ExecutorchProgram.
(
self,
passes: Optional[List[ExportPass]] = None,
external_constants_tag: Optional[
Callable[[torch.fx.Node], Optional[str]]
] = None,
share_mutable_buffers: bool = False,
)
| 475 | return self |
| 476 | |
| 477 | def to_executorch( |
| 478 | self, |
| 479 | passes: Optional[List[ExportPass]] = None, |
| 480 | external_constants_tag: Optional[ |
| 481 | Callable[[torch.fx.Node], Optional[str]] |
| 482 | ] = None, |
| 483 | share_mutable_buffers: bool = False, |
| 484 | ) -> "LLMEdgeManager": |
| 485 | """ |
| 486 | Lower the model to executorch and get an ExecutorchProgram. |
| 487 | """ |
| 488 | to_executorch_passes = [] |
| 489 | if passes: |
| 490 | # pyre-fixme[6]: In call `list.extend`, for 1st positional argument, |
| 491 | # expected `Iterable[Union[ConvertToLinearPass, QuantFusionPass]]` but |
| 492 | # got `List[ExportPass] |
| 493 | to_executorch_passes.extend(passes) |
| 494 | |
| 495 | assert self.edge_manager, "Need to run export_to_edge() first" |
| 496 | |
| 497 | # If there are Linear operations left in the graph, let's execute |
| 498 | # them with the optimized op_linear rather than materializing a |
| 499 | # transpose followed by a regular op_mm. |
| 500 | # TODO: ConvertToLinearPass is not a sound pass and must be called before |
| 501 | # const propagation. It requires fixing: |
| 502 | # https://github.com/pytorch/executorch/issues/10499 |
| 503 | self.edge_manager.transform([ConvertToLinearPass()]) |
| 504 | |
| 505 | self.export_program = self.edge_manager.to_executorch( |
| 506 | ExecutorchBackendConfig( |
| 507 | extract_delegate_segments=True, |
| 508 | # pyre-fixme[6]: In call `ExecutorchBackendConfig.__init__`, for |
| 509 | # argument `passes`, expected `List[typing.Callable[[GraphModule], |
| 510 | # Optional[PassResult]]]` but got `List[Union[ConvertToLinearPass, |
| 511 | # QuantFusionPass]]`. |
| 512 | passes=to_executorch_passes, |
| 513 | do_quant_fusion_and_const_prop=True, |
| 514 | memory_planning_pass=MemoryPlanningPass( |
| 515 | alloc_graph_input=False, |
| 516 | share_mutable_buffers=share_mutable_buffers, |
| 517 | ), |
| 518 | sym_shape_eval_pass=ConstraintBasedSymShapeEvalPass(), |
| 519 | external_constants=external_constants_tag, |
| 520 | ) |
| 521 | ) |
| 522 | logging.info( |
| 523 | "Required memory for activation in bytes: {}".format( |
| 524 | self.export_program._emitter_output.program.execution_plan[ |
| 525 | 0 |
| 526 | ].non_const_buffer_sizes |
| 527 | ), |
| 528 | ) |
| 529 | return self |
| 530 | |
| 531 | def save_to_pte(self, output_name: str) -> None: |
| 532 | """ |