Skip to content

Commit 35da5bf

Browse files
authored
Add event tracing and ETDumps to executor_runner
Differential Revision: D61211201 Pull Request resolved: #4502
1 parent 48b4304 commit 35da5bf

File tree

5 files changed

+64
-12
lines changed

5 files changed

+64
-12
lines changed

CMakeLists.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
# Copyright (c) Meta Platforms, Inc. and affiliates.
2+
# Copyright 2024 Arm Limited and/or its affiliates.
23
# All rights reserved.
34
#
45
# This source code is licensed under the BSD-style license found in the
@@ -588,6 +589,10 @@ if(EXECUTORCH_BUILD_EXECUTOR_RUNNER)
588589
list(APPEND _executor_runner_libs portable_ops_lib)
589590
endif()
590591

592+
if(EXECUTORCH_ENABLE_EVENT_TRACER)
593+
list(APPEND _executor_runner_libs etdump flatccrt)
594+
endif()
595+
591596
# Generate lib to register quantized ops
592597
if(EXECUTORCH_BUILD_KERNELS_QUANTIZED)
593598
list(APPEND _executor_runner_libs quantized_ops_lib)

backends/xnnpack/CMakeLists.txt

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
# Copyright (c) Meta Platforms, Inc. and affiliates.
2+
# Copyright 2024 Arm Limited and/or its affiliates.
23
# All rights reserved.
34
#
45
# This source code is licensed under the BSD-style license found in the
@@ -120,8 +121,13 @@ if(NOT CMAKE_TOOLCHAIN_FILE MATCHES ".*(iOS|ios\.toolchain)\.cmake$")
120121
#
121122
list(TRANSFORM _xnn_executor_runner__srcs PREPEND "${EXECUTORCH_ROOT}/")
122123
add_executable(xnn_executor_runner ${_xnn_executor_runner__srcs})
124+
125+
if(EXECUTORCH_ENABLE_EVENT_TRACER)
126+
list(APPEND xnn_executor_runner_libs etdump)
127+
endif()
128+
123129
target_link_libraries(
124-
xnn_executor_runner xnnpack_backend gflags portable_ops_lib
130+
xnn_executor_runner gflags portable_ops_lib ${xnn_executor_runner_libs}
125131
)
126132
target_compile_options(xnn_executor_runner PUBLIC ${_common_compile_options})
127133
endif()

docs/source/native-delegates-executorch-xnnpack-delegate.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ Since weight packing creates an extra copy of the weights inside XNNPACK, We fre
7474
When executing the XNNPACK subgraphs, we prepare the tensor inputs and outputs and feed them to the XNNPACK runtime graph. After executing the runtime graph, the output pointers are filled with the computed tensors.
7575

7676
#### **Profiling**
77-
We have enabled basic profiling for XNNPACK delegate that can be enabled with the following compiler flag `-DENABLE_XNNPACK_PROFILING`. With ExecuTorch's SDK integration, you can also now use the SDK tools to profile the model. You can follow the steps in [Using the ExecuTorch SDK to Profile a Model](./tutorials/sdk-integration-tutorial) on how to profile ExecuTorch models and use SDK's Inspector API to view XNNPACK's internal profiling information.
77+
We have enabled basic profiling for the XNNPACK delegate that can be enabled with the compiler flag `-DEXECUTORCH_ENABLE_EVENT_TRACER` (add `-DENABLE_XNNPACK_PROFILING` for additional details). With ExecuTorch's SDK integration, you can also now use the SDK tools to profile the model. You can follow the steps in [Using the ExecuTorch SDK to Profile a Model](./tutorials/sdk-integration-tutorial) on how to profile ExecuTorch models and use SDK's Inspector API to view XNNPACK's internal profiling information. An example implementation is available in the `xnn_executor_runner` (see [tutorial here](tutorial-xnnpack-delegate-lowering.md#profiling)).
7878

7979

8080
[comment]: <> (TODO: Refactor quantizer to a more official quantization doc)

docs/source/tutorial-xnnpack-delegate-lowering.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,3 +171,6 @@ Now you should be able to find the executable built at `./cmake-out/backends/xnn
171171

172172
## Building and Linking with the XNNPACK Backend
173173
You can build the XNNPACK backend [CMake target](https://github.com/pytorch/executorch/blob/main/backends/xnnpack/CMakeLists.txt#L83), and link it with your application binary such as an Android or iOS application. For more information on this you may take a look at this [resource](demo-apps-android.md) next.
174+
175+
## Profiling
176+
To enable profiling in the `xnn_executor_runner` pass the flags `-DEXECUTORCH_ENABLE_EVENT_TRACER=ON` and `-DEXECUTORCH_BUILD_SDK=ON` to the build command (add `-DENABLE_XNNPACK_PROFILING=ON` for additional details). This will enable ETDump generation when running the inference and enables command line flags for profiling (see `xnn_executor_runner --help` for details).

examples/portable/executor_runner/executor_runner.cpp

Lines changed: 48 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
/*
22
* Copyright (c) Meta Platforms, Inc. and affiliates.
3+
* Copyright 2024 Arm Limited and/or its affiliates.
34
* All rights reserved.
45
*
56
* This source code is licensed under the BSD-style license found in the
@@ -29,13 +30,23 @@
2930
#include <executorch/runtime/executor/program.h>
3031
#include <executorch/runtime/platform/log.h>
3132
#include <executorch/runtime/platform/runtime.h>
33+
#ifdef ET_EVENT_TRACER_ENABLED
34+
#include <executorch/sdk/etdump/etdump_flatcc.h>
35+
#endif // ET_EVENT_TRACER_ENABLED
3236

3337
static uint8_t method_allocator_pool[4 * 1024U * 1024U]; // 4 MB
3438

3539
DEFINE_string(
3640
model_path,
3741
"model.pte",
3842
"Model serialized in flatbuffer format.");
43+
DEFINE_uint32(num_executions, 1, "Number of times to run the model.");
44+
#ifdef ET_EVENT_TRACER_ENABLED
45+
DEFINE_string(
46+
etdump_path,
47+
"model.etdump",
48+
"If ETDump generation is enabled an ETDump will be written out to this path.");
49+
#endif // ET_EVENT_TRACER_ENABLED
3950

4051
using namespace torch::executor;
4152
using torch::executor::util::FileDataLoader;
@@ -142,8 +153,20 @@ int main(int argc, char** argv) {
142153
// the method can mutate the memory-planned buffers, so the method should only
143154
// be used by a single thread at at time, but it can be reused.
144155
//
145-
146-
Result<Method> method = program->load_method(method_name, &memory_manager);
156+
EventTracer* event_tracer_ptr = nullptr;
157+
#ifdef ET_EVENT_TRACER_ENABLED
158+
std::unique_ptr<FILE, decltype(&fclose)> etdump_file(
159+
fopen(FLAGS_etdump_path.c_str(), "w+"), fclose);
160+
ET_CHECK_MSG(
161+
etdump_file,
162+
"Failed to open ETDump file at %s.",
163+
FLAGS_etdump_path.c_str());
164+
165+
torch::executor::ETDumpGen etdump_gen = torch::executor::ETDumpGen();
166+
event_tracer_ptr = &etdump_gen;
167+
#endif // ET_EVENT_TRACER_ENABLED
168+
Result<Method> method =
169+
program->load_method(method_name, &memory_manager, event_tracer_ptr);
147170
ET_CHECK_MSG(
148171
method.ok(),
149172
"Loading of method %s failed with status 0x%" PRIx32,
@@ -162,24 +185,39 @@ int main(int argc, char** argv) {
162185
ET_LOG(Info, "Inputs prepared.");
163186

164187
// Run the model.
165-
Error status = method->execute();
166-
ET_CHECK_MSG(
167-
status == Error::Ok,
168-
"Execution of method %s failed with status 0x%" PRIx32,
169-
method_name,
170-
(uint32_t)status);
171-
ET_LOG(Info, "Model executed successfully.");
188+
for (uint32_t i = 0; i < FLAGS_num_executions; i++) {
189+
Error status = method->execute();
190+
ET_CHECK_MSG(
191+
status == Error::Ok,
192+
"Execution of method %s failed with status 0x%" PRIx32,
193+
method_name,
194+
(uint32_t)status);
195+
}
196+
ET_LOG(Info, "Model executed successfully %i time(s).", FLAGS_num_executions);
172197

173198
// Print the outputs.
174199
std::vector<EValue> outputs(method->outputs_size());
175200
ET_LOG(Info, "%zu outputs: ", outputs.size());
176-
status = method->get_outputs(outputs.data(), outputs.size());
201+
Error status = method->get_outputs(outputs.data(), outputs.size());
177202
ET_CHECK(status == Error::Ok);
178203
// Print the first and last 100 elements of long lists of scalars.
179204
std::cout << torch::executor::util::evalue_edge_items(100);
180205
for (int i = 0; i < outputs.size(); ++i) {
181206
std::cout << "Output " << i << ": " << outputs[i] << std::endl;
182207
}
183208

209+
#ifdef ET_EVENT_TRACER_ENABLED
210+
// Dump the ETDump data containing profiling/debugging data to the specified
211+
// file.
212+
etdump_result result = etdump_gen.get_etdump_data();
213+
if (result.buf != nullptr && result.size > 0) {
214+
fwrite((uint8_t*)result.buf, 1, result.size, etdump_file.get());
215+
free(result.buf);
216+
ET_LOG(Info, "ETDump written to file '%s'.", FLAGS_etdump_path.c_str());
217+
} else {
218+
ET_LOG(Error, "No ETDump data available!");
219+
}
220+
#endif // ET_EVENT_TRACER_ENABLED
221+
184222
return 0;
185223
}

0 commit comments

Comments
 (0)