forked from pytorch/executorch
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy path_serialize.py
More file actions
123 lines (108 loc) · 4.91 KB
/
_serialize.py
File metadata and controls
123 lines (108 loc) · 4.91 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
# Copyright (c) Meta Platforms, Inc. and affiliates.
# All rights reserved.
#
# This source code is licensed under the BSD-style license found in the
# LICENSE file in the root directory of this source tree.
# pyre-strict
from typing import Dict, Optional, Tuple
from executorch.exir._serialize._cord import Cord
from executorch.exir._serialize._named_data_store import (
NamedDataStore,
NamedDataStoreOutput,
)
from executorch.exir._serialize._program import PTEFile, serialize_pte_binary
from executorch.exir._serialize.data_serializer import DataPayload, DataSerializer
from executorch.exir.capture._config import ExecutorchBackendConfig
from executorch.exir.emit import EmitterOutput
from executorch.exir.schema import Program, Tensor, TensorDataLocation
from executorch.exir.tensor_layout import TensorLayout
def _extract_external_tensor_layouts(program: Program) -> Dict[str, TensorLayout]:
# Find all external tensors and organize into {fqn: TensorLayout}.
fqn_to_tensor_layout: Dict[str, TensorLayout] = {}
for plan in program.execution_plan:
for evalue in plan.values:
if isinstance(evalue.val, Tensor):
tensor = evalue.val
if (
tensor.extra_tensor_info is not None
and tensor.extra_tensor_info.fully_qualified_name is not None
and tensor.extra_tensor_info.location is TensorDataLocation.EXTERNAL
):
fqn_to_tensor_layout[
# pyre-ignore Undefined attribute [16]: `Optional` has no attribute `fully_qualified_name`
tensor.extra_tensor_info.fully_qualified_name
] = TensorLayout(tensor.scalar_type, tensor.sizes, tensor.dim_order)
return fqn_to_tensor_layout
def serialize_for_executorch(
emitter_output: EmitterOutput,
config: ExecutorchBackendConfig,
data_serializer: DataSerializer,
named_data_store: Optional[NamedDataStoreOutput] = None,
) -> Tuple[Cord, Dict[str, Cord]]:
"""Serialize the output from Emitter into ExecuTorch artifacts; PTE and PTD files."""
# Serialize PTE file.
pte_named_data = None
if (
named_data_store is not None
and len(named_data_store.buffers) > 0
and len(named_data_store.pte_data) > 0
):
# Create a separate NamedDataStoreOutput with only pte_data; exclude
# external_data, which shouldn't be serialized with the PTE file.
if len(named_data_store.external_data) == 0:
pte_named_data = named_data_store
else:
pte_named_data = NamedDataStoreOutput(
buffers=named_data_store.buffers,
pte_data=named_data_store.pte_data,
external_data={},
)
pte: Cord = serialize_pte_binary(
pte_file=PTEFile(
program=emitter_output.program,
mutable_data=emitter_output.mutable_data,
named_data=pte_named_data,
),
extract_delegate_segments=config.extract_delegate_segments,
segment_alignment=config.segment_alignment,
constant_tensor_alignment=config.constant_tensor_alignment,
delegate_alignment=config.delegate_alignment,
)
# Early exit if no external weights.
if len(emitter_output.external_constant_map) == 0 and (
named_data_store is None or len(named_data_store.external_data) == 0
):
return pte, {}
ptd_files: Dict[str, Cord] = {}
# If there are no emitter constants, use named_data_store directly.
if len(emitter_output.external_constant_map) == 0:
for tag in named_data_store.external_data.keys():
ptd_files[tag] = data_serializer.serialize(
DataPayload(
buffers=named_data_store.buffers,
named_data=named_data_store.external_data[tag],
)
)
return pte, ptd_files
# Collect external weights from emitter output and merge them.
fqn_to_tensor_layout = _extract_external_tensor_layouts(emitter_output.program)
updated_named_data_store = NamedDataStore()
# Add tensor constants from the emitter to the NamedDataStore.
for tag, fqn_to_index in emitter_output.external_constant_map.items():
for fqn, index in fqn_to_index.items():
updated_named_data_store.add_named_data(
fqn,
emitter_output.external_constant_buffer[index],
tensor_layout=fqn_to_tensor_layout[fqn],
external_tag=tag,
)
updated_named_data_store.merge_named_data_store(named_data_store)
# Serialize each tag into a PTD file.
for tag in updated_named_data_store.external_data.keys():
ptd_files[tag] = data_serializer.serialize(
DataPayload(
buffers=updated_named_data_store.buffers,
named_data=updated_named_data_store.external_data[tag],
)
)
return pte, ptd_files