@@ -6,19 +6,72 @@ 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
1010
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.
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 the model's intermediate tensors live in
24+ memory, so the device keeps them in an arena whose size is known before
25+ it starts.
26+
27+ On the device, the runtime reads the ` .pte ` in place from flash and runs
28+ it: each operator with a kernel from a kernel library, and each
29+ delegated part with its backend.
30+
31+ [ How ExecuTorch works] ( https://docs.pytorch.org/executorch/stable/intro-how-it-works.html )
32+ and [ Model export and lowering] ( https://docs.pytorch.org/executorch/stable/using-executorch-export.html )
33+ cover this in more depth.
1434
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.
35+ ## What the component provides
2036
21- ## Using it
37+ - The ExecuTorch runtime, and ` et_model.h ` , a small C API that runs a
38+ ` .pte ` from flash.
39+ - Kernel libraries: portable (reference kernels for the core ATen
40+ operators), quantized, and the Cadence backend's generic kernels.
41+ - The ESP-NN delegate, ` EspNNBackend ` , which runs the int8 parts of a
42+ model lowered for it with Espressif's
43+ [ ESP-NN] ( https://github.com/espressif/esp-nn ) kernels. ESP-NN has SIMD
44+ kernels for the ESP32-S3 and portable C kernels for the other chips.
45+ The delegate is a prototype under active development.
46+ - ` tools/gen_kernels.py ` , which makes the kernel bundle that registers
47+ the kernels your models use.
48+ - ` examples/hello_executorch ` , a complete project, in every published
49+ version.
50+
51+ ## Try it
52+
53+ ` hello_executorch ` runs a small model and checks its outputs. Its ` .pte `
54+ and kernel bundle are already made, so it needs only ESP-IDF:
55+
56+ ``` sh
57+ idf.py create-project-from-example " pytorch/executorch==@ET_COMPONENT_VERSION@:hello_executorch"
58+ cd hello_executorch
59+ idf.py set-target esp32s3
60+ idf.py build flash monitor
61+ ```
62+
63+ It prints ` ET_COMPONENT_SMOKE: PASS ` when every output matches. A
64+ release candidate is on the staging registry only, so for one, first
65+ ` export IDF_COMPONENT_REGISTRY_URL=https://components-staging.espressif.com `
66+ in the shell, since the build resolves the version again. In a copy of
67+ this component you generated yourself, build ` examples/hello_executorch `
68+ in place instead. The generator leaves it out only of an
69+ ` --allow-dev-stamp ` copy made without the executorch package built from
70+ that commit.
71+
72+ ## Using it in your project
73+
74+ ### Add the dependency
2275
2376Depend on one exact version and commit ` dependencies.lock ` :
2477
@@ -27,47 +80,75 @@ dependencies:
2780 pytorch/executorch : " ==@ET_COMPONENT_VERSION@"
2881` ` `
2982
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`.
83+ A release candidate's dependency also needs
84+ ` registry_url: https://components-staging.espressif.com`.
3385
3486A kernel bundle is made for one component version, a `~N` respin
3587included, and the build refuses a bundle made for another version, or
3688for the same version from another commit. With a range, the build
3789breaks once the lock is re-solved to a newer version (for example by
3890` idf.py update-dependencies` ), until the bundle is regenerated.
3991
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 :
92+ The component depends on `espressif/esp-nn`, which the component manager
93+ fetches from the production registry, components.espressif.com, even
94+ for a project that names another registry. A project that builds
95+ without the component manager provides it as `components/esp-nn`.
96+
97+ # ## Set up Python
98+
99+ Exporting models and making kernel bundles need the executorch this
100+ component was built from, and the torch that `VERSION` names as
101+ ` torch_requirement` , from its `torch_index`, since ExecuTorch's wheels
102+ declare no torch :
53103
54104` ` ` sh
55- python <this directory>/tools/gen_kernels.py --pte main/model.pte --out main/et_kernels
105+ @ET_INSTALL@
56106` ` `
57107
58- The Python environment you export models and run `gen_kernels.py` with
59- needs the executorch this component was built from, and the torch that
60- ` VERSION` names as `torch_requirement`, from its `torch_index`, since
61- ExecuTorch's wheels declare no torch :
108+ # ## Export a model
109+
110+ To run a model with ESP-NN, quantize it with `EspNNQuantizer` and lower
111+ it with `to_espnn_edge`, which delegates the int8 regions ESP-NN
112+ supports and leaves the rest to the CPU kernels :
113+
114+ ` ` ` python
115+ import torch
116+ from executorch.backends.espressif import EspNNQuantizer, to_espnn_edge
117+ from torchao.quantization.pt2e.quantize_pt2e import convert_pt2e, prepare_pt2e
118+
119+ model = MyModel().eval() # your torch.nn.Module
120+ example_inputs = (torch.randn(1, 3, 96, 96),)
121+
122+ prepared = prepare_pt2e(
123+ torch.export.export(model, example_inputs).module(), EspNNQuantizer()
124+ )
125+ # Tuples of representative inputs, from which the int8 scales are set.
126+ for inputs in calibration_inputs:
127+ prepared(*inputs)
128+ quantized = torch.export.export(convert_pt2e(prepared), example_inputs)
129+ edge, report = to_espnn_edge(quantized)
130+ print(report["cpu_ops"]) # the operators left to the CPU kernels
131+ with open("main/model.pte", "wb") as f:
132+ f.write(edge.to_executorch().buffer)
133+ ` ` `
134+
135+ # ## Make the kernel bundle
136+
137+ ` tools/gen_kernels.py` makes the kernel bundle from your `.pte` files.
138+ Run it with the Python environment you exported the models with, after
139+ every export, ExecuTorch upgrade or update of this component, and keep
140+ the bundle in your project :
62141
63142` ` ` sh
64- @ET_INSTALL@
143+ python <this directory>/tools/gen_kernels.py --pte main/model.pte --out main/et_kernels
65144` ` `
66145
67- Then declare the models and the bundle, from a component's
68- ` CMakeLists.txt` after its `idf_component_register()` or from the
69- project's after `project()`, and add `executorch` to the requirements
70- of the components that use it :
146+ # ## Declare the models and the bundle
147+
148+ From a component's `CMakeLists.txt` after its `idf_component_register()`,
149+ or from the project's after `project()`, declare the models and the
150+ bundle, and add `executorch` to the requirements of the components that
151+ use it :
71152
72153` ` ` cmake
73154idf_component_register(SRCS "main.c" PRIV_REQUIRES executorch)
@@ -102,18 +183,43 @@ With a bundle that registers kernels, the build compiles every vendored
102183kernel source, and the link keeps only the ones the bundle registers.
103184The extra kernels cost clean-build time, not flash.
104185
105- - ` #include <et_model.h>` for the small C inference API (flash XIP
106- model bytes; method, planned and optional scratch arenas either
107- passed in or allocated with heap_caps internal/PSRAM placement). This
108- is what most applications should use. The `.pte` bytes must be
109- 16-byte aligned; `et_model_create` rejects misaligned data. Application pipelines built on it (audio
110- front ends, detectors, wake word logic) live with the application,
111- not in this runtime component.
112- - ` #include <executorch/...>` for the core C++ runtime
113- (`Program`/`Method`) and `BufferDataLoader`. `extension::Module`, the
114- file and mmap data loaders, and external `.ptd` data maps are not
115- included. Runtime logging goes through ESP_LOG under the
116- ` executorch` tag.
186+ # ## Run the model
187+
188+ `et_model.h` loads a `.pte` and runs it :
189+
190+ ` ` ` c
191+ #include <esp_log.h>
192+ #include <et_model.h>
193+
194+ et_model_config_t cfg = ET_MODEL_CONFIG_DEFAULT(model_pte, model_pte_size);
195+ cfg.planned_location = ET_MEM_INTERNAL; // planned tensors in internal SRAM
196+ et_model_t *m = et_model_create(&cfg);
197+ if (!m) {
198+ return; // et_model_create logs why
199+ }
200+ size_t n;
201+ const void *out = NULL;
202+ if (!et_model_load_method(m, NULL) || !et_model_set_input(m, 0, frame, sizeof(frame)) ||
203+ !et_model_execute(m) || !(out = et_model_output_data(m, 0, &n))) {
204+ ESP_LOGE("app", "%s", et_model_last_error(m));
205+ et_model_destroy(m);
206+ return;
207+ }
208+ ` ` `
209+
210+ ` model_pte` and `model_pte_size` are the `.pte` bytes, read in place,
211+ typically from flash. They must be 16-byte aligned, and
212+ ` et_model_create` rejects misaligned data. ESP-IDF's `EMBED_FILES` does
213+ not align what it embeds, so `examples/hello_executorch/main/CMakeLists.txt`
214+ embeds its `.pte` with an assembler `.balign 16` and `.incbin` instead.
215+ The method, planned and optional scratch arenas are either passed in or
216+ allocated with heap_caps in internal RAM or PSRAM. Application pipelines
217+ built on it (audio front ends, detectors, wake word logic) live with the
218+ application, not in this component.
219+
220+ For the core C++ runtime (`Program`/`Method`) and `BufferDataLoader`,
221+ ` #include <executorch/...>` . `extension::Module`, the file and mmap data
222+ loaders, and external `.ptd` data maps are not included.
117223
118224# # Size and debug options
119225
@@ -148,3 +254,19 @@ Projects moving from the op profiles of earlier versions remove
148254` CONFIG_ET_ENABLE` and `CONFIG_ET_OP_PROFILE_*` from their sdkconfig,
149255which no longer do anything, and declare their models and a kernel
150256bundle as above.
257+
258+ # # About this component
259+
260+ **This tree is generated. Do not edit it by hand.** It is produced by
261+ ` examples/espressif/build_idf_component.sh` in the ExecuTorch
262+ repository. Releases are versioned as ExecuTorch's, `X.Y.Z`, with
263+ ` X.Y.Z-rc.N` for release candidates and `X.Y.Z~N` for respins of this
264+ component. The registry's dev versions, `X.Y.Z-dev.YYYYMMDD`, come from
265+ the `nightly` branch. A copy you generate yourself is not published; use
266+ it from your project's `components/` or through `override_path`.
267+
268+ ` VERSION` records the ExecuTorch commit, the generator's options, the
269+ kernel libraries the component ships and the torch to install with
270+ executorch. The README of `examples/hello_executorch` says how its model
271+ and kernel bundle were made. Vendored third-party code is listed in
272+ ` THIRD_PARTY_LICENSES` and the `sbom*.yml` files.
0 commit comments