Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add event tracing and ETDumps to executor_runner #5027

Open
wants to merge 22 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
b09d09e
Add event tracing and ETDumps to executor_runner
benkli01 Jun 27, 2024
cbcbbe7
Merge branch 'pytorch:main' into add-profiling-to-xnn-executor-runner-2
benkli01 Oct 1, 2024
4db02c9
Merge branch 'pytorch:main' into add-profiling-to-xnn-executor-runner-2
benkli01 Oct 8, 2024
bf27add
Merge branch 'pytorch:main' into add-profiling-to-xnn-executor-runner-2
benkli01 Oct 29, 2024
a2c254c
Merge branch 'pytorch:main' into add-profiling-to-xnn-executor-runner-2
benkli01 Nov 18, 2024
3f23fae
Merge branch 'pytorch:main' into add-profiling-to-xnn-executor-runner-2
benkli01 Nov 25, 2024
e692a76
Merge branch 'pytorch:main' into add-profiling-to-xnn-executor-runner-2
benkli01 Dec 4, 2024
1d9d0c0
Merge branch 'pytorch:main' into add-profiling-to-xnn-executor-runner-2
benkli01 Dec 9, 2024
f3493e4
Merge branch 'pytorch:main' into add-profiling-to-xnn-executor-runner-2
benkli01 Dec 27, 2024
1a9721f
Fix comments during code review
benkli01 Jan 10, 2025
da448ce
Merge branch 'pytorch:main' into add-profiling-to-xnn-executor-runner-2
benkli01 Jan 10, 2025
b36d5b4
Merge branch 'pytorch:main' into add-profiling-to-xnn-executor-runner-2
benkli01 Jan 15, 2025
fde5862
Small fix for use of flag `FLAGS_etdump`
benkli01 Jan 15, 2025
931ddf4
Another fix for case ET_EVENT_TRACER_ENABLED=OFF
benkli01 Jan 15, 2025
b080c76
Merge branch 'pytorch:main' into add-profiling-to-xnn-executor-runner-2
benkli01 Jan 15, 2025
88f0e91
Merge branch 'pytorch:main' into add-profiling-to-xnn-executor-runner-2
benkli01 Jan 16, 2025
42a8b9c
Revert use of FLATCCRT_LIB to flatccrt
benkli01 Jan 17, 2025
34b6b3e
Merge branch 'pytorch:main' into add-profiling-to-xnn-executor-runner-2
benkli01 Jan 17, 2025
07d1c26
Merge branch 'pytorch:main' into add-profiling-to-xnn-executor-runner-2
benkli01 Jan 20, 2025
c886ad2
Fix linker issue when building executor_runner
benkli01 Jan 24, 2025
d9f3269
Merge branch 'pytorch:main' into add-profiling-to-xnn-executor-runner-2
benkli01 Jan 27, 2025
662cb81
Merge branch 'pytorch:main' into add-profiling-to-xnn-executor-runner-2
benkli01 Jan 28, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# Copyright (c) Meta Platforms, Inc. and affiliates.
# Copyright 2024-2025 Arm Limited and/or its affiliates.
# All rights reserved.
#
# This source code is licensed under the BSD-style license found in the
Expand Down Expand Up @@ -820,6 +821,14 @@ if(EXECUTORCH_BUILD_EXECUTOR_RUNNER)
list(APPEND _executor_runner_libs quantized_ops_lib)
endif()

if(EXECUTORCH_ENABLE_EVENT_TRACER)
if(EXECUTORCH_BUILD_DEVTOOLS)
list(APPEND _executor_runner_libs etdump flatccrt)
else()
message(SEND_ERROR "Use of 'EXECUTORCH_ENABLE_EVENT_TRACER' requires 'EXECUTORCH_BUILD_DEVTOOLS' to be enabled.")
endif()
endif()

