Skip to content

Commit 43484a2

Browse files
committed
Update on "[executorch][runtime] Introduce PteDataMap for weight sharing"
PteDataMap is the NamedDataMap that will live in the runtime. It is used to give delegates access to opaque named data stored in the PTE file. Open to alternative naming suggestions, maybe 'PTEDataMap' or 'ProgramDataMap'? **Usage** The PteDataMap is owned by the program, and instantiated at program load time if named_data exists in the PTE file. We introduce usage of 'std::optional' here. I think we can also use executorch::aten::optional to avoid adding standard lib ? When initializing delegates, the PteDataMap is given to delegate_init. Delegates can retrieve opaque delegate data by key using 'get_data'. This gives them a FreeableBuffer that they can free later. **Testing** This test uses the C++ flatbuffer API to build a fake program containing named data. We also creates a temp file with sample data that the data loader can wrap around. TODO: e2e test once delegate aot is ready and we can generate a file with named data. **Note** As the PteDataMap wraps around flatbuffer constructs, the Program must outlive the PteDataMap. PteDataMap does not implement - get_metadata; currently, all data stored is opaque. Later, we can implement get_metadata if a backend stores plain tensor data. - load_into; this is mostly used for the training case, and isn't used by delegates, at least not at the moment Differential Revision: [D70213646](https://our.internmc.facebook.com/intern/diff/D70213646/) [ghstack-poisoned]
2 parents afb3839 + 0fd4e9b commit 43484a2

File tree

10 files changed

+174
-151
lines changed

10 files changed

+174
-151
lines changed

.github/workflows/android-perf.yml

