I'm trying to use Pardiso 6 sparse solver library in Python. The problem is that I can't seem to load the Pardiso shared object (SO). Here's the error that I get when calling
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_
I'd really appreciate it if someone could shed some light on this.
PS. I already contacted Pardiso developers and they told me that I need to link against optimized BLAS, but I already have MKL installed via conda.
Update 1: I installed mkl via conda, but it didn't help. Strangely, I added import scipy to the header and the error went away. The same thing happens if I add import mkl. So, for some reason, unless scipy or mkl are manually imported, the .so doesn't know that a lapack installation exists. Anyway, now another error is thrown, which I think might be related the libgfortran library. Here's the error
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
I double-checked to see if libgfortran is installed, and indeed it is:
(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
I think something similar might be at play, i.e. the library is there but it needs to be triggered (similar to what import scipy seems to have done for liblapack, but I have no idea how I can trigger it.
Note: I found an example in C on Pardiso website and tested the .so file against it via
$ gcc pardiso_sym.c -o pardiso_sym -L . -lpardiso600-GNU720-X86-64 -llapack -fopenmp -lgfortran
$ OMP_NUM_THREADS=1 ./pardiso_sym
and it worked with no problem (with the existing libraries on my machine). So, the .so works, it's just that I don't know how to inform it of its dependencies in Python.
Update 2: Here's the output of 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)
So, I added the common path, i.e. /lib/x86_64-linux-gnu and /lib64 to PATH and ran the Python script again via:
PATH=$PATH:/lib/x86_64-linux-gnu:/lib64 python padiso_script.py
but the same error is thrown. I also tried adding to LD_LIBRARY_PATH as well, but didn't work either.
The trick is, rather than adding the location of dependencies to system
PATHs, you need to explicitly load the dependencies, i.e.lapack,blas, andgfortranin the Python script prior to loading the Pardiso library. Also, it's essential that you explicitly pass the optionalmode=ctypes.RLTD_GLOBALargument toctypes.CDLLmethod in order to make the dependencies globally accessible and hence, Pardiso can access them.In my experience, if you are inside a
condaenvironment withmklinstalled, you only need to listgfortranas dependency and the rest are automatically loaded and accessible, in which case setshared_libs = ["gfortran"].