Repository navigation
Commit 46017a1
authored
Split the runtime out of the Python bindings extension (pytorch#21610)
`pip install executorch` gives you the Python half of ExecuTorch and
nothing a C++ program can
link. Everything is fused into one large Python extension file, so a C++
developer has to clone
the repository, sync submodules, and build from source.
There is a correctness problem underneath the packaging one. Because the
runtime is fused into the
extension, anything else that needs it gets its own private copy, and
two copies mean two
registries. A backend registered in one is invisible to the other.
Build the runtime and the pieces around it as separate shared libraries,
and make the Python
extension link them instead of embedding them. A shared library is a
file a program loads at run
time, so several programs can use one copy instead of each carrying its
own.
```
executorch/
lib/libexecutorch.so the runtime
lib/libexecutorch_kernels_optimized.so CPU operator kernels
lib/libexecutorch_backend_xnnpack.so the XNNPACK delegate
lib/libexecutorch_threadpool.so one thread pool per process
lib/libexecutorch_etdump.so the profiler
extension/pybindings/_portable_lib.so now under a megabyte, links the above
```
The extension is much smaller than before, because it no longer contains
what it now links.
Linux only, and only when the CUDA backend is off. macOS and Windows
keep the fused extension
because the split relies on ELF sonames, the `$ORIGIN` search-path token
and GNU linker options,
none of which apply there, and enabling it elsewhere now fails while
configuring rather than much
later. A CUDA build also keeps the fused extension for now, because the
CUDA libraries are not yet
shipped alongside the others.
The CMake package a source install writes follows the same line. It
hands out the shared runtime
on Linux, and on Apple it keeps handing out the static libraries it
always did. The shared runtime
does not carry the kernels, so a consumer needs the kernels archive
alongside it, and that archive
pulls a second copy of the core in behind it. ELF resolves both copies
to the executable's
definition and the program is correct; Mach-O binds each image to its
own, so the two never
converge and a registration would not cross the boundary. Removing that
second copy on Apple means
dropping every archive already bundled into the shared runtime from the
list this file hands out,
which is a wider change than this one.
The wheel now ships the profiler as a library and documents it as
usable, so the event tracer is
turned on for the Linux and macOS builds, where it was off and every
recording hook was
preprocessed away. Windows keeps it off. Nothing here touches the
Windows branch of the preset, and
no Windows wheel has been exercised yet, so turning the hooks on there
is left for when it can be
tested.
Turning the tracer on also creates XNNPACK with basic profiling, so the
delegate read per-operator
timings after every execution whether or not a caller had attached a
tracer to read them. That
retrieval now happens only when there is a tracer to receive it. It does
not remove the cost of
profiling, since the timers around each operator remain, and the
standalone profiling build still
retrieves unconditionally through its own gate.
Built the wheel from source, installed it into a clean environment, and
checked:
- exactly one library defines each component, and it is the library that
should own it. Counting
owners alone would also pass on the old fused layout, which has exactly
one too.
- the Python extension defines none of them and resolves all of them
from outside.
- every shipped library loads with no unresolved dependency, and none of
them searches a directory
from the machine that built the wheel. The build-directory patterns are
matched as whole path
components, because a bare substring also matched an unrelated directory
a user could really
have, such as `/home/user/cmake-outputs/torchlibs`, and stripping that
breaks a dependency the
library legitimately resolves there.
- a read-only build output is no longer archived world-writable. The
previous code granted write
to the group and to everyone via an absolute chmod mode; the fix only
grants owner-write, so a
`0555` file lands as `0755` instead of `0777`.
- a custom operator library compiles and links against the shipped
Python extension, which is the
existing contract this must not break. Linking these libraries from a
standalone C++ application
additionally needs an installed CMake package, which the wheel does not
carry yet.
- the ahead-of-time quantized library records its route to the runtime
through the same helper the
other targets use. It was written by hand in two blocks that between
them covered only the wheel
layout and only when the wheel flag was set, so a plain
`-DEXECUTORCH_BUILD_SHARED=ON` build left
it with no route at all. Checked all four combinations of the shared
build and the presence of the
Python extension.
Ran on Linux x86_64 and aarch64, including a Jetson device.
Two runtime requirements are new, `py-cpuinfo` and `requests`. Rewiring
the Qualcomm backend onto
the shared runtime showed that `backends/qualcomm/__init__.py` cannot be
imported from a clean
install at all: it reads the CPU vendor through `cpuinfo` to disable an
mkldnn path on AMD, and the
module it imports first does a module-scope `import requests`. Neither
was declared, so declaring
only one of them moves the failure one line rather than fixing it. They
are declared here, in the
commit that moves that backend, rather than as a separate change.
Not fixed here: these libraries bundle third-party code that torch also
links, and both keep it
visible, so a process holds two definitions of symbols like
`pthreadpool_create`. A caller reaches
whichever the loader found first. Fixing it means hiding or dropping the
bundled copies, which is a
larger change.1 parent eefaf28 commit 46017a1
38 files changed
Lines changed: 3289 additions & 192 deletions
File tree
- .ci/scripts
- tests
- wheel
- .github/workflows
- backends
- apple/coreml
- cuda
- qualcomm
- xnnpack
- runtime/profiling
- codegen/tools
- configurations
- devtools
- bundled_program
- etdump
- extension
- llm
- custom_ops
- runner
- threadpool
- training
- kernels
- portable
- quantized
- runtime/core/exec_aten/util
- tools/cmake
- preset
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
71 | 71 | | |
72 | 72 | | |
73 | 73 | | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
74 | 79 | | |
75 | 80 | | |
76 | 81 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
8 | 8 | | |
9 | 9 | | |
10 | 10 | | |
| 11 | + | |
| 12 | + | |
11 | 13 | | |
12 | 14 | | |
| 15 | + | |
13 | 16 | | |
14 | 17 | | |
15 | 18 | | |
| |||
42 | 45 | | |
43 | 46 | | |
44 | 47 | | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
45 | 54 | | |
46 | 55 | | |
47 | 56 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
5 | 5 | | |
6 | 6 | | |
7 | 7 | | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
8 | 11 | | |
| 12 | + | |
9 | 13 | | |
10 | 14 | | |
11 | 15 | | |
| |||
26 | 30 | | |
27 | 31 | | |
28 | 32 | | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
29 | 39 | | |
30 | 40 | | |
31 | 41 | | |
| |||
0 commit comments