Lines changed: 63 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -96,63 +96,6 @@ jobs:
9696
9797
PYTHONPATH="${PWD}" python .ci/scripts/gather_benchmark_configs.py $ARGS
9898
99-
prepare-test-specs:
100-
runs-on: linux.2xlarge
101-
needs: set-parameters
102-
strategy:
103-
matrix: ${{ fromJson(needs.set-parameters.outputs.benchmark_configs) }}
104-
fail-fast: false
105-
steps:
106-
- uses: actions/checkout@v3
107-
108-
- name: Prepare the spec
109-
id: prepare
110-
shell: bash
111-
env:
112-
BENCHMARK_CONFIG: ${{ toJSON(matrix) }}
113-
working-directory: extension/benchmark/android/benchmark
114-
run: |
115-
set -eux
116-
117-
# The model will be exported in the next step to this S3 path
118-
MODEL_PATH="https://gha-artifacts.s3.amazonaws.com/${{ github.repository }}/${{ github.run_id }}/artifacts/${{ matrix.model }}_${{ matrix.config }}/model.zip"
119-
# We could write a script to properly use jinja here, but there is only one variable,
120-
# so let's just sed it
121-
sed -i -e 's,{{ model_path }},'"${MODEL_PATH}"',g' android-llm-device-farm-test-spec.yml.j2
122-
123-
BENCHMARK_CONFIG_ID=$(echo "${{ matrix.model }}_${{ matrix.config }}" | sed -e 's/[^A-Za-z0-9._-]/_/g')
124-
# The config for this benchmark runs, we save it in the test spec so that it can be fetched
125-
# later by the upload script
126-
sed -i -e 's,{{ benchmark_config_id }},'"${BENCHMARK_CONFIG_ID}"',g' android-llm-device-farm-test-spec.yml.j2
127-
128-
cp android-llm-device-farm-test-spec.yml.j2 android-llm-device-farm-test-spec.yml
129-
# Just print the test spec for debugging
130-
cat android-llm-device-farm-test-spec.yml
131-
132-
# Save the benchmark configs so that we can use it later in the dashboard
133-
echo "${BENCHMARK_CONFIG}" > "${BENCHMARK_CONFIG_ID}.json"
134-
echo "benchmark-config-id=${BENCHMARK_CONFIG_ID}" >> $GITHUB_OUTPUT
135-
136-
- name: Upload the spec
137-
uses: seemethere/upload-artifact-s3@v5
138-
with:
139-
s3-bucket: gha-artifacts
140-
s3-prefix: |
141-
${{ github.repository }}/${{ github.run_id }}/artifacts/${{ matrix.model }}_${{ matrix.config }}
142-
retention-days: 1
143-
if-no-files-found: error
144-
path: extension/benchmark/android/benchmark/android-llm-device-farm-test-spec.yml
145-
146-
- name: Update the benchmark configs
147-
uses: seemethere/upload-artifact-s3@v5
148-
with:
149-
s3-bucket: gha-artifacts
150-
s3-prefix: |
151-
${{ github.repository }}/${{ github.run_id }}/artifacts/benchmark-configs/
152-
retention-days: 1
153-
if-no-files-found: error
154-
path: extension/benchmark/android/benchmark/${{ steps.prepare.outputs.benchmark-config-id }}.json
155-
15699
export-models:
157100
name: export-models
158101
uses: pytorch/test-infra/.github/workflows/linux_job_v2.yml@main
@@ -335,6 +278,69 @@ jobs:
335278
fi
336279
echo "::endgroup::"
337280
281+
prepare-test-specs:
282+
runs-on: linux.2xlarge
283+
needs:
284+
- set-parameters
285+
- export-models
286+
strategy:
287+
matrix: ${{ fromJson(needs.set-parameters.outputs.benchmark_configs) }}
288+
fail-fast: false
289+
steps:
290+
- uses: actions/checkout@v3
291+
292+
- name: Prepare the spec
293+
id: prepare
294+
shell: bash
295+
env:
296+
BENCHMARK_CONFIG: ${{ toJSON(matrix) }}
297+
working-directory: extension/benchmark/android/benchmark
298+
run: |
299+
set -eux
300+
301+
# The model will be exported in the next step to this S3 path
302+
MODEL_PATH="https://gha-artifacts.s3.amazonaws.com/${{ github.repository }}/${{ github.run_id }}/artifacts/${{ matrix.model }}_${{ matrix.config }}/model.zip"
303+
304+
# Check if the model artifact exists, fail this step skip generating test-spec.
305+
curl -s --head -f ${MODEL_PATH}
306+
307+
# We could write a script to properly use jinja here, but there is only one variable,
308+
# so let's just sed it
309+
sed -i -e 's,{{ model_path }},'"${MODEL_PATH}"',g' android-llm-device-farm-test-spec.yml.j2
310+
311+
BENCHMARK_CONFIG_ID=$(echo "${{ matrix.model }}_${{ matrix.config }}" | sed -e 's/[^A-Za-z0-9._-]/_/g')
312+
# The config for this benchmark runs, we save it in the test spec so that it can be fetched
313+
# later by the upload script
314+
sed -i -e 's,{{ benchmark_config_id }},'"${BENCHMARK_CONFIG_ID}"',g' android-llm-device-farm-test-spec.yml.j2
315+
316+
cp android-llm-device-farm-test-spec.yml.j2 android-llm-device-farm-test-spec.yml
317+
# Just print the test spec for debugging
318+
cat android-llm-device-farm-test-spec.yml
319+
320+
# Save the benchmark configs so that we can use it later in the dashboard
321+
echo "${BENCHMARK_CONFIG}" > "${BENCHMARK_CONFIG_ID}.json"
322+
echo "benchmark-config-id=${BENCHMARK_CONFIG_ID}" >> $GITHUB_OUTPUT
323+
324+
- name: Upload the spec
325+
uses: seemethere/upload-artifact-s3@v5
326+
with:
327+
s3-bucket: gha-artifacts
328+
s3-prefix: |
329+
${{ github.repository }}/${{ github.run_id }}/artifacts/${{ matrix.model }}_${{ matrix.config }}
330+
retention-days: 1
331+
if-no-files-found: error
332+
path: extension/benchmark/android/benchmark/android-llm-device-farm-test-spec.yml
333+
334+
- name: Update the benchmark configs
335+
uses: seemethere/upload-artifact-s3@v5
336+
with:
337+
s3-bucket: gha-artifacts
338+
s3-prefix: |
339+
${{ github.repository }}/${{ github.run_id }}/artifacts/benchmark-configs/
340+
retention-days: 1
341+
if-no-files-found: error
342+
path: extension/benchmark/android/benchmark/${{ steps.prepare.outputs.benchmark-config-id }}.json
343+
338344
build-benchmark-app:
339345
name: build-benchmark-app
340346
uses: pytorch/test-infra/.github/workflows/linux_job_v2.yml@main

