Skip to content

Commit 6779d15

Browse files
authored
Update selective build example + CI for top-level targets (#13741)
### Summary Update the selective build example and CI to use the new top-level targets, where appropriate. I've positioned the example as showcasing two flows - a standard way, using top-level targets, and appropriate for most use cases, and an advanced flow where the user creates a custom kernel target. This is mainly useful when integrating custom ops, which we can't easily integrate with top-level targets due to the inverted dependency on the user build. I've updated the CMake to take an additional arg to specify whether or not to define a custom target and refactored to use the standard top-level target when not. I've also unified the CMake option naming with the top-level target. Finally, I've updated the CI job to cover both flows. For additional context, I'd like to take a larger look at simplifying the selective build flows and CMake APIs. This will likely happen after 1.0, as it will be a larger effort. Tracking task: #12948. ### Test plan Changes are covered by the test selective build job.
1 parent c97c2c1 commit 6779d15

File tree

4 files changed

+233
-82
lines changed

4 files changed

+233
-82
lines changed

examples/selective_build/README.md

Lines changed: 128 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,137 @@
11
# Selective Build Examples
2-
To optimize binary size of ExecuTorch runtime, selective build can be used. This folder contains examples to select only the operators needed for ExecuTorch build. This example will demonstrate the CMake build.
2+
To optimize binary size of ExecuTorch runtime, selective build can be used. This folder contains examples to select only the operators needed for ExecuTorch build.
33

4-
## How to run
4+
These examples showcase two flows - the simple way, using CMake options to configure the framework build, and an advanced flow - showcasing user-defined kernel targets including custom operators.
55

66
Prerequisite: finish the [setting up wiki](https://pytorch.org/executorch/main/getting-started-setup).
77

8-
Run:
8+
## Example 1 - Basic Flow
99

10-
```bash
11-
cd executorch
12-
bash examples/selective_build/test_selective_build.sh cmake
10+
This example showcases using CMake options to control which operators are included. This approach should be preferred when not using
11+
custom operators or additional kernel libraries beyond the standard kernels provided by ExecuTorch.
12+
13+
The code under the basic/ directory builds a minimal model runner binary which links to a selective kernel target. To build the
14+
example with operators needed for the MobileNetV2 model, run the following commands:
15+
```
16+
# From the executorch directory
17+
python -m examples.portable.scripts.export --model_name="mv2" # Create a PTE file for MobileNetV2
18+
cd examples/selective_build/basic
19+
mkdir cmake-out && cd cmake-out
20+
cmake .. -DEXECUTORCH_SELECT_OPS_MODEL="../../mv2.pte" # Build with kernels needed for mv2.pte
21+
cmake --build . -j8
22+
./selective_build_test --model_path="../../mv2.pte" # Run the model with the selective kernel library
23+
```
24+
25+
### CMake Options
26+
27+
The example commands above show use of the EXECUTORCH_SELECT_OPS_MODEL option to select operators used in a PTE file, but there are
28+
several ways to provide the operator list. The options can be passed to CMake in the same way (during configuration) and are mutually
29+
exclusive, meaning that only one of these options should be chosen.
30+
31+
* `EXECUTORCH_SELECT_OPS_MODEL`: Select operators used in a .PTE file. Takes a path to the file.
32+
* `EXECUTORCH_SELECT_OPS_YAML`: Provide a list of operators from a .yml file, typically generated with the `codegen/tools/gen_oplist.py` script. See this script for usage information.
33+
* `EXECUTORCH_SELECT_OPS_LIST`: Provide a comma-separated list of operators to include. An example is included below.
34+
35+
Example operator list specification (passed as a CLI arg to the CMake configure command):
36+
```
37+
-DEXECUTORCH_SELECT_OPS_LIST="aten::convolution.out,\
38+
aten::_native_batch_norm_legit_no_training.out,aten::hardtanh.out,aten::add.out,\
39+
aten::mean.out,aten::view_copy.out,aten::permute_copy.out,aten::addmm.out,\
40+
aten,aten::clone.out"
41+
```
42+
43+
#### DType-Selective Build
44+
45+
To further reduce binary size, ExecuTorch can specialize the individual operators for only the dtypes (data types) used. For example, if
46+
the model only calls add with 32-bit floating point tensors, it can drop parts of the code that handle integer tensors or other floating point types. This option is controlled by passing `-DEXECUTORCH_DTYPE_SELECTIVE_BUILD=ON` to CMake. It is only supported in conjunction
47+
with the `EXECUTORCH_SELECT_OPS_MODEL` option and is not yet supported for other modes. It is recommended to enable this option when using `EXECUTORCH_SELECT_OPS_MODEL` as it provides significant size savings on top of the kernel selective build.
48+
49+
### How it Works
50+
51+
The CMake options described above are read by ExecuTorch framework build, which is referenced via `add_subdirectory` in basic/CMakeLists.txt. These options reflect in the `executorch_kernels` CMake target, which is linked against the example binary.
52+
53+
```cmake
54+
# basic/CMakeLists.txt
55+
target_link_libraries(
56+
selective_build_test
57+
PRIVATE executorch_core extension_evalue_util extension_runner_util
58+
gflags::gflags executorch_kernels
59+
)
60+
```
61+
62+
To use selective build in a user CMake project, take the following steps:
63+
* Reference the executorch framework via `add_subdirectory`.
64+
* Add `executorch_kernels` as a dependency (via target_link_libraries).
65+
* Set CMake options at build time or in user CMake code.
66+
67+
To use the CMake-build framework libraries from outside of the CMake ecosystem, link against libexecutorch_selected_kernels.
68+
69+
## Example 2 - Advanced Flow for Custom Ops and Kernel Libraries
70+
71+
This example showcases defined a custom kernel target. This option can be used when defining custom operators or integrating with
72+
kernel libraries not part of the standard ExecuTorch build.
73+
74+
The code under the advanced/ directory builds a minimal model runner binary which links to a user-defined kernel library target. To run a model with a simple custom operator, run the following commands:
75+
```
76+
# From the executorch directory
77+
python -m examples.portable.custom_ops.custom_ops_1 # Create a model PTE file
78+
cd examples/selective_build/basic
79+
mkdir cmake-out && cd cmake-out
80+
cmake .. -DEXECUTORCH_SELECT_OPS_MODEL="../../custom_ops_1.pte" -DEXECUTORCH_EXAMPLE_USE_CUSTOM_OPS=ON # Build with kernels needed for the model
81+
cmake --build . -j8
82+
./selective_build_test --model_path="../../custom_ops_1.pte" # Run the model with the selective kernel library
83+
```
84+
85+
### CMake Options
86+
87+
The CMake logic in `advanced/CMakeLists.txt` respects the CMake options described in the basic flow, as well as the following options:
88+
89+
* `EXECUTORCH_EXAMPLE_USE_CUSTOM_OPS`: Build and link some simple custom operators.
90+
* `EXECUTORCH_EXAMPLE_SELECT_ALL_OPS`: Build a kernel target with all available operators.
91+
92+
### How it Works
93+
94+
The build logic in `advanced/CMakeLists.txt` uses the `gen_selected_ops`, `generate_bindings_for_kernels`, and `gen_operators_lib` CMake functions to define an operator target. See [Kernel Library Selective Build](https://docs.pytorch.org/executorch/main/kernel-library-selective-build.html) for more information on selective build.
95+
96+
```cmake
97+
gen_selected_ops(
98+
LIB_NAME
99+
"select_build_lib"
100+
OPS_SCHEMA_YAML
101+
"${_custom_ops_yaml}"
102+
ROOT_OPS
103+
"${EXECUTORCH_SELECT_OPS_LIST}"
104+
INCLUDE_ALL_OPS
105+
"${EXECUTORCH_SELECT_ALL_OPS}"
106+
OPS_FROM_MODEL
107+
"${EXECUTORCH_SELECT_OPS_MODEL}"
108+
DTYPE_SELECTIVE_BUILD
109+
"${EXECUTORCH_DTYPE_SELECTIVE_BUILD}"
110+
)
111+
112+
generate_bindings_for_kernels(
113+
LIB_NAME
114+
"select_build_lib"
115+
FUNCTIONS_YAML
116+
${EXECUTORCH_ROOT}/kernels/portable/functions.yaml
117+
CUSTOM_OPS_YAML
118+
"${_custom_ops_yaml}"
119+
DTYPE_SELECTIVE_BUILD
120+
"${EXECUTORCH_DTYPE_SELECTIVE_BUILD}"
121+
)
122+
123+
gen_operators_lib(
124+
LIB_NAME
125+
"select_build_lib"
126+
KERNEL_LIBS
127+
${_kernel_lib}
128+
DEPS
129+
executorch_core
130+
DTYPE_SELECTIVE_BUILD
131+
"${EXECUTORCH_DTYPE_SELECTIVE_BUILD}"
132+
)
13133
```
14134

15-
Check out `CMakeLists.txt` for demo of selective build APIs:
16-
1. `SELECT_ALL_OPS`: Select all ops from the dependency kernel libraries, register all of them into ExecuTorch runtime.
17-
2. `SELECT_OPS_LIST`: Only select operators from a list.
18-
3. `SELECT_OPS_YAML`: Only select operators from a yaml file.
19-
4. `SELECT_OPS_FROM_MODEL`: Only select operators from a from an exported model pte.
20-
5. `DTYPE_SELECTIVE_BUILD`: Enable rebuild of `portable_kernels` to use dtype selection. Currently only supported for `SELECTED_OPS_FROM_MODEL` API and `portable_kernels` lib.
135+
To link against this target, the top-level binary target declares a dependency on `select_build_lib`, which is the library name defined by the above function invocations. To use outside of the CMake ecosystem, link against libselect_build_lib.
21136

22-
Other configs:
23-
- `MAX_KERNEL_NUM=N`: Only allocate memory for N operators.
137+
See `test_selective_build.sh` for additional build examples.

examples/selective_build/CMakeLists.txt renamed to examples/selective_build/advanced/CMakeLists.txt

Lines changed: 22 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
cmake_minimum_required(VERSION 3.19)
1919
project(selective_build_example)
2020

21-
set(EXECUTORCH_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/../..)
21+
set(EXECUTORCH_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/../../..)
2222
set(TORCH_ROOT ${EXECUTORCH_ROOT}/third-party/pytorch)
2323

2424
include(${EXECUTORCH_ROOT}/tools/cmake/Utils.cmake)
@@ -37,56 +37,37 @@ set(_common_compile_options -Wno-deprecated-declarations -fPIC
3737
-ffunction-sections -fdata-sections
3838
)
3939

40-
# Let files say "include <executorch/path/to/header.h>".
41-
set(_common_include_directories ${EXECUTORCH_ROOT}/..)
42-
43-
find_package(executorch CONFIG REQUIRED)
44-
find_package(
45-
gflags REQUIRED PATHS ${CMAKE_CURRENT_BINARY_DIR}/../../third-party
46-
)
47-
48-
target_include_directories(
49-
executorch_core INTERFACE ${_common_include_directories}
50-
)
40+
add_subdirectory(${EXECUTORCH_ROOT} ${CMAKE_CURRENT_BINARY_DIR}/executorch)
5141

5242
# ------------------------------ OPTIONS BEGIN -------------------------------
5343

54-
# Option to register ops from yaml file
55-
option(EXECUTORCH_SELECT_OPS_YAML "Register all the ops from a given yaml file"
56-
OFF
57-
)
58-
59-
# Option to register op list
60-
option(EXECUTORCH_SELECT_OPS_LIST "Register a list of ops, separated by comma"
61-
OFF
62-
)
63-
6444
# Selective build options.
65-
option(EXECUTORCH_SELECT_ALL_OPS
45+
option(EXECUTORCH_EXAMPLE_SELECT_ALL_OPS
6646
"Whether to register all ops defined in portable kernel library." OFF
6747
)
6848

69-
# Option to enable parsing ops and dtypes directly from model pte file
70-
option(EXECUTORCH_SELECT_OPS_FROM_MODEL
71-
"Enable op selection from pte during build." OFF
49+
option(EXECUTORCH_EXAMPLE_USE_CUSTOM_OPS
50+
"Whether to include custom ops in the example." OFF
7251
)
7352

74-
# Option to enable dtype selective build. Note: must be using selective build
75-
# model API.
76-
option(EXECUTORCH_DTYPE_SELECTIVE_BUILD "Enable dtype selective build." OFF)
53+
# Note that the following options are defined by the core framework and are also
54+
# used by this example when defining a custom operator target:
55+
#
56+
# EXECUTORCH_SELECT_OPS_YAML EXECUTORCH_SELECT_OPS_LIST
57+
# EXECUTORCH_SELECT_OPS_MODEL EXECUTORCH_DTYPE_SELECTIVE_BUILD
58+
7759
# ------------------------------- OPTIONS END --------------------------------
7860

7961
#
8062
# The `_<target>_srcs` lists are defined by executorch_load_build_variables.
8163
#
8264
executorch_load_build_variables()
8365

84-
#
85-
# select_build_lib: C++ library to register selected ops in custom kernel
86-
# library
87-
#
66+
# For advanced use cases, we can define a custom operator target. This is useful
67+
# when using custom operators.
8868
set(_kernel_lib)
89-
if(EXECUTORCH_SELECT_OPS_YAML)
69+
70+
if(EXECUTORCH_EXAMPLE_USE_CUSTOM_OPS)
9071
set(_custom_ops_yaml
9172
${EXECUTORCH_ROOT}/examples/portable/custom_ops/custom_ops.yaml
9273
)
@@ -116,7 +97,7 @@ gen_selected_ops(
11697
INCLUDE_ALL_OPS
11798
"${EXECUTORCH_SELECT_ALL_OPS}"
11899
OPS_FROM_MODEL
119-
"${EXECUTORCH_SELECT_OPS_FROM_MODEL}"
100+
"${EXECUTORCH_SELECT_OPS_MODEL}"
120101
DTYPE_SELECTIVE_BUILD
121102
"${EXECUTORCH_DTYPE_SELECTIVE_BUILD}"
122103
)
@@ -143,6 +124,9 @@ gen_operators_lib(
143124
"${EXECUTORCH_DTYPE_SELECTIVE_BUILD}"
144125
)
145126

127+
executorch_target_link_options_shared_lib(select_build_lib)
128+
set(selected_kernel_target select_build_lib)
129+
146130
list(TRANSFORM _executor_runner__srcs PREPEND "${EXECUTORCH_ROOT}/")
147131

148132
#
@@ -154,8 +138,8 @@ if(NOT CMAKE_BUILD_TYPE STREQUAL "Debug")
154138
target_link_options_gc_sections(selective_build_test)
155139
endif()
156140
target_link_libraries(
157-
selective_build_test PRIVATE executorch_core extension_evalue_util
158-
extension_runner_util gflags select_build_lib
141+
selective_build_test
142+
PRIVATE executorch_core extension_evalue_util extension_runner_util
143+
gflags::gflags ${selected_kernel_target}
159144
)
160-
executorch_target_link_options_shared_lib(select_build_lib)
161145
target_compile_options(selective_build_test PUBLIC ${_common_compile_options})
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
# Copyright (c) Meta Platforms, Inc. and affiliates.
2+
# All rights reserved.
3+
#
4+
# This source code is licensed under the BSD-style license found in the
5+
# LICENSE file in the root directory of this source tree.
6+
7+
#
8+
# Simple CMake build system for selective build demo.
9+
#
10+
# ### Editing this file ###
11+
#
12+
# This file should be formatted with
13+
# ~~~
14+
# cmake-format -i CMakeLists.txt
15+
# ~~~
16+
# It should also be cmake-lint clean.
17+
#
18+
cmake_minimum_required(VERSION 3.19)
19+
project(selective_build_example)
20+
21+
set(EXECUTORCH_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/../../..)
22+
set(TORCH_ROOT ${EXECUTORCH_ROOT}/third-party/pytorch)
23+
24+
include(${EXECUTORCH_ROOT}/tools/cmake/Utils.cmake)
25+
include(${EXECUTORCH_ROOT}/tools/cmake/Codegen.cmake)
26+
27+
if(NOT PYTHON_EXECUTABLE)
28+
resolve_python_executable()
29+
endif()
30+
31+
if(NOT CMAKE_CXX_STANDARD)
32+
set(CMAKE_CXX_STANDARD 17)
33+
# Can't set to 11 due to executor_runner.cpp make_unique
34+
endif()
35+
36+
set(_common_compile_options -Wno-deprecated-declarations -fPIC
37+
-ffunction-sections -fdata-sections
38+
)
39+
40+
add_subdirectory(${EXECUTORCH_ROOT} ${CMAKE_CURRENT_BINARY_DIR}/executorch)
41+
42+
# ------------------------------ OPTIONS BEGIN -------------------------------
43+
44+
# The following options are defined by the core framework and are also used in
45+
# the generated kernel target.
46+
#
47+
# EXECUTORCH_SELECT_OPS_YAML EXECUTORCH_SELECT_OPS_LIST
48+
# EXECUTORCH_SELECT_OPS_MODEL EXECUTORCH_DTYPE_SELECTIVE_BUILD
49+
50+
# ------------------------------- OPTIONS END --------------------------------
51+
52+
#
53+
# The `_<target>_srcs` lists are defined by executorch_load_build_variables.
54+
#
55+
executorch_load_build_variables()
56+
57+
# For most use cases, we can configure the ExecuTorch kernel library build using
58+
# the EXECUTORCH_SELECT_OPS_* variables. This will reflect in the
59+
# executorch_kernels target, which includes the configured kernel libraries,
60+
# including selective build, where supported.
61+
62+
list(TRANSFORM _executor_runner__srcs PREPEND "${EXECUTORCH_ROOT}/")
63+
64+
#
65+
# selective_build_test: test binary to allow different operator libraries to
66+
# link to
67+
#
68+
add_executable(selective_build_test ${_executor_runner__srcs})
69+
if(NOT CMAKE_BUILD_TYPE STREQUAL "Debug")
70+
target_link_options_gc_sections(selective_build_test)
71+
endif()
72+
target_link_libraries(
73+
selective_build_test
74+
PRIVATE executorch_core extension_evalue_util extension_runner_util
75+
gflags::gflags executorch_kernels
76+
)
77+
target_compile_options(selective_build_test PUBLIC ${_common_compile_options})

0 commit comments

Comments
 (0)