在 Python 中调用 Pardiso 6

Calling Pardiso 6 in Python

我正在尝试在 Python 中使用 Pardiso 6 稀疏求解器库。问题是我似乎无法加载 Pardiso shared object (SO)。这是我在调用

时遇到的错误
import ctypes
pardiso = ctypes.CDLL(pardiso_so_address)
Traceback (most recent call last):
  File "test.py", line 27, in <module>
    pardiso = ctypes.CDLL(lib720)
  File "/home/amin/anaconda3/envs/idp/lib/python3.7/ctypes/__init__.py", line 364, in __init__
    self._handle = _dlopen(self._name, mode)
OSError: ./libpardiso600-GNU720-X86-64.so: undefined symbol: sgetrf_

如果有人能对此有所说明,我将不胜感激。


PS。我已经联系了 Pardiso 开发人员,他们告诉我我需要 link 针对优化的 BLAS,但我已经通过 conda.

安装了 MKL

更新 1:我通过 conda 安装了 mkl,但没有用。 St运行gely,我将 import scipy 添加到 header 并且错误消失了。如果我添加 import mkl,也会发生同样的事情。因此,出于某种原因,除非手动导入 scipymkl,否则 .so 不知道 lapack 安装存在。无论如何,现在抛出另一个错误,我认为这可能与 libgfortran 库有关。这是错误

Traceback (most recent call last):
  File "test.py", line 34, in <module>
    pardiso = ctypes.CDLL(lib720)
  File "/home/amin/anaconda3/envs/test/lib/python3.7/ctypes/__init__.py", line 364, in __init__
    self._handle = _dlopen(self._name, mode)
OSError: ./libpardiso600-GNU720-X86-64.so: undefined symbol: _gfortran_st_close

我double-checked看看是否安装了libgfortran,果然是:

(test) PyPardisoProject$ ldconfig -p | grep libgfortran
    libgfortran.so.5 (libc6,x86-64) => /lib/x86_64-linux-gnu/libgfortran.so.5
    libgfortran.so.4 (libc6,x86-64) => /lib/x86_64-linux-gnu/libgfortran.so.4

我认为类似的事情可能在起作用,即库在那里但需要被触发(类似于 import scipy 似乎为 liblapack 所做的,但我不知道我怎么触发它。

注意:我在 Pardiso 网站上找到了一个 C 语言的例子,并通过

测试了 .so 文件
$ gcc pardiso_sym.c -o pardiso_sym -L . -lpardiso600-GNU720-X86-64 -llapack -fopenmp -lgfortran
$ OMP_NUM_THREADS=1 ./pardiso_sym 

它没有问题(使用我机器上的现有库)。所以,.so 有效,只是我不知道如何在 Python.

中告知它的依赖关系

更新 2:这是 ldd pardiso_sym 的输出:

Scripts$ ldd pardiso_sym
    linux-vdso.so.1 (0x00007ffe7e982000)
    libpardiso600-GNU720-X86-64.so (0x00007f326802d000)
    liblapack.so.3 => /lib/x86_64-linux-gnu/liblapack.so.3 (0x00007f3267976000)
    libgfortran.so.4 => /lib/x86_64-linux-gnu/libgfortran.so.4 (0x00007f3267795000)
    libgomp.so.1 => /lib/x86_64-linux-gnu/libgomp.so.1 (0x00007f326775b000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f3267568000)
    libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f3267545000)
    libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f32673f6000)
    /lib64/ld-linux-x86-64.so.2 (0x00007f32685df000)
    libblas.so.3 => /lib/x86_64-linux-gnu/libblas.so.3 (0x00007f3267389000)
    libgfortran.so.5 => /lib/x86_64-linux-gnu/libgfortran.so.5 (0x00007f32670e9000)
    libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f32670cf000)
    libquadmath.so.0 => /lib/x86_64-linux-gnu/libquadmath.so.0 (0x00007f3267083000)
    libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f326707d000)

所以,我添加了公共路径,即 /lib/x86_64-linux-gnu/lib64PATH 和 运行 Python 脚本再次通过:

PATH=$PATH:/lib/x86_64-linux-gnu:/lib64 python padiso_script.py

但是报同样的错误。我也尝试添加到 LD_LIBRARY_PATH,但也没有用。

Pardiso 6 sparse solver 至少 sgetrf 依赖于 Lapack 函数,它使用带行交换的部分旋转计算一般 M×N 矩阵 A 的 LU 分解。

根据我们的阅读,libpardiso600-GNU720-X86-64.so 与共享的 Lapack 库动态链接。您需要提供一个包含一个实现的路径。

在启动 Python 之前,我建议您使用 LD_LIBRARY_PATH 并包含您正在使用的 BLAS/Lapack 库的路径。它可以是 netlib 实现、ATLAS 实现或 MKL 实现。

LD_LIRARY_PATH=$LD_LIRARY_PATH:/my_path_to_lapack \
python -c"import ctypes; pardiso = ctypes.CDLL(pardiso_so_address)"

如果使用conda,可以用命令安装

conda install -c anaconda mkl 

这种情况,安装可能直接解决问题

Pardiso 6 和 Intel MKL Pardiso 不兼容,因为它们具有不同的 API。您可以尝试从系统路径中删除 MKL,添加 OpenBLAS,然后再次尝试 link 您的示例。

诀窍是,不是将依赖项的位置添加到系统 PATHs,而是需要显式加载依赖项,即 lapackblasgfortran 在加载 Pardiso 库之前在 Python 脚本中。此外,您必须显式地将可选的 mode=ctypes.RLTD_GLOBAL 参数传递给 ctypes.CDLL 方法,以便使依赖项可以全局访问,因此 Pardiso 可以访问它们。

import ctypes
import ctypes.util

shared_libs = ["lapack", "blas", "omp", "gfortran"]
for lib in shared_libs:
    # Fetch the proper name of the dependency
    libname = ctypes.util.find_library(lib)
    # Load the dependency and make it globally accessible
    ctypes.CDLL(libname, mode=ctypes.RTLD_GLOBAL)
# Finally, load the Pardiso library
pardiso = ctypes.CDLL(pardiso_so_address)

根据我的经验,如果您在安装了 mklconda 环境中,您只需将 gfortran 列为依赖项,其余部分将自动加载和访问,在哪个案例集 shared_libs = ["gfortran"].