@@ -6,19 +6,65 @@ This source code is licensed under the BSD-style license found in the
66LICENSE file in the root directory of this source tree.
77-->
88
9- # ExecuTorch for ESP-IDF (` executorch ` component)
9+ # ExecuTorch for ESP-IDF
10+
11+ [ ExecuTorch] ( https://github.com/pytorch/executorch ) is PyTorch's open
12+ source stack for running AI locally on phones, wearables, laptops,
13+ browsers, embedded systems and microcontrollers. This component brings
14+ its runtime to ESP-IDF 6.0 and later, for any ESP target, as source that
15+ builds with your project.
16+
17+ ## How ExecuTorch works
18+
19+ A model is prepared ahead of time, on your computer, with the
20+ ` executorch ` Python package. You export it with ` torch.export ` ,
21+ optionally quantize it, and lower it to a ` .pte ` program. Lowering can
22+ hand the parts of the model that a backend supports to that backend's
23+ delegate, and it plans where every tensor lives in memory, so the
24+ device runs the model in arenas whose sizes are known before it starts.
25+
26+ On the device, the runtime reads the ` .pte ` in place from flash and runs
27+ it: each operator with a kernel from a kernel library, and each
28+ delegated part with its backend.
29+
30+ [ How ExecuTorch works] ( https://docs.pytorch.org/executorch/stable/intro-how-it-works.html )
31+ and [ Model export and lowering] ( https://docs.pytorch.org/executorch/stable/using-executorch-export.html )
32+ cover this in more depth.
33+
34+ ## What the component provides
35+
36+ - The ExecuTorch runtime, and ` et_model.h ` , a small C API that runs a
37+ ` .pte ` from flash.
38+ - Kernel libraries: portable (reference kernels for the core ATen
39+ operators), quantized, and the Cadence backend's generic kernels.
40+ - The ESP-NN delegate, ` EspNNBackend ` , which runs the int8 parts of a
41+ model lowered for it with Espressif's
42+ [ ESP-NN] ( https://github.com/espressif/esp-nn ) kernels. ESP-NN has SIMD
43+ kernels for the ESP32-S3 and portable C kernels for the other chips.
44+ The delegate is a prototype under active development.
45+ - ` tools/gen_kernels.py ` , which makes the kernel bundle that registers
46+ the kernels your models use.
47+ - ` examples/hello_executorch ` , a complete project.
48+
49+ ## Try it
50+
51+ ` hello_executorch ` runs a small model and checks its outputs. Its ` .pte `
52+ and kernel bundle are already made, so it needs only ESP-IDF:
1053
11- ** This tree is generated. Do not edit it by hand.** It is produced by
12- ` examples/espressif/build_idf_component.sh ` in the
13- [ ExecuTorch] ( https://github.com/pytorch/executorch ) repository.
54+ ``` sh
55+ idf.py create-project-from-example " pytorch/executorch==@ET_COMPONENT_VERSION@:hello_executorch"
56+ cd hello_executorch
57+ idf.py set-target esp32s3
58+ idf.py build flash monitor
59+ ```
60+
61+ It prints ` ET_COMPONENT_SMOKE: PASS ` when every output matches. In a
62+ copy of this component you generated yourself, build
63+ ` examples/hello_executorch ` in place instead.
1464
15- ` VERSION ` in this directory records the ExecuTorch commit, the generator's
16- options, the kernel libraries the component ships and the torch to
17- install with executorch. ` examples/hello_executorch ` is a complete
18- project that runs a small model with its kernel bundle; its README says
19- how they were made.
65+ ## Using it in your project
2066
21- ## Using it
67+ ### Add the dependency
2268
2369Depend on one exact version and commit ` dependencies.lock ` :
2470
@@ -27,38 +73,23 @@ dependencies:
2773 pytorch/executorch : " ==@ET_COMPONENT_VERSION@"
2874` ` `
2975
30- The registry's dev versions, ` X.Y.Z-dev.YYYYMMDD`, come from the
31- ` nightly` branch. A copy you generate yourself is not published; use it
32- from your project's `components/` or through `override_path`.
33-
3476A kernel bundle is made for one component version, a ` ~N` respin
3577included, and the build refuses a bundle made for another version, or
3678for the same version from another commit. With a range, the build
3779breaks once the lock is re-solved to a newer version (for example by
3880` idf.py update-dependencies` ), until the bundle is regenerated.
3981
40- The component carries the runtime, every kernel of its kernel
41- libraries (portable, quantized, the Cadence backend's generic kernels
42- and the `esp_nn::` op library) and the ESP-NN delegate
43- (`EspNNBackend`), but registers only the kernels your models use and
44- links the delegate only when one of them uses it. It depends on
45- ` espressif/esp-nn` , which the component manager fetches from the
46- production registry, components.espressif.com, even for a project that
47- names another registry; a project that builds without the component
48- manager provides it as `components/esp-nn`. The kernels come
49- from a kernel bundle that `tools/gen_kernels.py` makes from your
50- ` .pte` files. Run it with the Python environment you exported the
51- models with, after every export, ExecuTorch upgrade or update of this
52- component, and keep the bundle in your project :
82+ The component depends on `espressif/esp-nn`, which the component manager
83+ fetches from the production registry, components.espressif.com, even
84+ for a project that names another registry. A project that builds
85+ without the component manager provides it as `components/esp-nn`.
5386
54- ` ` ` sh
55- python <this directory>/tools/gen_kernels.py --pte main/model.pte --out main/et_kernels
56- ` ` `
87+ # ## Set up Python
5788
58- That environment ( Python 3.11 to 3.15) needs the executorch this
59- component was built from, and the torch that `VERSION` names as
60- ` torch_requirement` , from its `torch_index`, since ExecuTorch's wheels
61- declare no torch :
89+ Exporting models and making kernel bundles need Python 3.11 to 3.15 with
90+ the executorch this component was built from, and the torch that
91+ ` VERSION ` names as ` torch_requirement`, from its `torch_index`, since
92+ ExecuTorch's wheels declare no torch :
6293
6394` ` ` sh
6495@ET_INSTALL@
@@ -68,10 +99,48 @@ A dev version's executorch comes from the nightly index, which keeps
6899about 60 days of wheels, so move to a newer version before yours ages
69100out.
70101
71- Then declare the models and the bundle, from a component's
72- ` CMakeLists.txt` after its `idf_component_register()` or from the
73- project's after `project()`, and add `executorch` to the requirements
74- of the components that use it :
102+ # ## Export a model
103+
104+ To run a model with ESP-NN, quantize it with `EspNNQuantizer` and lower
105+ it with `to_espnn_edge`, which delegates the int8 regions ESP-NN
106+ supports and leaves the rest to the CPU kernels :
107+
108+ ` ` ` python
109+ import torch
110+ from executorch.backends.espressif import EspNNQuantizer, to_espnn_edge
111+ from torchao.quantization.pt2e.quantize_pt2e import convert_pt2e, prepare_pt2e
112+
113+ model = MyModel().eval()
114+ example_inputs = (torch.randn(1, 3, 96, 96),)
115+
116+ prepared = prepare_pt2e(
117+ torch.export.export(model, example_inputs).module(), EspNNQuantizer()
118+ )
119+ for inputs in calibration_inputs: # representative inputs set the int8 scales
120+ prepared(*inputs)
121+ quantized = torch.export.export(convert_pt2e(prepared), example_inputs)
122+ edge, report = to_espnn_edge(quantized)
123+ with open("main/model.pte", "wb") as f:
124+ f.write(edge.to_executorch().buffer)
125+ ` ` `
126+
127+ # ## Make the kernel bundle
128+
129+ ` tools/gen_kernels.py` makes the kernel bundle from your `.pte` files.
130+ Run it with the Python environment you exported the models with, after
131+ every export, ExecuTorch upgrade or update of this component, and keep
132+ the bundle in your project :
133+
134+ ` ` ` sh
135+ python <this directory>/tools/gen_kernels.py --pte main/model.pte --out main/et_kernels
136+ ` ` `
137+
138+ # ## Declare the models and the bundle
139+
140+ From a component's `CMakeLists.txt` after its `idf_component_register()`,
141+ or from the project's after `project()`, declare the models and the
142+ bundle, and add `executorch` to the requirements of the components that
143+ use it :
75144
76145` ` ` cmake
77146idf_component_register(SRCS "main.c" PRIV_REQUIRES executorch)
@@ -106,18 +175,34 @@ With a bundle that registers kernels, the build compiles every vendored
106175kernel source, and the link keeps only the ones the bundle registers.
107176The extra kernels cost clean-build time, not flash.
108177
109- - ` #include <et_model.h>` for the small C inference API (flash XIP
110- model bytes; method, planned and optional scratch arenas either
111- passed in or allocated with heap_caps internal/PSRAM placement). This
112- is what most applications should use. The `.pte` bytes must be
113- 16-byte aligned; `et_model_create` rejects misaligned data. Application pipelines built on it (audio
114- front ends, detectors, wake word logic) live with the application,
115- not in this runtime component.
116- - ` #include <executorch/...>` for the core C++ runtime
117- (`Program`/`Method`) and `BufferDataLoader`. `extension::Module`, the
118- file and mmap data loaders, and external `.ptd` data maps are not
119- included. Runtime logging goes through ESP_LOG under the
120- ` executorch` tag.
178+ # ## Run the model
179+
180+ `et_model.h` loads a `.pte` and runs it :
181+
182+ ` ` ` c
183+ #include <et_model.h>
184+
185+ et_model_config_t cfg = ET_MODEL_CONFIG_DEFAULT(model_pte, model_pte_size);
186+ cfg.planned_location = ET_MEM_INTERNAL; // activations in internal SRAM
187+ et_model_t *m = et_model_create(&cfg);
188+ if (!m || !et_model_load_method(m, NULL)) { /* handle the error */ }
189+ et_model_set_input(m, 0, frame, sizeof(frame));
190+ et_model_execute(m);
191+ size_t n;
192+ const void *out = et_model_output_data(m, 0, &n);
193+ ` ` `
194+
195+ The model bytes are read in place, typically from flash, and must be
196+ 16-byte aligned; `et_model_create` rejects misaligned data.
197+ ` examples/hello_executorch/main/CMakeLists.txt` embeds a `.pte` that way.
198+ The method, planned and optional scratch arenas are either passed in or
199+ allocated with heap_caps in internal RAM or PSRAM. Application pipelines
200+ built on it (audio front ends, detectors, wake word logic) live with the
201+ application, not in this component.
202+
203+ For the core C++ runtime (`Program`/`Method`) and `BufferDataLoader`,
204+ ` #include <executorch/...>` . `extension::Module`, the file and mmap data
205+ loaders, and external `.ptd` data maps are not included.
121206
122207# # Size and debug options
123208
@@ -152,3 +237,19 @@ Projects moving from the op profiles of earlier versions remove
152237` CONFIG_ET_ENABLE` and `CONFIG_ET_OP_PROFILE_*` from their sdkconfig,
153238which no longer do anything, and declare their models and a kernel
154239bundle as above.
240+
241+ # # About this component
242+
243+ **This tree is generated. Do not edit it by hand.** It is produced by
244+ ` examples/espressif/build_idf_component.sh` in the ExecuTorch
245+ repository. Releases are versioned as ExecuTorch's, `X.Y.Z`, with
246+ ` X.Y.Z-rc.N` for release candidates and `X.Y.Z~N` for respins of this
247+ component. The registry's dev versions, `X.Y.Z-dev.YYYYMMDD`, come from
248+ the `nightly` branch. A copy you generate yourself is not published; use
249+ it from your project's `components/` or through `override_path`.
250+
251+ ` VERSION` records the ExecuTorch commit, the generator's options, the
252+ kernel libraries the component ships and the torch to install with
253+ executorch. The README of `examples/hello_executorch` says how its model
254+ and kernel bundle were made. Vendored third-party code is listed in
255+ ` THIRD_PARTY_LICENSES` and the `sbom*.yml` files.
0 commit comments