Repository navigation
Conversation
Signed-off-by: Pawel Gadzinski <[email protected]>
# Conflicts: # torch/csrc/stable/c/shim_function_versions.txt
🔗 Helpful Links🧪 See artifacts and rendered test results at hud.pytorch.org/pr/183323
Note: Links to docs will display an error until the docs builds have been completed. ✅ No FailuresAs of commit 575d711 with merge base dcadb9d ( This comment was automatically generated by Dr. CI and updates every 15 minutes. |
Attention! PyTorch one of the C-stable API file was changedYou MUST NOT change existing function declarations in this, as this header defines a stable C ABI. If you need to change the signature for a function, introduce a new v2 version of the function and modify code generation to target the new version of the function. |
Drop the verbose docstrings on torch_tensor_from_pyobject / torch_tensor_to_pyobject and their inline wrappers in favour of short // comments matching the rest of torch/csrc/stable. No behaviour change. Signed-off-by: Pawel Gadzinski <[email protected]>
# Conflicts: # torch/csrc/stable/c/shim_function_versions.txt
janeyx99
left a comment
There was a problem hiding this comment.
Most majorly: The main difference between this and other shims is that it requires linking with libtorch_python.so which is a new dependency every other shim does not require. Architecturally I haven't discerned yet where they should live. Do you know if any of the Python APIs would make these APIs tied with CPython?
Regardless, we would need to carve out a new section of documentation and tests for this new class of shims that depend on both libtorch_python and libtorch.
Minorly, once the above is cleared:
- Needs to be 2.14+ now
- the STABLE_SHIM_VERSION (.lintrunner.toml:1827-1830) lint need to include the file
- For missing tests. You should add tests in libtorch_agnostic_extension under 2.14, which will require adding a bit of scaffolding.
Apply Jane Xu's review comments on the stable PyObject<->Tensor shim. The header-only helpers in python_interop.h now use STABLE_TORCH_ERROR_CODE_CHECK instead of TORCH_ERROR_CODE_CHECK. The new shims are retargeted from 2.13 to 2.14: add the TORCH_VERSION_2_14_0 macro to version.h and bump the version guards in python_interop.h and c/python_shim.h (the shim_function_versions.txt entries were moved to TORCH_VERSION_2_14_0 as part of the upstream merge). Finally, register c/python_shim.h with the STABLE_SHIM_VERSION lint so the new stable C entry points are version-checked. Test Plan: Build/lint-config only change; no runtime behavior change. The feature is gated on TORCH_VERSION_2_14_0, matching the version file. Note: lintrunner was not run (not installed in this environment). Authored by Claude. Signed-off-by: Pawel Gadzinski <[email protected]>
|
|
|
@pytorchbot rebase (Need to rebase to get the lastest Docker build workflow change) |
|
@pytorchbot started a rebase job onto refs/remotes/origin/viable/strict. Check the current status here |
|
Rebase failed due to Command |
The PyObject<->Tensor conversion shims added for 2.14 are the first stable shims that depend on libtorch_python rather than only libtorch. Give them a dedicated subdirectory so that dependency is explicit and separated from the libtorch-only stable ABI: c/python_shim.h -> python/c/shim.h, python_interop.h -> python/interop.h, and python_shim.cpp -> python/shim.cpp, with build_variables.bzl and the STABLE_SHIM_VERSION lint updated to match. Test Plan: Path-only refactor; the tree builds and the shim symbol is exported (verified in the follow-up commit). lintrunner was not run (not installed in this environment). Authored by Claude. Signed-off-by: Pawel Gadzinski <[email protected]>
a764ba3 to
019ae5a
Compare
Adds libtorch_python_interop_2_14, an abi3 (py_limited_api) test extension that
links torch_python and exercises torch::stable::from_pyobject / to_pyobject.
Because these shims depend on both libtorch and libtorch_python and require the
GIL, they form a separate class from the libtorch-only libtorch_agn_* family:
this extension links torch_python, is imported as a module, and exposes
PyMethodDef functions (entered from Python with the GIL held) rather than
torch.ops ops, which the dispatcher may run with the GIL released. It gets its
own test file (test_libtorch_python_interop.py) and a section in the stable-ABI
docs.
Test Plan:
Built a CPU torch at 2.14 on the workstation and ran:
python -m pytest test/cpp_extensions/test_libtorch_python_interop.py -v
Result: 4 passed -- round-trip shares storage, to_pyobject with an explicit
py_type (torch.nn.Parameter), real work on the tensor (torch::stable::sum), and
a non-tensor input raising. Confirmed the built _C.so is abi3 (named _C.so, no
cpXXX suffix), links libtorch_python, and resolves torch_tensor_from_pyobject /
torch_tensor_to_pyobject from it.
Authored by Claude.
Signed-off-by: Pawel Gadzinski <[email protected]>
torch_tensor_from_pyobject / to_pyobject touch Python objects, so calling them
without the GIL is undefined behavior. Add a PyGILState_Check() assertion to each
so misuse (for example calling from a boxed STABLE_TORCH_LIBRARY op whose kernel
the dispatcher may run with the GIL released) fails with a clear error instead of
a data race. The check runs in libtorch_python and does not itself require the
GIL.
Test Plan:
Rebuilt torch at 2.14 and reran:
python -m pytest test/cpp_extensions/test_libtorch_python_interop.py -v
Result: 4 passed. The extension calls the shims from Python-entered PyMethodDef
functions, so the GIL is held and the assertions pass.
Authored by Claude.
Signed-off-by: Pawel Gadzinski <[email protected]>
The stable-ABI note points at external, pinned examples (e.g. the FA3 repo), not internal test files. Remove the "runnable example see test/cpp_extensions/..." pointer, which was the only such reference and would rot if the tests move. Test Plan: docs-only change. Authored by Claude. Signed-off-by: Pawel Gadzinski <[email protected]>
|
Thanks @janeyx99! Agreed this is a new kind of shim and needs a clear place to live. For now I moved it into a separate On your question about whether the Python APIs tie this to CPython — for the user side, they don't:
The one thing these give up compared to the rest of the stable ABI is running without Python at all (libtorch-only). They need For the docs I added a "Python interop shims" section in For the tests I added a separate test extension and test file rather than reusing the
Please let me know what do you think. |
|
@pytorchbot merge -r |
|
@pytorchbot started a rebase job onto refs/remotes/origin/viable/strict. Check the current status here |
|
Rebase failed due to Command |
|
@pytorchbot merge |
Merge startedYour change will be merged once all checks pass (ETA 0-4 Hours). Learn more about merging in the wiki. Questions? Feedback? Please reach out to the PyTorch DevX Team |
Merge failedReason: 3 mandatory check(s) failed. The first few are: Dig deeper by viewing the failures on hud |
|
@pytorchbot merge |
Merge startedYour change will be merged once all checks pass (ETA 0-4 Hours). Learn more about merging in the wiki. Questions? Feedback? Please reach out to the PyTorch DevX Team |
Follow-up to pytorch#183323, which introduced the PyObjectConversionInterface vtable so libtorch-only stable shims can convert PyObjects using functionality that lives in libtorch_python. This extends the same mechanism (no new machinery) with torch.dtype <-> ScalarType and torch.device <-> Device conversions, which python-registered custom ops need alongside tensors. Review in the order the pieces fit together: the vtable interface and its erroring no-op default (torch/csrc/PyObjectConversion.{h,cpp}), the concrete THPDtype/THPDevice-based implementation in libtorch_python (torch/csrc/PyObjectConversionPythonImpl.cpp), the C shims (torch/csrc/shim_common.cpp, torch/csrc/stable/c/shim.h, shim_function_versions.txt; all versioned at 2.14), the header-only helpers (torch/csrc/stable/pyobject.h), then tests and docs. Unlike the tensor shims there is no handle type: a dtype crosses the ABI boundary as the int32_t code already used by aoti_torch_dtype_*(), and a device as (device_type, device_index) int32_t in the aoti_torch_device_type_*() encoding, matching how aoti_torch_get_dtype / _get_device_type / _get_device_index encode them. The pyobject.h helpers translate the codes through torch::stable::detail::from/to like Tensor::scalar_type() / Tensor::device(), so extension-side and libtorch-side enum values stay decoupled. Test Plan: Minimal CPU build (BUILD_TEST=1, PYTORCH_BUILD_VERSION=2.14.0a0) on a linux workstation; all touched TUs recompiled and torch imports: ``` pip install -e . -v --no-build-isolation ``` Libtorch-only no-op fallback (links libtorch, not libtorch_python): ``` ./build/bin/test_shim --gtest_filter="TorchPyObjectConversion.*" ``` 3 tests pass. Extension-side interop tests (rebuilt libtorch_agn_2_14): ``` cd test/cpp_extensions/libtorch_agn_2_14_extension && pip install -e . -v --no-build-isolation cd .. && python -m pytest test_libtorch_agnostic.py -q -k "pyobject" ``` 9 passed (5 new: dtype/device roundtrips incl. float8 and cuda:1, tensor_dtype/tensor_device end to end, non-dtype/non-device error cases). lintrunner (CLANGFORMAT, RUFF, PYFMT, ...) and the STABLE_SHIM_VERSION / STABLE_SHIM_USAGE adapters are clean on all touched files. This PR was authored with the help of an AI assistant (Claude). Signed-off-by: Pawel Gadzinski <[email protected]>
Follow-up to pytorch#183323, which introduced the PyObjectConversionInterface vtable so libtorch-only stable shims can convert PyObjects using functionality that lives in libtorch_python. This extends the same mechanism (no new machinery) with torch.dtype <-> ScalarType and torch.device <-> Device conversions, which python-registered custom ops need alongside tensors. Review in the order the pieces fit together: the vtable interface and its erroring no-op default (torch/csrc/PyObjectConversion.{h,cpp}), the concrete THPDtype/THPDevice-based implementation in libtorch_python (torch/csrc/PyObjectConversionPythonImpl.cpp), the C shims (torch/csrc/shim_common.cpp, torch/csrc/stable/c/shim.h, shim_function_versions.txt; all versioned at 2.14), the header-only helpers (torch/csrc/stable/pyobject.h), then tests and docs. Unlike the tensor shims there is no handle type: a dtype crosses the ABI boundary as the int32_t code already used by aoti_torch_dtype_*(), and a device as (device_type, device_index) int32_t in the aoti_torch_device_type_*() encoding, matching how aoti_torch_get_dtype / _get_device_type / _get_device_index encode them. The pyobject.h helpers translate the codes through torch::stable::detail::from/to like Tensor::scalar_type() / Tensor::device(), so extension-side and libtorch-side enum values stay decoupled. Test Plan: Minimal CPU build (BUILD_TEST=1, PYTORCH_BUILD_VERSION=2.14.0a0) on a linux workstation; all touched TUs recompiled and torch imports: ``` pip install -e . -v --no-build-isolation ``` Libtorch-only no-op fallback (links libtorch, not libtorch_python): ``` ./build/bin/test_shim --gtest_filter="TorchPyObjectConversion.*" ``` 3 tests pass. Extension-side interop tests (rebuilt libtorch_agn_2_14): ``` cd test/cpp_extensions/libtorch_agn_2_14_extension && pip install -e . -v --no-build-isolation cd .. && python -m pytest test_libtorch_agnostic.py -q -k "pyobject" ``` 9 passed (5 new: dtype/device roundtrips incl. float8 and cuda:1, tensor_dtype/tensor_device end to end, non-dtype/non-device error cases). lintrunner (CLANGFORMAT, RUFF, PYFMT, ...) and the STABLE_SHIM_VERSION / STABLE_SHIM_USAGE adapters are clean on all touched files. This PR was authored with the help of an AI assistant (Claude). Signed-off-by: Pawel Gadzinski <[email protected]>
Follow-up to pytorch#183323, which introduced the PyObjectConversionInterface vtable so libtorch-only stable shims can convert PyObjects using functionality that lives in libtorch_python. This extends the same mechanism (no new machinery) with torch.dtype <-> ScalarType and torch.device <-> Device conversions, which python-registered custom ops need alongside tensors. Review in the order the pieces fit together: the vtable interface and its erroring no-op default (torch/csrc/PyObjectConversion.{h,cpp}), the concrete THPDtype/THPDevice-based implementation in libtorch_python (torch/csrc/PyObjectConversionPythonImpl.cpp), the C shims (torch/csrc/shim_common.cpp, torch/csrc/stable/c/shim.h, shim_function_versions.txt; all versioned at 2.14), the header-only helpers (torch/csrc/stable/pyobject.h), then tests and docs. Unlike the tensor shims there is no handle type: a dtype crosses the ABI boundary as the int32_t code already used by aoti_torch_dtype_*(), and a device as (device_type, device_index) int32_t in the aoti_torch_device_type_*() encoding, matching how aoti_torch_get_dtype / _get_device_type / _get_device_index encode them. The pyobject.h helpers translate the codes through torch::stable::detail::from/to like Tensor::scalar_type() / Tensor::device(), so extension-side and libtorch-side enum values stay decoupled. Test Plan: Minimal CPU build (BUILD_TEST=1, PYTORCH_BUILD_VERSION=2.14.0a0) on a linux workstation; all touched TUs recompiled and torch imports: ``` pip install -e . -v --no-build-isolation ``` Libtorch-only no-op fallback (links libtorch, not libtorch_python): ``` ./build/bin/test_shim --gtest_filter="TorchPyObjectConversion.*" ``` 3 tests pass. Extension-side interop tests (rebuilt libtorch_agn_2_14): ``` cd test/cpp_extensions/libtorch_agn_2_14_extension && pip install -e . -v --no-build-isolation cd .. && python -m pytest test_libtorch_agnostic.py -q -k "pyobject" ``` 9 passed (5 new: dtype/device roundtrips incl. float8 and cuda:1, tensor_dtype/tensor_device end to end, non-dtype/non-device error cases). lintrunner (CLANGFORMAT, RUFF, PYFMT, ...) and the STABLE_SHIM_VERSION / STABLE_SHIM_USAGE adapters are clean on all touched files. This PR was authored with the help of an AI assistant (Claude). Signed-off-by: Pawel Gadzinski <[email protected]>
…be (2.15+) (#192774) Follow-up to #183323, extending the Python interop shims with dtype/device conversions and a tensor type-check probe, using the same `PyObjectConversionInterface` vtable mechanism (no new machinery). ## Summary - Add `torch::stable::dtype_from_pyobject` and `dtype_to_pyobject` for converting between `torch.dtype` and `torch::headeronly::ScalarType`. - Add `torch::stable::device_from_pyobject` and `device_to_pyobject` for converting between `torch.device` and `torch::stable::Device`. - Add `torch::stable::is_tensor_pyobject` for checking whether an object’s actual C-level type is `torch.Tensor` or a genuine subclass. - It deliberately ignores spoofed `__class__` attributes. - It uses the same structural check as `tensor_from_pyobject`, making it safe as a conversion guard. - Add the corresponding stable C shims, versioned for PyTorch 2.15. - Dtypes cross the ABI as the existing `int32_t` `ScalarType` encoding. - Devices cross as an `int32_t` device type and index, with `-1` representing no index. - Inputs are validated before narrowing to the internal enum representations. - Implement the conversions in `libtorch_python` through the existing `PyObjectConversionInterface` vtable. Extensions continue to link only against `libtorch`, but `libtorch_python` must be loaded and the GIL must be held. - Translate dtype and device values through the stable enum mappings. Valid Python values outside the supported stable subset produce an explicit error. - Document reference ownership, GIL requirements, runtime requirements, and the supported conversion behavior. ## Release targeting These APIs are intentionally marked `TORCH_VERSION_2_15_0` because this change will be cherry-picked into the 2.15 release branch. ## Test plan - [x] `python -m pytest test/cpp_extensions/test_libtorch_agnostic.py -k pyobject -v` — parametrized roundtrips (7 dtypes incl. float8; cpu/meta/cuda/cuda:1 devices, incl. an index-less device that must not come back as cuda:0), end-to-end `Tensor::scalar_type()`/`device()` -> Python object, the probe on tensors / a tensor subclass / non-tensors, error cases for non-dtype/non-device inputs - [x] `test_shim --gtest_filter="TorchPyObjectConversion.*"` — 6 tests: no-op fallback returns `AOTI_TORCH_FAILURE` (not a crash) without libtorch_python, and out-of-range dtype/device codes are rejected with clear errors --- _This PR was prepared with the help of Claude._ Pull Request resolved: #192774 Approved by: https://github.com/janeyx99 Co-authored-by: Claude Fable 5 <[email protected]> Co-authored-by: Jane Xu <[email protected]>
…be (2.15+) (#200183) Add stable dtype and device PyObject conversions and an is_tensor probe (2.15+) (#192774) Follow-up to #183323, extending the Python interop shims with dtype/device conversions and a tensor type-check probe, using the same `PyObjectConversionInterface` vtable mechanism (no new machinery). ## Summary - Add `torch::stable::dtype_from_pyobject` and `dtype_to_pyobject` for converting between `torch.dtype` and `torch::headeronly::ScalarType`. - Add `torch::stable::device_from_pyobject` and `device_to_pyobject` for converting between `torch.device` and `torch::stable::Device`. - Add `torch::stable::is_tensor_pyobject` for checking whether an object’s actual C-level type is `torch.Tensor` or a genuine subclass. - It deliberately ignores spoofed `__class__` attributes. - It uses the same structural check as `tensor_from_pyobject`, making it safe as a conversion guard. - Add the corresponding stable C shims, versioned for PyTorch 2.15. - Dtypes cross the ABI as the existing `int32_t` `ScalarType` encoding. - Devices cross as an `int32_t` device type and index, with `-1` representing no index. - Inputs are validated before narrowing to the internal enum representations. - Implement the conversions in `libtorch_python` through the existing `PyObjectConversionInterface` vtable. Extensions continue to link only against `libtorch`, but `libtorch_python` must be loaded and the GIL must be held. - Translate dtype and device values through the stable enum mappings. Valid Python values outside the supported stable subset produce an explicit error. - Document reference ownership, GIL requirements, runtime requirements, and the supported conversion behavior. ## Release targeting These APIs are intentionally marked `TORCH_VERSION_2_15_0` because this change will be cherry-picked into the 2.15 release branch. ## Test plan - [x] `python -m pytest test/cpp_extensions/test_libtorch_agnostic.py -k pyobject -v` — parametrized roundtrips (7 dtypes incl. float8; cpu/meta/cuda/cuda:1 devices, incl. an index-less device that must not come back as cuda:0), end-to-end `Tensor::scalar_type()`/`device()` -> Python object, the probe on tensors / a tensor subclass / non-tensors, error cases for non-dtype/non-device inputs - [x] `test_shim --gtest_filter="TorchPyObjectConversion.*"` — 6 tests: no-op fallback returns `AOTI_TORCH_FAILURE` (not a crash) without libtorch_python, and out-of-range dtype/device codes are rejected with clear errors --- _This PR was prepared with the help of Claude._ Pull Request resolved: #192774 Approved by: https://github.com/janeyx99 (cherry picked from commit 6d0ba1a) Co-authored-by: Pawel Gadzinski <[email protected]> Co-authored-by: Claude Fable 5 <[email protected]> Co-authored-by: Jane Xu <[email protected]>
…be (2.15+) (pytorch#192774) Follow-up to pytorch#183323, extending the Python interop shims with dtype/device conversions and a tensor type-check probe, using the same `PyObjectConversionInterface` vtable mechanism (no new machinery). ## Summary - Add `torch::stable::dtype_from_pyobject` and `dtype_to_pyobject` for converting between `torch.dtype` and `torch::headeronly::ScalarType`. - Add `torch::stable::device_from_pyobject` and `device_to_pyobject` for converting between `torch.device` and `torch::stable::Device`. - Add `torch::stable::is_tensor_pyobject` for checking whether an object’s actual C-level type is `torch.Tensor` or a genuine subclass. - It deliberately ignores spoofed `__class__` attributes. - It uses the same structural check as `tensor_from_pyobject`, making it safe as a conversion guard. - Add the corresponding stable C shims, versioned for PyTorch 2.15. - Dtypes cross the ABI as the existing `int32_t` `ScalarType` encoding. - Devices cross as an `int32_t` device type and index, with `-1` representing no index. - Inputs are validated before narrowing to the internal enum representations. - Implement the conversions in `libtorch_python` through the existing `PyObjectConversionInterface` vtable. Extensions continue to link only against `libtorch`, but `libtorch_python` must be loaded and the GIL must be held. - Translate dtype and device values through the stable enum mappings. Valid Python values outside the supported stable subset produce an explicit error. - Document reference ownership, GIL requirements, runtime requirements, and the supported conversion behavior. ## Release targeting These APIs are intentionally marked `TORCH_VERSION_2_15_0` because this change will be cherry-picked into the 2.15 release branch. ## Test plan - [x] `python -m pytest test/cpp_extensions/test_libtorch_agnostic.py -k pyobject -v` — parametrized roundtrips (7 dtypes incl. float8; cpu/meta/cuda/cuda:1 devices, incl. an index-less device that must not come back as cuda:0), end-to-end `Tensor::scalar_type()`/`device()` -> Python object, the probe on tensors / a tensor subclass / non-tensors, error cases for non-dtype/non-device inputs - [x] `test_shim --gtest_filter="TorchPyObjectConversion.*"` — 6 tests: no-op fallback returns `AOTI_TORCH_FAILURE` (not a crash) without libtorch_python, and out-of-range dtype/device codes are rejected with clear errors --- _This PR was prepared with the help of Claude._ Pull Request resolved: pytorch#192774 Approved by: https://github.com/janeyx99 Co-authored-by: Claude Fable 5 <[email protected]> Co-authored-by: Jane Xu <[email protected]>
Keeps the 2.3 lower bound (required for the AOTI metadata functions).
The dispatch in _tensor_bridge.view_as_torch_tensor now picks between:
* torch >= 2.14 -- stable torch_tensor_from_pyobject shim
(pytorch/pytorch#183323; part of torch's stable C ABI contract)
* torch 2.3 - 2.13 -- pyobj_to_aten_handle pointer-arithmetic,
validated against the two known THPVariable layouts
Future torch releases >= 2.14 are automatically covered by the shim,
removing the per-release cap bump treadmill.
…ersion cap (#3033) * cuda.core: bump torch tensor-bridge upper cap to 2.14 * cuda.core: use torch 2.14+ stable PyObject->Tensor shim as primary path PyTorch >= 2.14 exposes torch_tensor_from_pyobject / aoti_torch_delete_tensor_object as part of the stable C ABI (landed via pytorch/pytorch#183323). These let us obtain an AtenTensorHandle from a Python tensor object without peering at THPVariable's internal layout. Dispatch is driven by *symbol presence* via dlsym / GetProcAddress on first call to view_as_torch_tensor: - resolved -> primary path (owned handle, deleted after metadata reads) - NULL -> fall back to the existing pyobj_to_aten_handle pointer-arithmetic trick, which stays correct for torch 2.3-2.13 (the only versions where this matters). The outer version gate in _memoryview.pyx (``2.3 <= torch <= 2.14``) is unchanged -- it still bounds the fallback. Once we drop support for torch < 2.14 we can remove the upper bound entirely because the shim itself is part of torch's stable ABI contract. Diagnostics kept module-private: - _get_pyobj_path_counts() / _reset_pyobj_path_counts() - _get_shim_available() - _set_use_shim(bool) to force the fallback for A/B benchmarking. * cuda.core: drop benchmark toggle and path counters from tensor bridge * cuda.core: drop upper torch version cap, shim covers 2.14+ Keeps the 2.3 lower bound (required for the AOTI metadata functions). The dispatch in _tensor_bridge.view_as_torch_tensor now picks between: * torch >= 2.14 -- stable torch_tensor_from_pyobject shim (pytorch/pytorch#183323; part of torch's stable C ABI contract) * torch 2.3 - 2.13 -- pyobj_to_aten_handle pointer-arithmetic, validated against the two known THPVariable layouts Future torch releases >= 2.14 are automatically covered by the shim, removing the per-release cap bump treadmill. * cuda.core: regenerate _tensor_bridge.pyi for the new ctypedefs
Hi,
I would like to propose a PR adding conversions from a Python object to
torch::stable::Tensorand vice versa.Motivation
I work on the Transformer Engine
project. We want to use the torch stable ABI, but we cannot do it in the
recommended way of registering a custom op in libtorch. There are 2 issues:
of our design),
functions (especially with complex fusions).
So we would like to do something like this:
convert them into stable tensors.
Approach
The two shims (
torch_tensor_from_pyobject/torch_tensor_to_pyobject) livein libtorch, but the actual
PyObject <-> at::Tensorconversion needsTHPVariable_*, which lives in libtorch_python. To bridge that without libtorchdepending on libtorch_python (or on
Python.h), the PR mirrors the existingc10::impl::PyInterpreterVTableindirection:PyObjectConversionInterface) plus a no-op default in libtorch,reachable through a global pointer;
THPVariable_Unpack/THPVariable_Wrap, registered into libtorch at load time via static init (andreset to the no-op on teardown);
AtenTensorHandleand forward towhatever implementation is currently installed.
AtenTensorHandleis confinedto the shim layer; the vtable itself works in
at::Tensor.If libtorch_python is not loaded (e.g. a libtorch-only process), the no-op is
still installed and both shims return
AOTI_TORCH_FAILUREwith a clear messageinstead of crashing (covered by a libtorch-only gtest).
A new class of shims
Existing stable-ABI shims are self-contained in libtorch. These are the first
shims that reach up from libtorch into libtorch_python for functionality that
only exists there (the CPython-facing tensor wrapper), using the vtable
indirection to keep the layering intact. The same mechanism can host future
Python-interop shims.
This PR was prepared with the help of Claude Opus.