.github/workflows/apple-perf.yml

Lines changed: 62 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -98,63 +98,6 @@ jobs:
9898
9999
echo "benchmark_configs is: ${{ steps.set-parameters.outputs.benchmark_configs }}"
100100
101-
prepare-test-specs:
102-
runs-on: linux.2xlarge
103-
needs: set-parameters
104-
strategy:
105-
matrix: ${{ fromJson(needs.set-parameters.outputs.benchmark_configs) }}
106-
fail-fast: false
107-
steps:
108-
- uses: actions/checkout@v3
109-
110-
- name: Prepare the spec
111-
id: prepare
112-
shell: bash
113-
env:
114-
BENCHMARK_CONFIG: ${{ toJSON(matrix) }}
115-
working-directory: extension/benchmark/apple/Benchmark
116-
run: |
117-
set -eux
118-
119-
# The model will be exported in the next step to this S3 path
120-
MODEL_PATH="https://gha-artifacts.s3.amazonaws.com/${{ github.repository }}/${{ github.run_id }}/artifacts/${{ matrix.model }}_${{ matrix.config }}/model.zip"
121-
# We could write a script to properly use jinja here, but there is only one variable,
122-
# so let's just sed it
123-
sed -i -e 's,{{ model_path }},'"${MODEL_PATH}"',g' default-ios-device-farm-appium-test-spec.yml.j2
124-
125-
BENCHMARK_CONFIG_ID=$(echo "${{ matrix.model }}_${{ matrix.config }}" | sed -e 's/[^A-Za-z0-9._-]/_/g')
126-
# The config for this benchmark runs, we save it in the test spec so that it can be fetched
127-
# later by the upload script
128-
sed -i -e 's,{{ benchmark_config_id }},'"${BENCHMARK_CONFIG_ID}"',g' default-ios-device-farm-appium-test-spec.yml.j2
129-
130-
cp default-ios-device-farm-appium-test-spec.yml.j2 default-ios-device-farm-appium-test-spec.yml
131-
# Just print the test spec for debugging
132-
cat default-ios-device-farm-appium-test-spec.yml
133-
134-
# Save the benchmark configs so that we can use it later in the dashboard
135-
echo "${BENCHMARK_CONFIG}" > "${BENCHMARK_CONFIG_ID}.json"
136-
echo "benchmark-config-id=${BENCHMARK_CONFIG_ID}" >> $GITHUB_OUTPUT
137-
138-
- name: Upload the spec
139-
uses: seemethere/upload-artifact-s3@v5
140-
with:
141-
s3-bucket: gha-artifacts
142-
s3-prefix: |
143-
${{ github.repository }}/${{ github.run_id }}/artifacts/${{ matrix.model }}_${{ matrix.config }}
144-
retention-days: 1
145-
if-no-files-found: error
146-
path: extension/benchmark/apple/Benchmark/default-ios-device-farm-appium-test-spec.yml
147-
148-
- name: Update the benchmark configs
149-
uses: seemethere/upload-artifact-s3@v5
150-
with:
151-
s3-bucket: gha-artifacts
152-
s3-prefix: |
153-
${{ github.repository }}/${{ github.run_id }}/artifacts/benchmark-configs/
154-
retention-days: 1
155-
if-no-files-found: error
156-
path: extension/benchmark/apple/Benchmark/${{ steps.prepare.outputs.benchmark-config-id }}.json
157-
158101
export-models:
159102
name: export-models
160103
uses: pytorch/test-infra/.github/workflows/macos_job.yml@main
@@ -344,6 +287,68 @@ jobs:
344287
fi
345288
echo "::endgroup::"
346289
290+
prepare-test-specs:
291+
runs-on: linux.2xlarge
292+
needs:
293+
- set-parameters
294+
- export-models
295+
strategy:
296+
matrix: ${{ fromJson(needs.set-parameters.outputs.benchmark_configs) }}
297+
fail-fast: false
298+
steps:
299+
- uses: actions/checkout@v3
300+
301+
- name: Prepare the spec
302+
id: prepare
303+
shell: bash
304+
env:
305+
BENCHMARK_CONFIG: ${{ toJSON(matrix) }}
306+
working-directory: extension/benchmark/apple/Benchmark
307+
run: |
308+
set -eux
309+
310+
# The model will be exported in the next step to this S3 path
311+
MODEL_PATH="https://gha-artifacts.s3.amazonaws.com/${{ github.repository }}/${{ github.run_id }}/artifacts/${{ matrix.model }}_${{ matrix.config }}/model.zip"
312+
# Check if the model artifact exists, fail this step skip generating test-spec.
313+
curl -s --head -f ${MODEL_PATH}
314+
# We could write a script to properly use jinja here, but there is only one variable,
315+
# so let's just sed it
316+
sed -i -e 's,{{ model_path }},'"${MODEL_PATH}"',g' default-ios-device-farm-appium-test-spec.yml.j2
317+
318+
BENCHMARK_CONFIG_ID=$(echo "${{ matrix.model }}_${{ matrix.config }}" | sed -e 's/[^A-Za-z0-9._-]/_/g')
319+
# The config for this benchmark runs, we save it in the test spec so that it can be fetched
320+
# later by the upload script
321+
sed -i -e 's,{{ benchmark_config_id }},'"${BENCHMARK_CONFIG_ID}"',g' default-ios-device-farm-appium-test-spec.yml.j2
322+
323+
cp default-ios-device-farm-appium-test-spec.yml.j2 default-ios-device-farm-appium-test-spec.yml
324+
# Just print the test spec for debugging
325+
cat default-ios-device-farm-appium-test-spec.yml
326+
327+
# Save the benchmark configs so that we can use it later in the dashboard
328+
echo "${BENCHMARK_CONFIG}" > "${BENCHMARK_CONFIG_ID}.json"
329+
echo "benchmark-config-id=${BENCHMARK_CONFIG_ID}" >> $GITHUB_OUTPUT
330+
331+
- name: Upload the spec
332+
uses: seemethere/upload-artifact-s3@v5
333+
with:
334+
s3-bucket: gha-artifacts
335+
s3-prefix: |
336+
${{ github.repository }}/${{ github.run_id }}/artifacts/${{ matrix.model }}_${{ matrix.config }}
337+
retention-days: 1
338+
if-no-files-found: error
339+
path: extension/benchmark/apple/Benchmark/default-ios-device-farm-appium-test-spec.yml
340+
341+
- name: Update the benchmark configs
342+
uses: seemethere/upload-artifact-s3@v5
343+
with:
344+
s3-bucket: gha-artifacts
345+
s3-prefix: |
346+
${{ github.repository }}/${{ github.run_id }}/artifacts/benchmark-configs/
347+
retention-days: 1
348+
if-no-files-found: error
349+
path: extension/benchmark/apple/Benchmark/${{ steps.prepare.outputs.benchmark-config-id }}.json
350+
351+
347352
build-benchmark-app:
348353
name: build-benchmark-app
349354
uses: pytorch/test-infra/.github/workflows/macos_job.yml@main

