Skip to content

Import profiling and threadpool test helpers from the extension module - #22032

Closed
shoumikhin wants to merge 1 commit into
mainfrom
pybindings-test-imports
Closed

Import profiling and threadpool test helpers from the extension module#22032
shoumikhin wants to merge 1 commit into
mainfrom
pybindings-test-imports

Conversation

@shoumikhin

Copy link
Copy Markdown
Contributor

Background: what portable_lib is actually for

ExecuTorch can build its Python extension against two different kernel sets, and this is a documented concept (see ATen mode in docs/source/concepts.md):

portable kernels   ExecuTorch's own small tensor type (ETensor mode)
ATen kernels       PyTorch's full at::Tensor (ATen mode)

portable_lib is the entry point for the first, and aten_lib is the entry point for the second. So portable_lib is a kernel build selector, not a general utility module.

The problem

Three tests import private helpers from portable_lib that have nothing to do with choosing a kernel build:

profiler/test/test_profiler_e2e.py            _create_profile_block, _dump_profile_results,
                                              _reset_profile_results
extension/llm/custom_ops/test_sdpa_with_kv_cache.py   _unsafe_reset_threadpool
extension/llm/custom_ops/test_quantized_sdpa.py       _unsafe_reset_threadpool

None of these three ever reference aten_lib or a kernel mode. They have no fallback and no choice, so importing portable_lib already pinned them to the portable build. The import suggests a kernel-build decision that the tests do not actually make.

The change

Import those helpers from the extension module directly. That is the same build these tests were already getting, stated plainly instead of implied. Build dependencies are updated to match.

-from executorch.extension.pybindings.portable_lib import _unsafe_reset_threadpool
+from executorch.extension.pybindings._C import _unsafe_reset_threadpool

What is deliberately left alone

Two other tests keep importing portable_lib, because they use it for exactly what it is for: they try portable_lib, fall back to aten_lib, and record which kernel build they got.

try:
    from executorch.extension.pybindings import portable_lib as runtime
    kernel_mode = "portable"
except Exception:
    from executorch.extension.pybindings import aten_lib as runtime
    kernel_mode = "aten"

Those are correct as written and are not touched here.

Test plan

No behaviour change, verified rather than assumed:

  • All five imported names are declared in the extension's type stub (pybindings.pyi).
  • torch is imported before the extension in all three files, which the extension needs in order to load its dependencies.
  • None of the three reference aten_lib or a kernel mode, so no kernel selection behaviour changes.
  • black, flake8 and usort clean.

Not verified locally: running these tests needs a compiled extension, which is not available on the machine this was prepared on. Left to CI.

Three tests import a handful of private helpers, for profiling and for resetting the
threadpool, from portable_lib. Those helpers are not part of what portable_lib is for.
portable_lib exists to select the portable kernel build, as opposed to aten_lib, which
selects the ATen kernel build. None of these three tests make that choice: they never
reference aten_lib or a kernel mode, so importing portable_lib already fixed them to the
portable build.

Import the helpers from the extension module directly, which is the same build these
tests were already getting, and says so plainly. Build dependencies are updated to match.

No behaviour change. Every imported name is declared in the extension's type stub, and
each of these files already imports torch before the extension, which the extension
needs in order to load.

Two other tests keep importing portable_lib, because they use it the way it is meant to
be used: they try portable_lib and fall back to aten_lib to pick a kernel build at
runtime.

Test plan:
- Confirmed all five imported names are declared in the extension type stub.
- Confirmed torch is imported before the extension in all three files.
- Confirmed none of the three reference aten_lib or a kernel mode, so no kernel selection
  behaviour is being changed.
- black, flake8 and usort clean.
Copilot AI lite review requested due to automatic review settings August 21, 2026 20:05
@pytorch-bot

pytorch-bot Bot commented Aug 21, 2026

Copy link
Copy Markdown

🔗 Helpful Links

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

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

✅ You can merge normally! (7 Unrelated Failures)

As of commit 194852a with merge base 8b93850 (image):

FLAKY - The following job failed but was likely due to flakiness present on trunk:

BROKEN TRUNK - The following jobs failed but was present on the merge base:

👉 Rebase onto the `viable/strict` branch to avoid these failures

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

@meta-cla meta-cla Bot added the CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. label Aug 21, 2026

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.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@github-actions

Copy link
Copy Markdown

This PR needs a release notes: label

If your change should be included in the release notes (i.e. would users of this library care about this change?), please use a label starting with release notes:. This helps us keep track and include your important work in the next release notes.

To add a label, you can comment to pytorchbot, for example
@pytorchbot label "release notes: none"

For more information, see
https://github.com/pytorch/pytorch/wiki/PyTorch-AutoLabel-Bot#why-categorize-for-release-notes-and-how-does-it-work.

@shoumikhin

Copy link
Copy Markdown
Contributor Author

Closing this. Two independent reviews and my own follow-up checks agree it should not land, and the reasoning in the description above does not hold up.

It contradicts a change I landed the day before. d64c302 (#21816) describes _C as "the private module" and portable_lib as "the public wrapper", and moved callers toward the wrapper. This PR moves three callers the other way.

Three of the five names are documented as portable_lib's API. extension/pybindings/README.md:2 introduces "This Python module, named portable_lib", and lines 24-27 list _dump_profile_results, _create_profile_block and _reset_profile_results as its functions.

The "no behaviour change" claim was wrong. Importing _C directly skips everything portable_lib.py does first: the experimental warning (:23), OpenVINO discovery and OPENVINO_LIB_PATH (:39-60), and the Windows DLL directory call (:64-73).

And my justification for dismissing those was wrong. I checked the test sources for Windows references and found none, but pytest-windows.ini:64,66 runs two of these three tests on Windows, so the DLL step does apply. Where a test runs is decided by CI configuration, not by its contents.

One more correction: profiler/test/test_profiler_e2e.py:18 also imports _load_for_executorch_from_buffer and uses it at :59 to load a program. That is a runtime loader, not a profiling or threadpool helper, so the framing above was inaccurate.

The underlying observation is still real: the profiling and threadpool controls have no public home, since executorch.runtime exposes neither. But the fix is to give them one, not to name the private module in three more places. Closing rather than reworking.

@shoumikhin shoumikhin closed this Aug 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

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