add_executable(executor_runner ${_executor_runner__srcs})
if(CMAKE_BUILD_TYPE STREQUAL "Release")
if(APPLE)
Expand Down
6 changes: 1 addition & 5 deletions backends/qualcomm/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# Copyright (c) Qualcomm Innovation Center, Inc.
# Copyright 2025 Arm Limited and/or its affiliates.
# All rights reserved
#
# This source code is licensed under the BSD-style license found in the
Expand Down Expand Up @@ -199,11 +200,6 @@ target_link_libraries(
#
target_link_options_shared_lib(qnn_executorch_backend)

#
# add compile option
#
target_compile_options(executorch PUBLIC -DET_EVENT_TRACER_ENABLED)

#
# add sources
#
Expand Down
12 changes: 11 additions & 1 deletion backends/xnnpack/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# Copyright (c) Meta Platforms, Inc. and affiliates.
# Copyright 2024-2025 Arm Limited and/or its affiliates.
# All rights reserved.
#
# This source code is licensed under the BSD-style license found in the
Expand Down Expand Up @@ -128,8 +129,17 @@ if(NOT CMAKE_TOOLCHAIN_FILE MATCHES ".*(iOS|ios\.toolchain)\.cmake$")
#
list(TRANSFORM _xnn_executor_runner__srcs PREPEND "${EXECUTORCH_ROOT}/")
add_executable(xnn_executor_runner ${_xnn_executor_runner__srcs})

if(EXECUTORCH_ENABLE_EVENT_TRACER)
if(EXECUTORCH_BUILD_DEVTOOLS)
list(APPEND xnn_executor_runner_libs etdump)
else()
message(SEND_ERROR "Use of 'EXECUTORCH_ENABLE_EVENT_TRACER' requires 'EXECUTORCH_BUILD_DEVTOOLS' to be enabled.")
endif()
endif()

target_link_libraries(
xnn_executor_runner xnnpack_backend gflags portable_ops_lib
xnn_executor_runner gflags portable_ops_lib ${xnn_executor_runner_libs}
)
target_compile_options(xnn_executor_runner PUBLIC ${_common_compile_options})
endif()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ Since weight packing creates an extra copy of the weights inside XNNPACK, We fre
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.

#### **Profiling**
We have enabled basic profiling for XNNPACK delegate that can be enabled with the following compiler flag `-DENABLE_XNNPACK_PROFILING`. With ExecuTorch's Developer Tools integration, you can also now use the Developer Tools to profile the model. You can follow the steps in [Using the ExecuTorch Developer Tools to Profile a Model](./tutorials/devtools-integration-tutorial) on how to profile ExecuTorch models and use Developer Tools' Inspector API to view XNNPACK's internal profiling information.
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 Developer Tools integration, you can also now use the Developer Tools to profile the model. You can follow the steps in [Using the ExecuTorch Developer Tools to Profile a Model](./tutorials/devtools-integration-tutorial) on how to profile ExecuTorch models and use Developer Tools' 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)).


[comment]: <> (TODO: Refactor quantizer to a more official quantization doc)
Expand Down
3 changes: 3 additions & 0 deletions docs/source/tutorial-xnnpack-delegate-lowering.md
Original file line number Diff line number Diff line change
Expand Up @@ -177,3 +177,6 @@ Now you should be able to find the executable built at `./cmake-out/backends/xnn

## Building and Linking with the XNNPACK Backend
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.

## Profiling
To enable profiling in the `xnn_executor_runner` pass the flags `-DEXECUTORCH_ENABLE_EVENT_TRACER=ON` and `-DEXECUTORCH_BUILD_DEVTOOLS=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).
93 changes: 83 additions & 10 deletions examples/portable/executor_runner/executor_runner.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
* Copyright 2024-2025 Arm Limited and/or its affiliates.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
Expand All @@ -25,10 +26,14 @@
#include <executorch/extension/data_loader/file_data_loader.h>
#include <executorch/extension/evalue_util/print_evalue.h>
#include <executorch/extension/runner_util/inputs.h>
#include <executorch/runtime/core/event_tracer.h>
#include <executorch/runtime/executor/method.h>
#include <executorch/runtime/executor/program.h>
#include <executorch/runtime/platform/log.h>
#include <executorch/runtime/platform/runtime.h>
#ifdef ET_EVENT_TRACER_ENABLED
#include <executorch/devtools/etdump/etdump_flatcc.h>
#endif // ET_EVENT_TRACER_ENABLED

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

Expand All @@ -38,10 +43,15 @@ DEFINE_string(
model_path,
"model.pte",
"Model serialized in flatbuffer format.");
DEFINE_uint32(num_executions, 1, "Number of times to run the model.");
#ifdef ET_EVENT_TRACER_ENABLED
DEFINE_string(etdump_path, "model.etdump", "Write ETDump data to this path.");
#endif // ET_EVENT_TRACER_ENABLED

