Вызов Пардизо 6 в Python - PullRequest
1 голос
/ 01 мая 2020

Я пытаюсь использовать библиотеку разреженных решателей Pardiso 6 в Python. Проблема в том, что я не могу загрузить общий объект Pardiso (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, и они сказали мне, что мне нужно связать с оптимизированным BLAS, но у меня уже установлен MKL через conda.


Обновление 1 : я установил mkl через conda, но это не помогло. Странно, я добавил import scipy в шапку и ошибка ушла. То же самое происходит, если я добавлю import mkl. По какой-то причине, если scipy или mkl не импортированы вручную, .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

Я дважды проверил, установлен ли 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, но я понятия не имею, как ее вызвать.

Примечание : Я нашел пример в C на веб-сайте Pardiso и проверил файл .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 и /lib64 к PATH и снова запустил сценарий Python с помощью:

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

, но та же ошибка Я также попытался добавить к LD_LIBRARY_PATH, но тоже не сработало.

Ответы [ 3 ]

1 голос
/ 01 мая 2020

Pardiso 6 sparse solver зависит от функций Лапака как минимум sgetrf, которые вычисляют факторизацию LU общей матрицы A размером M на N с использованием частичного поворота с чередованием строк.

Из того, что мы читаем, libpardiso600-GNU720-X86-64.so динамически связан с общей библиотекой Lapack. Вам необходимо предоставить PATH, содержащий одну реализацию.

Перед запуском 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 

В этом случае установка может напрямую решить проблему.

0 голосов
/ 03 мая 2020

Хитрость в том, что вместо добавления местоположения зависимостей в системные PATH s необходимо явно загружать зависимости, то есть lapack, blas и gfortran в сценарии Python до загрузка библиотеки Pardiso. Кроме того, важно, чтобы вы явно передали необязательный аргумент 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)

По моему опыту, если вы находятся в среде conda с установленным mkl, вам нужно всего лишь указать gfortran в качестве зависимости, а остальные будут автоматически загружены и доступны, в этом случае установите shared_libs = ["gfortran"].

0 голосов
/ 03 мая 2020

Pardiso 6 и Intel MKL Pardiso несовместимы, так как имеют разные API. Вы можете попытаться удалить MKL из ваших системных путей, добавить OpenBLAS и попытаться связать свой пример еще раз.

...