Ссылка ATLAS/MKL на установленный Numpy

TL;DR как связать ATLAS/MKL с существующим Numpy без перестройки.

Я использовал Numpy для расчета с большой матрицей и обнаружил, что он очень медленный, потому что Numpy использует только 1 ядро ​​для выполнения расчетов. После долгих поисков я понял, что мой Numpy не связан с какой-то оптимизированной библиотекой, такой как ATLAS/MKL. Вот мой конфиг numpy:

>>>import numpy as np
>>>np.__config__.show()
blas_info:
    libraries = ['blas']
    library_dirs = ['/usr/lib']
    language = f77
lapack_info:
    libraries = ['lapack']
    library_dirs = ['/usr/lib']
    language = f77
atlas_threads_info:
    NOT AVAILABLE
blas_opt_info:
    libraries = ['blas']
    library_dirs = ['/usr/lib']
    language = f77
    define_macros = [('NO_ATLAS_INFO', 1)]
atlas_blas_threads_info:
  NOT AVAILABLE
openblas_info:
  NOT AVAILABLE
lapack_opt_info:
    libraries = ['lapack', 'blas']
    library_dirs = ['/usr/lib']
    language = f77
    define_macros = [('NO_ATLAS_INFO', 1)]
atlas_info:
  NOT AVAILABLE
lapack_mkl_info:
  NOT AVAILABLE
blas_mkl_info:
  NOT AVAILABLE
atlas_blas_info:
  NOT AVAILABLE
mkl_info:
  NOT AVAILABLE

По этой причине я хочу связать ATLAS/MKL с Numpy. Тем не менее, мой Numpy устанавливается из PIP, поэтому я не хочу устанавливать вручную, потому что я хочу использовать последнюю версию. Я сделал некоторые поиски, но они только для строительства с нуля. По этой причине мой вопрос таков:

  • Есть ли способ связать ATLAS/MKL с Numpy без повторной сборки?
  • Я обнаружил, что информация о конфигурации сохраняется в _config_.py в установленной папке Numpy. Так решит ли это изменение моей проблемы? Если да, не могли бы вы показать мне, как?

2 ответа

Решение

Предполагая, что вы работаете с Linux, вы можете сделать это одним из способов:

  1. Узнайте, с какой библиотекой BLAS в настоящее время связана numpy ldd,

    • Для версий numpy старше v1.10:

      $ ldd /<path_to_site-packages>/numpy/core/_dotblas.so
      

      Например, если я установлю NumPy через apt-get, это ссылки на

      ...
      libblas.so.3 => /usr/lib/libblas.so.3 (0x00007fed81de8000)
      ...
      

      Если _dotblas.so не существует, это, вероятно, означает, что numpy не удалось обнаружить какие-либо библиотеки BLAS, когда он был первоначально установлен, и в этом случае он просто не создает ни один из BLAS-зависимых компонентов. Это часто случается, если вы устанавливаете NumPy с помощью pip без указания библиотеки BLAS вручную (см. ниже). Боюсь, у вас не будет другого выбора, кроме как перестроить NumPy, если вы захотите создать ссылку на внешнюю библиотеку BLAS.


    • Для numpy v1.10 и новее:

      _dotblas.so был удален из последних версий numpy, но вы должны быть в состоянии проверить зависимости multiarray.so вместо:

      $ ldd /<path_to_site-packages>/numpy/core/multiarray.so
      
  2. Установите ATLAS/MKL/OpenBLAS, если вы еще этого не сделали. Кстати, я бы определенно рекомендовал OpenBLAS вместо ATLAS - взгляните на этот ответ (хотя данные сравнительного анализа сейчас, вероятно, немного устарели).

  3. использование update-alternatives создать символическую ссылку на новую библиотеку BLAS по вашему выбору. Например, если вы установили libopenblas.so в /opt/OpenBLAS/lib, вы бы сделали:

    $ sudo update-alternatives --install /usr/lib/libblas.so.3 \
                                         libblas.so.3 \
                                         /opt/OpenBLAS/lib/libopenblas.so \
                                         50
    

    Вы можете настроить несколько символических ссылок для одной целевой библиотеки, что позволит вам вручную переключаться между несколькими установленными библиотеками BLAS.

    Например, когда я звоню $ sudo update-alternatives --config libblas.so.3 Я могу выбрать одну из 3 библиотек:

      Selection    Path                                    Priority   Status
    ------------------------------------------------------------
      0            /opt/OpenBLAS/lib/libopenblas.so         40        auto mode
      1            /opt/OpenBLAS/lib/libopenblas.so         40        manual mode
      2            /usr/lib/atlas-base/atlas/libblas.so.3   35        manual mode
    * 3            /usr/lib/libblas/libblas.so.3            10        manual mode
    