using executorch::extension::FileDataLoader;
using executorch::runtime::Error;
using executorch::runtime::EValue;
using executorch::runtime::EventTracer;
using executorch::runtime::HierarchicalAllocator;
using executorch::runtime::MemoryAllocator;
using executorch::runtime::MemoryManager;
Expand All @@ -51,6 +61,56 @@ using executorch::runtime::Program;
using executorch::runtime::Result;
using executorch::runtime::Span;

/// Helper to manage resources for ETDump generation
class EventTraceManager {
public:
EventTraceManager() : event_tracer_ptr_(nullptr) {
#ifdef ET_EVENT_TRACER_ENABLED
event_tracer_ptr_ = std::make_shared<executorch::etdump::ETDumpGen>();
#endif // ET_EVENT_TRACER_ENABLED
}

EventTracer* get_event_tracer() const {
return event_tracer_ptr_.get();
};

Error write_etdump_to_file() const {
EventTracer* const event_tracer_ptr = get_event_tracer();
if (!event_tracer_ptr) {
return Error::NotSupported;
}

#ifdef ET_EVENT_TRACER_ENABLED
executorch::etdump::ETDumpGen* const etdump_ptr =
static_cast<executorch::etdump::ETDumpGen*>(event_tracer_ptr);

const char* filename = FLAGS_etdump_path.c_str();

std::unique_ptr<FILE, decltype(&fclose)> etdump_file(
fopen(filename, "w+"), fclose);
if (!etdump_file) {
ET_LOG(Error, "Failed to open ETDump file at %s.", filename);
return Error::AccessFailed;
}

executorch::etdump::ETDumpResult result = etdump_ptr->get_etdump_data();
if (result.buf != nullptr && result.size > 0) {
fwrite((uint8_t*)result.buf, 1, result.size, etdump_file.get());
free(result.buf);
ET_LOG(Info, "ETDump written to file '%s'.", filename);
} else {
ET_LOG(Error, "No ETDump data available!");
return Error::NotFound;
}
#endif // ET_EVENT_TRACER_ENABLED

return Error::Ok;
}

private:
std::shared_ptr<EventTracer> event_tracer_ptr_;
};

int main(int argc, char** argv) {
executorch::runtime::runtime_init();

Expand Down Expand Up @@ -158,8 +218,9 @@ int main(int argc, char** argv) {
// the method can mutate the memory-planned buffers, so the method should only
// be used by a single thread at at time, but it can be reused.
//

Result<Method> method = program->load_method(method_name, &memory_manager);
EventTraceManager tracer;
Result<Method> method = program->load_method(
method_name, &memory_manager, tracer.get_event_tracer());
ET_CHECK_MSG(
method.ok(),
"Loading of method %s failed with status 0x%" PRIx32,
Expand All @@ -178,24 +239,36 @@ int main(int argc, char** argv) {
ET_LOG(Info, "Inputs prepared.");

// Run the model.
Error status = method->execute();
ET_CHECK_MSG(
status == Error::Ok,
"Execution of method %s failed with status 0x%" PRIx32,
method_name,
(uint32_t)status);
ET_LOG(Info, "Model executed successfully.");
for (uint32_t i = 0; i < FLAGS_num_executions; i++) {
Error status = method->execute();
ET_CHECK_MSG(
status == Error::Ok,
"Execution of method %s failed with status 0x%" PRIx32,
method_name,
(uint32_t)status);
}
ET_LOG(
Info,
"Model executed successfully %" PRIu32 " time(s).",
FLAGS_num_executions);

// Print the outputs.
std::vector<EValue> outputs(method->outputs_size());
ET_LOG(Info, "%zu outputs: ", outputs.size());
status = method->get_outputs(outputs.data(), outputs.size());
Error status = method->get_outputs(outputs.data(), outputs.size());
ET_CHECK(status == Error::Ok);
// Print the first and last 100 elements of long lists of scalars.
std::cout << executorch::extension::evalue_edge_items(100);
for (int i = 0; i < outputs.size(); ++i) {
std::cout << "Output " << i << ": " << outputs[i] << std::endl;
}

if (tracer.get_event_tracer()) {
// Dump ETDump data containing profiling/debugging data to file specified in
// command line flag.
Error status = tracer.write_etdump_to_file();
ET_CHECK_MSG(status == Error::Ok, "Failed to save ETDump file.");
}

return 0;
}