我正在构建一个使用onnxruntime
的库(Ubuntu 22)。反过来,onnxruntime
使用CUDA,动态加载一些专用的“后端”。我构建了除CUDA库之外的整个代码栈,没有一个库设置了RPATH
或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绑定来使用同一个库。为了让它工作,我需要在本例中设置python绑定的RPATH
(至少在我的理解中,它只是一个在运行时加载的共享库)。请注意,Python可执行文件既没有设置RPATH
也没有设置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会话的上下文中加载库有很深的关系?这可能是onnxruntime
中的bug的奇怪表现,也许是dlopen
做错了什么?
请注意,在onnxruntime
本身的Python版本中似乎存在相同的问题:他们的setup.py
确保所有依赖项都是预加载的,使用ctypes.CDLL
和RTLD_GLOBAL
。
1条答案
按热度按时间ddrv8njm1#
点击此链接:https://wiki.debian.org/RpathIssue。动态链接器
ld
将在以下位置查找匹配的库:1.导致查找的库的DT_RPATH动态节属性
1.可执行文件的DT_RPATH动态节属性
1.可执行文件的DT_RUNPATH动态节属性
1./etc/ld.so.cache
1.基本库目录(/lib和/usr/lib)
在你的例子中:
因此,要使libonnxruntime加载libcu,您还必须在libonnxruntime上设置RPATH(以便应用规则1)。
为了帮助调试,可以使用
lddtree
工具(apt install pax-utils
)来获得lib依赖关系的层次视图。