我正在尝试使用我构建的C++共享库(libmine.so
),并使用英特尔的 MKL 库从 Java 使用 JNI。
我还创建了libminejni.so
,并从Java代码加载它,如下所示:
System.loadLibrary("minejni")
但是,它无法加载其中一个MKL库(libmkl_avx2.so
)
<path_to_lib>/libmkl_avx2.so: <path_to_lib>/libmkl_avx2.so:
undefined symbol: mkl_sparse_optimize_bsr_trsm_i8
符号在libmkl_gnu_thread.so
中定义
>nm <path_to_lib>/libmkl_gnu_thread.so | grep mkl_sparse_optimize_bsr_trsm_i8
00000000004fe240 T mkl_sparse_optimize_bsr_trsm_i8
所以我在加载有问题的库之前使用System.loadLibrary
加载了库,但错误没有解决。
我用LD_DEBUG=bindings,symbols
执行了它,发现它没有libmkl_gnu_thread.so
搜索符号。
[java] 11275: symbol=mkl_sparse_optimize_bsr_trsm_i8; lookup in file=/local/workspaces/JDK8-1.0/runtime/jdk1.8/bin/java [0]
[java] 11275: symbol=mkl_sparse_optimize_bsr_trsm_i8; lookup in file=/lib64/libpthread.so.0 [0]
[java] 11275: symbol=mkl_sparse_optimize_bsr_trsm_i8; lookup in file=/lib/amd64/jli/libjli.so [0]
[java] 11275: symbol=mkl_sparse_optimize_bsr_trsm_i8; lookup in file=/lib64/libdl.so.2 [0]
[java] 11275: symbol=mkl_sparse_optimize_bsr_trsm_i8; lookup in file=/lib64/libc.so.6 [0]
[java] 11275: symbol=mkl_sparse_optimize_bsr_trsm_i8; lookup in file=/lib64/ld-linux-x86-64.so.2 [0]
[java] 11275: symbol=mkl_sparse_optimize_bsr_trsm_i8; lookup in file=/jdk1.8/jre/lib/amd64/server/libjvm.so [0]
[java] 11275: symbol=mkl_sparse_optimize_bsr_trsm_i8; lookup in file=/lib64/libm.so.6 [0]
[java] 11275: symbol=mkl_sparse_optimize_bsr_trsm_i8; lookup in file=/lib/libmkl_avx2.so [0]
[java] 11275: symbol=mkl_sparse_optimize_bsr_trsm_i8; lookup in file=/lib64/libdl.so.2 [0]
[java] 11275: symbol=mkl_sparse_optimize_bsr_trsm_i8; lookup in file=/lib64/libc.so.6 [0]
[java] 11275: symbol=mkl_sparse_optimize_bsr_trsm_i8; lookup in file=/lib64/ld-linux-x86-64.so.2 [0]
[java] 11275: /lib/libmkl_avx2.so: error: symbol lookup error: undefined symbol: mkl_sparse_optimize_bsr_trsm_i8 (fatal)
如果我使用 C++ 创建可执行文件,该库将起作用。我想将libmkl_gnu_thread.so
添加到 ld 将搜索符号的库列表中,有人知道如何做到这一点吗?
注意:如果我将所有与MKL相关的库添加到LD_PRELOAD,它可以工作,但我正在寻找不那么黑客的方式。 注2:修改示例中的某些路径以删除个人信息。
JNI 库通过使用RTLD_LOCAL
(即默认值)调用dlopen
来加载对象。 这意味着库的符号不可用于其他dlopen
调用。 如果你在同一进程中只用RTLD_GLOBAL
一次调用dlopen
forlibmkl_gnu_thread.so
,它将被注入到全局范围内,其他库(包括那些使用RTLD_LOCAL
加载的库)可以找到它的符号。
或者,应该可以将minejni
链接到libmkl_gnu_thread.so
,以便将其加载到相同的搜索范围内。 请注意,在某些发行版上,您必须与-Wl,--no-as-neeeded
链接,以防止优化此依赖项,此时似乎不需要这种依赖关系。