Если вам действительно нужна "новейшая" версия numpy, вы также можете взглянуть на мой ответ о компиляции numpy из исходного кода с интеграцией OpenBLAS.

Установка numpy с поддержкой BLAS с помощью pip

Как упоминалось в комментариях @tndoan, можно сделать pip уважать конкретную конфигурацию для NumPy, поместив файл конфигурации в ~/.numpy-site.cfg - см. этот ответ для более подробной информации.

Мое личное предпочтение состоит в том, чтобы настраивать и создавать NumPy вручную. Это не особенно сложно, и это дает вам лучший контроль над конфигурацией Numpy.

Ответ зависит от того, как изначально был построен NumPy. Если он был построен против BLAS и LAPACK, то, по крайней мере, нет никакого способа заставить numpy.dot использовать ATLAS/MKL позже без перестройки. Другие функции не используют numpy.dot и вы можете использовать update-alternatives изменить цели символических ссылок libblas.so.3 а также liblapack.so.3, Это потому что numpy.dot требуется CBLAS в стиле ATLAS или OpenBLAS/MKL, но не BLAS/CBLAS и LAPACK от netlib.

Я использую openSUSE, и я установил стандартный cblas-devel из netlib. Однако кажется просто невозможным заставить NumPy использовать поставляемый cblas / cblas-devel. То есть, если вы построили NumPy против netlib BLAS/LAPACK/CBLAS (как официальный пакет), то _dotblas.so (который предоставляет версию BLAS numpy.dot) не может быть построен (до 1.10), или multiarray.so (1.10 и позже) не ссылается на libblas.so.3 совсем. Смотрите проблему на github: https://github.com/numpy/numpy/issues/1265 и цитируемый отчет об ошибках Debian: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=464784. Может быть, кто-то может погрузиться в исходный код, чтобы сделать патч... В любом случае, это влияет только на одну функцию (numpy.dot) и вы всегда можете легко перестроить весь NumPy, используя более быстрый OpenBLAS, так что, вероятно, ничего страшного в конце концов.

Вывод: Вы можете связаться с ATLAS/MKL/OpenBLAS позже без перестройки, но numpy.dot будет по-прежнему очень медленным, если NumPy изначально не был построен против ATLAS/MKL/OpenBLAS (потому что numpy.dot во-первых, просто не использовал BLAS, и вы ничего не можете с этим поделать, как только компиляция будет завершена).

Обновление: На самом деле вы можете заставить NumPy построить _dotblas.so, Я сделал патч для numpy-1.9.2:

diff -Npru numpy-1.9.2.orig/numpy/core/setup.py numpy-1.9.2/numpy/core/setup.py
--- numpy-1.9.2.orig/numpy/core/setup.py        2015-02-01 11:38:25.000000000 -0500
+++ numpy-1.9.2/numpy/core/setup.py     2016-03-28 01:31:12.948885383 -0400
@@ -953,8 +953,8 @@ def configuration(parent_package='',top_
     #blas_info = {}
     def get_dotblas_sources(ext, build_dir):
         if blas_info:
-            if ('NO_ATLAS_INFO', 1) in blas_info.get('define_macros', []):
-                return None # dotblas needs ATLAS, Fortran compiled blas will not be sufficient.
+            #if ('NO_ATLAS_INFO', 1) in blas_info.get('define_macros', []):
+            #    return None # dotblas needs ATLAS, Fortran compiled blas will not be sufficient.
             return ext.depends[:3]
         return None # no extension module will be built

Теперь, когда _dotblas.so связан с libblas.so.3, ты можешь использовать update-alternatives чтобы проверить разницу.

Другие вопросы по тегам