Skip to content

Ship the merged CPU kernels as their own library - #21524

Open
shoumikhin wants to merge 8 commits into
gh/shoumikhin/79/headfrom
gh/shoumikhin/80/head
Open

Ship the merged CPU kernels as their own library#21524
shoumikhin wants to merge 8 commits into
gh/shoumikhin/79/headfrom
gh/shoumikhin/80/head

Conversation

@shoumikhin

Copy link
Copy Markdown
Contributor

The CPU operator kernels are compiled into whichever component links them, so
the Python bindings extension carries its own full copy. That makes the
extension large, and it means a C++ application cannot get the same operators
without building them from source. It also means two components that both want
CPU operators end up with two independent registrations of the same operator
set in one process.

Build the merged CPU kernels as a shared library and ship it in the wheel, so
the operators live in one place and both the Python bindings and a C++
application can link the same copy.

The library type is opt-in rather than a global change: gen_operators_lib has
many callers that want an ordinary static library, and only the one shipped in
the wheel needs to be shared. Callers that do not pass SHARED are unaffected,
and the whole change is gated on the existing EXECUTORCH_BUILD_SHARED option,
so iOS, Android, and embedded builds keep linking static libraries exactly as
before.

Test plan:

The wheel smoke test now asserts that exactly one shipped library defines the
CPU kernels, alongside the existing backend-registry and thread-pool
assertions, so a change that reintroduces a second copy fails in CI rather than
aborting at startup with a duplicate operator registration. The symbol used by
the assertion was confirmed to exist in the shipped libraries first, so the
check cannot pass by matching nothing.

Built the wheel from a clean checkout and verified against a fresh virtual
environment with a normal dependency-resolving install:

  • The wheel ships the kernels as their own versioned library next to the
    runtime and the thread pool.
  • nm -DC across every shipped shared object shows exactly one definition of a
    representative CPU operator, in the new library rather than in the bindings
    extension.
  • The backend-registry and thread-pool assertions still hold with the new
    library loaded.
  • import executorch, the registered backend list, and .pte execution
    through the Python bindings are unchanged, with outputs matching eager
    PyTorch.
  • With EXECUTORCH_BUILD_SHARED off, the kernels remain a static library and
    no new shared object is produced, so every build that does not opt in is
    unaffected.

[ghstack-poisoned]
@pytorch-bot

pytorch-bot Bot commented Jul 31, 2026

Copy link
Copy Markdown

🔗 Helpful Links

🧪 See artifacts and rendered test results at hud.pytorch.org/pr/pytorch/executorch/21524

Note: Links to docs will display an error until the docs builds have been completed.

❌ 2 New Failures, 466 Pending

As of commit de364f8 with merge base d632341 (image):

NEW FAILURES - The following jobs have failed:

This comment was automatically generated by Dr. CI and updates every 15 minutes.

[ghstack-poisoned]
[ghstack-poisoned]
[ghstack-poisoned]
[ghstack-poisoned]

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR makes the merged CPU operator kernels available as a standalone shared library in the Python wheel so that (1) the pybindings extension no longer carries its own full copy of the kernels, and (2) multiple components in the same process can share a single kernel registration site instead of registering duplicates.

Changes:

  • Adds an opt-in SHARED mode to gen_operators_lib() and uses it to build optimized_native_cpu_ops_lib as a versioned shared library when EXECUTORCH_BUILD_SHARED is enabled.
  • Ships the new CPU-kernels shared library in the wheel and forces the pybindings module to retain it on the link line (so its static initializers run reliably).
  • Extends the wheel smoke test to assert that exactly one shipped shared object defines a representative CPU kernel symbol.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
tools/cmake/Codegen.cmake Adds SHARED option to gen_operators_lib() and sets SONAME/RPATH properties for shared builds.
configurations/CMakeLists.txt Builds optimized_native_cpu_ops_lib as SHARED when EXECUTORCH_BUILD_SHARED is enabled.
CMakeLists.txt Ensures the pybindings module retains the kernels shared library so it isn’t dropped by the linker.
setup.py Installs the new kernels shared library into executorch/lib/ inside the wheel.
.ci/scripts/wheel/test_cpp_sdk.py Adds a smoke test asserting only one shipped library defines a representative CPU kernel symbol.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread configurations/CMakeLists.txt
Comment thread tools/cmake/Codegen.cmake
[ghstack-poisoned]
[ghstack-poisoned]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ciflow/binaries/all Release PRs with this label will build wheels for all python versions ciflow/binaries ciflow/cuda ciflow/nightly ciflow/periodic ciflow/trunk CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants