mirror of
https://github.com/pytorch/pytorch.git
synced 2025-10-21 05:34:18 +08:00
Summary: Pull Request resolved: https://github.com/pytorch/pytorch/pull/58117 Previously it was not possible to load C extension modules with deploy because extension modules need to link against the Python.h API functions. Since each libtorchdeploy_interpreter.so had its own copy of these functions, it is not possible to tell dlopen to resolve symbols in a loaded SO from one of these libraries without exposing its symbols globally. This patch adds a custom ELF loader which does the custom loading of attaching c extension libraries to the Python API that loaded the shared library. Simple use of numpy and regex modules appears to work. This diff has some limitations: * 64-bit Linux only. OSX and windows use different formats for shared libraries. 32-bit ELF files are not supported. * debug info is not immediately availiable to debuggers. A script for lldb is provided which can be loaded so that lldb knows about the libraries as they are loaded. * shared libraries can directly use the Python API, but libraries they depend on (via DT_NEEDED entries in their dynamic segment) may not use Python. In the future, we can try to detect whether a sub library uses the Python API and load it with our customer loader. * TLS initialization and library initialization may occur in a different order than what would happen with dlopen, potentially leading to some issues running destructors in TLS segments. Use of this C++ features is relatively rare. Test Plan: Imported from OSS Reviewed By: suo Differential Revision: D28435305 Pulled By: zdevito fbshipit-source-id: 10f046053dd1d250e3c73f2cce8eb945eeba31b6
27 lines
976 B
Python
27 lines
976 B
Python
# this is imported by test_deploy to do some checks in python
|
|
import sys
|
|
import subprocess
|
|
from pathlib import Path
|
|
|
|
# we've taken steps to clear out the embedded python environment,
|
|
# so we have to go searching for real python to figure out where its libraries are installed.
|
|
def python_path(cpath):
|
|
for maybe in cpath.split(':'):
|
|
candidate = Path(maybe) / "python"
|
|
if candidate.exists():
|
|
cmd = [str(candidate), '-c', 'import sys; print(":".join(sys.path))']
|
|
return subprocess.check_output(cmd).decode('utf-8').strip('\n').split(':')
|
|
raise RuntimeError('could not find real python')
|
|
|
|
def setup(path):
|
|
sys.path.extend(python_path(path))
|
|
sys.path.append('build/lib') # for our test python extension
|
|
|
|
# smoke test the numpy extension loading works
|
|
def numpy_test(x):
|
|
import numpy as np
|
|
xs = [np.array([x, x]), np.array([x, x])]
|
|
for i in range(10):
|
|
xs.append(xs[-1] + xs[-2])
|
|
return int(xs[-1][0])
|