@@ -6,19 +6,70 @@ 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.
34+
35+ ## What the component provides
36+
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.
49+
50+ ## Try it
51+
52+ ` hello_executorch ` runs a small model and checks its outputs. Its ` .pte `
53+ and kernel bundle are already made, so it needs only ESP-IDF:
54+
55+ ``` sh
56+ idf.py create-project-from-example " pytorch/executorch==@ET_COMPONENT_VERSION@:hello_executorch"
57+ cd hello_executorch
58+ idf.py set-target esp32s3
59+ idf.py build flash monitor
60+ ```
61+
62+ It prints ` ET_COMPONENT_SMOKE: PASS ` when every output matches. A
63+ release candidate is on the staging registry only, so for one, set
64+ ` IDF_COMPONENT_REGISTRY_URL=https://components-staging.espressif.com `
65+ first. In a copy of this component you generated yourself, build
66+ ` examples/hello_executorch ` in place instead, if the generator included
67+ it, which it does when it runs with the executorch package built from
68+ the same commit.
1469
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.
70+ ## Using it in your project
2071
21- ## Using it
72+ ### Add the dependency
2273
2374Depend on one exact version and commit ` dependencies.lock ` :
2475
@@ -27,38 +78,26 @@ dependencies:
2778 pytorch/executorch : " ==@ET_COMPONENT_VERSION@"
2879` ` `
2980
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`.
81+ A release candidate's dependency also needs
82+ ` registry_url: https://components-staging.espressif.com`.
3383
3484A kernel bundle is made for one component version, a `~N` respin
3585included, and the build refuses a bundle made for another version, or
3686for the same version from another commit. With a range, the build
3787breaks once the lock is re-solved to a newer version (for example by
3888` idf.py update-dependencies` ), until the bundle is regenerated.
3989
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 :
90+ The component depends on `espressif/esp-nn`, which the component manager
91+ fetches from the production registry, components.espressif.com, even
92+ for a project that names another registry. A project that builds
93+ without the component manager provides it as `components/esp-nn`.
5394
54- ` ` ` sh
55- python <this directory>/tools/gen_kernels.py --pte main/model.pte --out main/et_kernels
56- ` ` `
95+ # ## Set up Python
5796
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 :
97+ Exporting models and making kernel bundles need the executorch this
98+ component was built from, and the torch that `VERSION` names as
99+ ` torch_requirement` , from its `torch_index`, since ExecuTorch's wheels
100+ declare no torch :
62101
63102` ` ` sh
64103@ET_INSTALL@
@@ -68,10 +107,48 @@ A dev version's executorch comes from the nightly index, which keeps
68107about 60 days of wheels, so move to a newer version before yours ages
69108out.
70109
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 :
110+ # ## Export a model
111+
112+ To run a model with ESP-NN, quantize it with `EspNNQuantizer` and lower
113+ it with `to_espnn_edge`, which delegates the int8 regions ESP-NN
114+ supports and leaves the rest to the CPU kernels :
115+
116+ ` ` ` python
117+ import torch
118+ from executorch.backends.espressif import EspNNQuantizer, to_espnn_edge
119+ from torchao.quantization.pt2e.quantize_pt2e import convert_pt2e, prepare_pt2e
120+
121+ model = MyModel().eval()
122+ example_inputs = (torch.randn(1, 3, 96, 96),)
123+
124+ prepared = prepare_pt2e(
125+ torch.export.export(model, example_inputs).module(), EspNNQuantizer()
126+ )
127+ for inputs in calibration_inputs: # representative inputs set the int8 scales
128+ prepared(*inputs)
129+ quantized = torch.export.export(convert_pt2e(prepared), example_inputs)
130+ edge, report = to_espnn_edge(quantized)
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 :
141+
142+ ` ` ` sh
143+ python <this directory>/tools/gen_kernels.py --pte main/model.pte --out main/et_kernels
144+ ` ` `
145+
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 :
75152
76153` ` ` cmake
77154idf_component_register(SRCS "main.c" PRIV_REQUIRES executorch)
@@ -106,18 +183,37 @@ With a bundle that registers kernels, the build compiles every vendored
106183kernel source, and the link keeps only the ones the bundle registers.
107184The extra kernels cost clean-build time, not flash.
108185
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.
186+ # ## Run the model
187+
188+ `et_model.h` loads a `.pte` and runs it :
189+
190+ ` ` ` c
191+ #include <et_model.h>
192+
193+ et_model_config_t cfg = ET_MODEL_CONFIG_DEFAULT(model_pte, model_pte_size);
194+ cfg.planned_location = ET_MEM_INTERNAL; // planned tensors in internal SRAM
195+ et_model_t *m = et_model_create(&cfg);
196+ if (!m || !et_model_load_method(m, NULL)) { /* handle the error */ }
197+ if (!et_model_set_input(m, 0, frame, sizeof(frame)) || !et_model_execute(m)) {
198+ /* et_model_last_error(m) says why */
199+ }
200+ size_t n;
201+ const void *out = et_model_output_data(m, 0, &n);
202+ ` ` `
203+
204+ ` model_pte` and `model_pte_size` are the `.pte` bytes, read in place,
205+ typically from flash. They must be 16-byte aligned, and
206+ ` et_model_create` rejects misaligned data. ESP-IDF's `EMBED_FILES` does
207+ not align what it embeds, so `examples/hello_executorch/main/CMakeLists.txt`
208+ embeds its `.pte` with an assembler `.balign 16` and `.incbin` instead.
209+ The method, planned and optional scratch arenas are either passed in or
210+ allocated with heap_caps in internal RAM or PSRAM. Application pipelines
211+ built on it (audio front ends, detectors, wake word logic) live with the
212+ application, not in this component.
213+
214+ For the core C++ runtime (`Program`/`Method`) and `BufferDataLoader`,
215+ ` #include <executorch/...>` . `extension::Module`, the file and mmap data
216+ loaders, and external `.ptd` data maps are not included.
121217
122218# # Size and debug options
123219
@@ -152,3 +248,19 @@ Projects moving from the op profiles of earlier versions remove
152248` CONFIG_ET_ENABLE` and `CONFIG_ET_OP_PROFILE_*` from their sdkconfig,
153249which no longer do anything, and declare their models and a kernel
154250bundle as above.
251+
252+ # # About this component
253+
254+ **This tree is generated. Do not edit it by hand.** It is produced by
255+ ` examples/espressif/build_idf_component.sh` in the ExecuTorch
256+ repository. Releases are versioned as ExecuTorch's, `X.Y.Z`, with
257+ ` X.Y.Z-rc.N` for release candidates and `X.Y.Z~N` for respins of this
258+ component. The registry's dev versions, `X.Y.Z-dev.YYYYMMDD`, come from
259+ the `nightly` branch. A copy you generate yourself is not published; use
260+ it from your project's `components/` or through `override_path`.
261+
262+ ` VERSION` records the ExecuTorch commit, the generator's options, the
263+ kernel libraries the component ships and the torch to install with
264+ executorch. The README of `examples/hello_executorch` says how its model
265+ and kernel bundle were made. Vendored third-party code is listed in
266+ ` THIRD_PARTY_LICENSES` and the `sbom*.yml` files.
0 commit comments