devtools/etdump/etdump_flatcc.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -503,7 +503,7 @@ void ETDumpGen::set_debug_buffer(Span<uint8_t> buffer) {
503503
Result<BufferDataSink> bds_ret = BufferDataSink::create(buffer);
504504
ET_CHECK_MSG(
505505
bds_ret.ok(),
506-
"Failed to write tensor with error 0x%" PRIx32,
506+
"Failed to create data sink from debug buffer with error 0x%" PRIx32,
507507
static_cast<uint32_t>(bds_ret.error()));
508508

509509
buffer_data_sink_ = std::move(bds_ret.get());

examples/qualcomm/oss_scripts/llama/model/static_llama.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -461,7 +461,7 @@ def get_metadata(self):
461461
"get_bos_id": 1,
462462
"get_eos_id": 2,
463463
"get_dim": self.dim,
464-
"get_head_dim": self.dim // self.n_heads,
464+
"get_head_dim": self.head_dim,
465465
"get_max_batch_size": self.max_batch_size,
466466
"get_max_seq_len": self.max_seq_len,
467467
"get_n_bos": 1,

exir/program/_program.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -978,6 +978,18 @@ def _remove_invalid_ops_for_not_decompose(
978978
) -> List[torch._ops.OpOverload]:
979979
# To address https://github.com/pytorch/executorch/issues/8781
980980
def keep(op):
981+
# Explicit allow list
982+
allow_list = []
983+
try:
984+
# Ops in torch.ops.quant are not always loaded, so we use try/except
985+
# Aliases output, but we need to allow it for XNNPACK
986+
allow_list.append(torch.ops.quant.choose_qparams_affine.default)
987+
except:
988+
pass
989+
990+
if op in allow_list:
991+
return True
992+
981993
schema = op._schema
982994
native_schema = _pybind_schema_to_native_schema(schema)
983995
if native_schema.is_mutable:

extension/llm/export/builder.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -448,6 +448,8 @@ def to_edge_transform_and_lower(
448448
compile_config=edge_config,
449449
constant_methods=self.metadata,
450450
)
451+
if self.verbose:
452+
logging.info(f"Exported graph:\n{self.edge_manager.exported_program()}")
451453
return self
452454

453455
def to_executorch(

runtime/executor/program.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -269,14 +269,14 @@ class Program final {
269269
FreeableBuffer&& program_data,
270270
const executorch_flatbuffer::Program* internal_program,
271271
FreeableBuffer&& constant_segment_data,
272-
std::optional<internal::PteDataMap>&& core_data_map)
272+
std::optional<internal::PteDataMap>&& pte_data_map)
273273
: program_data_(std::move(program_data)),
274274
// Don't need the loader if there are no segments.
275275
loader_(segment_base_offset > 0 ? loader : nullptr),
276276
internal_program_(internal_program),
277277
segment_base_offset_(segment_base_offset),
278278
constant_segment_data_(std::move(constant_segment_data)),
279-
core_data_map_(std::move(core_data_map)) {}
279+
pte_data_map_(std::move(pte_data_map)) {}
280280

281281
// Not copyable or assignable.
282282
Program(const Program& rhs) = delete;
@@ -301,7 +301,7 @@ class Program final {
301301
FreeableBuffer constant_segment_data_;
302302

303303
/// NamedDataMap holding named data from the program.
304-
std::optional<internal::PteDataMap> core_data_map_;
304+
std::optional<internal::PteDataMap> pte_data_map_;
305305
};
306306

307307
} // namespace runtime

runtime/executor/pte_data_map.cpp

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,8 @@ namespace internal {
1616
/* static */ executorch::runtime::Result<PteDataMap> PteDataMap::create(
1717
executorch::runtime::DataLoader* loader,
1818
size_t segment_base_offset,
19-
const flatbuffers::Vector<
20-
flatbuffers::Offset<executorch_flatbuffer::NamedData>,
21-
uint32_t>* named_data,
22-
const flatbuffers::Vector<
23-
flatbuffers::Offset<executorch_flatbuffer::DataSegment>,
24-
uint32_t>* segments) {
19+
const flatbuffers::FlatbufferNamedData* named_data,
20+
const flatbuffers::FlatbufferDataSegment* segments) {
2521
ET_CHECK_OR_RETURN_ERROR(
2622
loader != nullptr && named_data != nullptr && segments != nullptr,
2723
InvalidArgument,

0 commit comments

Comments
 (0)