我正在构建一个使用的库(Ubuntu 22)onnxruntime https://github.com/microsoft/onnxruntime在引擎盖下。反过来,onnxruntime
使用CUDA,动态加载一些专用的“后端”。我构建了除 CUDA 库之外的整个代码堆栈,并且没有一个库有它们的RPATH
or RUNPATH
设置(双重检查readelf -d
).
我构建了两个应用程序,一个是 C++,并直接链接到我的库。该应用程序有其RPATH
设置好,一切正常。如果我运行它LD_DEBUG=libs
我看到这样的东西(请注意,路径已被编辑,我只显示了调试输出的一小部分):
158834: calling init: .../install/bin/../lib/libonnxruntime_providers_cuda.so
158834:
158834: find library=libcudnn_ops_infer.so.8 [0]; searching
158834: search path=.../install/bin/../lib (RPATH from file .../install/bin/test)
158834: trying file=.../install/bin/../lib/libcudnn_ops_infer.so.8
158834:
158834:
158834: calling init: .../install/bin/../lib/libcudnn_ops_infer.so.8
158834:
这就是我所期待的,我很高兴。
但是,我还需要通过一些链接到它的 python 绑定来使用相同的库。为了让它工作,我需要在这种情况下设置RPATH
python 绑定(至少在我看来,它只是一个在运行时加载的共享库)。请注意,Python 可执行文件两者都没有RPATH
nor RUNPATH
放。这仅部分有效。即,RPATH
传播似乎在沿着依赖树向下移动时起作用,直到开始搜索 CUDA 库,此时它不再起作用。这是以相同的方式、相同的构建、在与上面相同的文件夹中使用相同的文件运行完全相同的 onnxruntime API。唯一的区别是 python 扩展层。这LD_DEBUG
输出看起来像这样:
159602: find library=libonnxruntime.so.1.15.1 [0]; searching
159602: search path=.../install/lib/../lib (RPATH from file .../install/lib/pyext.cpython-310-x86_64-linux-gnu.so)
159602: trying file=.../install/lib/../lib/libonnxruntime.so.1.15.1
[...]
159602: calling init: .../install/lib/pyext.cpython-310-x86_64-linux-gnu.so
159602:
159602: find library=libonnxruntime_providers_shared.so [0]; searching
159602: search path=.../install/lib/../lib (RPATH from file .../install/lib/pyext.cpython-310-x86_64-linux-gnu.so)
159602: trying file=.../install/lib/../lib/libonnxruntime_providers_shared.so
159602:
159602:
159602: calling init: .../install/lib/../lib/libonnxruntime_providers_shared.so
159602:
159602: find library=libonnxruntime_providers_cuda.so [0]; searching
159602: search path=.../install/lib/../lib (RPATH from file .../install/lib/pyext.cpython-310-x86_64-linux-gnu.so)
159602: trying file=.../install/lib/../lib/libonnxruntime_providers_cuda.so
159602:
159602: find library=libcublas.so.11 [0]; searching
159602: search cache=/etc/ld.so.cache
159602: search path=/lib/x86_64-linux-gnu/glibc-hwcaps/x86-64-v3:/lib/x86_64-linux-gnu/glibc-hwcaps/x86-64-v2:/lib/x86_64-linux-gnu/tls/haswell/x86_64:/lib/x
86_64-linux-gnu/tls/haswell:/lib/x86_64-linux-gnu/tls/x86_64:/lib/x86_64-linux-gnu/tls:/lib/x86_64-linux-gnu/haswell/x86_64:/lib/x86_64-linux-gnu/haswell:/lib/x86_64-
linux-gnu/x86_64:/lib/x86_64-linux-gnu:/usr/lib/x86_64-linux-gnu/glibc-hwcaps/x86-64-v3:/usr/lib/x86_64-linux-gnu/glibc-hwcaps/x86-64-v2:/usr/lib/x86_64-linux-gnu/tls
/haswell/x86_64:/usr/lib/x86_64-linux-gnu/tls/haswell:/usr/lib/x86_64-linux-gnu/tls/x86_64:/usr/lib/x86_64-linux-gnu/tls:/usr/lib/x86_64-linux-gnu/haswell/x86_64:/usr
/lib/x86_64-linux-gnu/haswell:/usr/lib/x86_64-linux-gnu/x86_64:/usr/lib/x86_64-linux-gnu:/lib/glibc-hwcaps/x86-64-v3:/lib/glibc-hwcaps/x86-64-v2:/lib/tls/haswell/x86_
64:/lib/tls/haswell:/lib/tls/x86_64:/lib/tls:/lib/haswell/x86_64:/lib/haswell:/lib/x86_64:/lib:/usr/lib/glibc-hwcaps/x86-64-v3:/usr/lib/glibc-hwcaps/x86-64-v2:/usr/li
b/tls/haswell/x86_64:/usr/lib/tls/haswell:/usr/lib/tls/x86_64:/usr/lib/tls:/usr/lib/haswell/x86_64:/usr/lib/haswell:/usr/lib/x86_64:/usr/lib (system search
path)
159602: trying file=/lib/x86_64-linux-gnu/glibc-hwcaps/x86-64-v3/libcublas.so.11
159602: trying file=/lib/x86_64-linux-gnu/glibc-hwcaps/x86-64-v2/libcublas.so.11
159602: trying file=/lib/x86_64-linux-gnu/tls/haswell/x86_64/libcublas.so.11
[...]
159602: calling fini: .../install/lib/../lib/libonnxruntime_providers_shared.so [0]
所以基本上libcublas
未找到(或任何其他 CUDA 库),触发后备机制onnxruntime
避免使用 CUDA。
为什么RPATH
传播适用于 C++ 应用程序但不适用于 Python 扩展?我是否遗漏了一些愚蠢的东西,或者它与如何在 python 会话上下文中加载库密切相关?难道是bug的奇怪表现onnxruntime
,也许做错了什么dlopen
?
请注意,Python 版本中似乎也存在同样的问题onnxruntime
本身:他们的setup.py
确保所有依赖项均已预加载 https://github.com/microsoft/onnxruntime/blob/347c963d5cdbc180980d9a7758ca6aab46da5b52/setup.py#L154, using ctypes.CDLL
with RTLD_GLOBAL
.