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からインストールされるため、最新バージョンを使用したいので手動でインストールしたくありません。私はいくつかの検索を行いましたが、それらはゼロから構築するためのものです。このため、私の質問は次のとおりです。
ある種のLinuxを実行していると仮定すると、次の方法で実行できます。
ldd
を使用して現在BLASライブラリnumpyがリンクされているものを見つけます。
v1.10より古いnumpyのバージョンの場合:
$ ldd /<path_to_site-packages>/numpy/core/_dotblas.so
たとえば、apt-get
を使用してnumpyをインストールすると、
...
libblas.so.3 => /usr/lib/libblas.so.3 (0x00007fed81de8000)
...
_dotblas.so
が存在しない場合、これはおそらく、numpyが最初にインストールされたときにBLASライブラリを検出できなかったことを意味します。 BLASに依存するコンポーネントをビルドします。これは、BLASライブラリを手動で指定せずにpip
を使用してnumpyをインストールした場合によく発生します(以下を参照)。外部のBLASライブラリとリンクしたい場合は、numpyを再構築するしかありません。
numpy v1.10以降の場合:
_dotblas.so
はnumpyの最近のバージョンから削除されました 代わりに、multiarray.so
の依存関係を確認できるはずです:
$ ldd /<path_to_site-packages>/numpy/core/multiarray.so
ATLAS/MKL/OpenBLASをまだインストールしていない場合はインストールします。ちなみに、私はATLASよりもOpenBLASをお勧めします- この答え を見てください(ただし、ベンチマークデータはおそらく少し古くなっています)。
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の「最新」バージョンが本当に必要な場合は、 OpenBLAS統合を使用してソースからnumpyをコンパイルすることについての私の答え も参照してください。
コメントで@tndoanが述べたように、~/.numpy-site.cfg
に構成ファイルを配置することで、pip
にnumpyの特定の構成を尊重させることができます。詳細については、 この回答 を参照してください。
私の個人的な好みは、手作業でnumpyを設定してビルドすることです。これは特に難しいことではありません。numpyの構成をよりよく制御できます。
答えは、NumPyが最初にどのように構築されたかによって異なります。 BLASおよびLAPACKに対してビルドされた場合、少なくともnumpy.dot
が後で再ビルドせずにATLAS/MKLを使用するように強制する方法はありません。他の関数はnumpy.dot
を使用せず、update-alternatives
を使用してシンボリックリンクlibblas.so.3
およびliblapack.so.3
のターゲットを変更できます。これは、numpy.dot
にはATLASスタイルのCBLAS、またはOpenBLAS/MKLが必要ですが、netlibのBLAS/CBLASおよびLAPACKは必要ないためです。
OpenSUSEを使用していますが、netlibから標準のcblas-develをインストールしました。しかし、NumPyに出荷されたcblas/cblas-develを使用するように強制することは単に不可能のようです。つまり、(公式パッケージとして)netlib BLAS/LAPACK/CBLASに対してNumPyをビルドした場合、_dotblas.so
(numpy.dot
のBLASバージョンを提供する)はビルドできません(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 。たぶん誰かがソースコードに飛び込んでパッチを作ることができます...とにかく、影響を受けるのは1つの関数(numpy.dot
)だけであり、高速のOpenBLASを使用してNumPy全体をいつでも簡単に再構築できるので、おそらくそれほど大きくありません結局対処します。
結論:後で再構築せずにATLAS/MKL/OpenBLASにリンクできますが、NumPyが構築されていない場合、numpy.dot
は依然として非常に遅くなります最初はATLAS/MKL/OpenBLAS(numpy.dot
がanyBLASを使用していないため、最初は何もできません)コンパイルが行われました)。
更新:実際には、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
を使用して違いをテストできます。