この記事は、インテル® デベロッパー・ゾーンに公開されている「Numpy/Scipy with Intel® MKL」の日本語参考訳です。
*著者注: この記事は 2014 年 8 月 27 日更新されました。
NumPy/SciPy アプリケーション・ノート
ステップ 1 – 概要
このガイドは、現在 Numpy/SciPy を利用しているユーザーが、インテル® マス・カーネル・ライブラリー (インテル® MKL) の利点を活用することを目的としています。
NumPy は、ベクトルや行列演算を可能な限り BLAS と LAPACK 関数に自動マッピングします。インテル® MKL は、業界標準であるそれらのインターフェイスをサポートしているため、NumPy のスクリプトをわずかに変更するだけでインテル® MKL の最適化の恩恵を受けることができます。
NumPy は、Python* による科学技術計算に必要な基本パッケージです。以下で構成されます:
- 強力な N 次元配列オブジェクト
- 洗練された (ブロードキャスト) 関数
- C/C++ および Fortran コードを統合するためのツール
- 便利な線形代数、フーリエ変換、および乱数機能を提供
NumPy は、科学的な用途に加えて、一般的なデータの効率良い多次元コンテナーとして使用することができます。
NumPy に関する詳細は、http://NumPy.scipy.org/ をご覧ください。
SciPy は、統計、最適化、積分、フーリエ変換、信号および画像処理、ODE (常微分方程式) ソルバーなど多くのモジュールを提供します。SciPy ライブラリーは、高速で使いやすい NumPy の N 次元配列操作を利用しています。そのため、SciPy ライブラリーは、NumPy 配列で動作するように構築され、Python* ユーザー向けに数値積分と最適化ルーチンなど使いやすく効率の良い多くの数値演算ルーチンを提供しています。SciPy に関する詳細は、http://www.scipy.org をご覧ください。
バージョン情報
このアプリケーション・ノートは、Linux* プラットフォーム上で最新のインテル® MKL を使用する NumPy/SciPy ユーザーを支援するために作成されました。
この記事に記載される内容は、インテル® MKL 11.0 以降およびインテル® コンパイラー 13.0 以降に適用されます。この記事に記載される手順は、Python* 2.7 と Python* 3.4 で検証されています。最新の環境では、インテル® MKL 11.2、インテル® コンパイラー 15.0、Numpy 1.8.1、そして SciPy 0.14.0 でも動作確認されています。
ステップ 2 – NumPy と SciPy のソースコードをダウンロードする
NumPy のソースコードは以下からダウンロードできます:
http://www.scipy.org/Download
前提条件
インテル® MKL は以下の方法で入手できます:
インテル® MKL 製品の無料評価版をダウンロードする。
インテル® MKL 製品の無料非商用版* をダウンロードする。
これらは、以下のページで入手できます:
インテル® マス・カーネル・ライブラリー製品ウェブページ
インテル® MKL は、次のスイート製品に同梱されています。
インテル® Parallel Studio XE Cluster Edition/Professional Edition/Composer Edition
ステップ 3 – 設定
ダウンロードした NumPy-x.x.x.tar.gz ファイルを解凍するには、次のコマンドを使用します。
1 | $gunzip numpy-x.x.x. tar .gz $ tar -xvf numpy-x.x.x. tar |
解凍すると、numpy-x.x.x というディレクトリーが作成されます。
同様に、以下のコマンドで SciPy を解凍します。
1 | $gunzip scipy-x.x.x. tar .gz $ tar -xvf scipy-x.x.x. tar .gz |
解凍すると、scipy-x.x.x というディレクトリーが作成されます。
NumPy と SciPy の最新のソースコードは、それぞれの Github リポジトリーからも入手できます。
インテル® C++ および Fortran コンパイラーがインストールされ、PATH が設定されていることを確認してください。また、インテル® コンパイラー (C++ と Fortran) およびインテル® MKL のライブラリーの場所が LD_LIBRARY_PATH に設定されていることを確認します。
ステップ 4 – NumPy をビルドおよびインストールする
numpy-x.x.x へ移動します。
site.cfg.example をコピーして site.cfg を作成します
site.cfg を次のように変更します:
インテル® MKL を利用するには、NumPy のトップレベル・ディレクトリーの site.cfg ファイルに以下の行を追加します。以下は、インテル® Parallel Studio XE 2015 の 64 ビット版コンポーネントを使用することを仮定しています:
1 2 3 4 5 | [mkl] library_dirs = /opt/intel/composer_xe_2015/mkl/lib/intel64 include_dirs = /opt/intel/composer_xe_2015/mkl/include mkl_libs = mkl_rt lapack_libs = |
32 ビット版の NumPy をビルドするには、次の行を追加します。
1 2 3 4 5 | [mkl] library_dirs = /opt/intel/composer_xe_2013/mkl/lib/ia32 include_dirs = /opt/intel/composer_xe_2015/mkl/include mkl_libs = mkl_rt lapack_libs = |
numpy/distutils/intelccompiler.py の cc_exe を変更します。
1 | self.cc_exe = 'icc -O3 -g -fPIC -fp-model strict -fomit-frame-pointer -openmp -xhost' |
ここでは、速度の最適化とより積極的なループ・フュージョン、ループのブロックのアンロールとジャム、IF 文の畳み込みのため -O3 を、OpenMP* によるスレッド化のために -openmp を、そしてコンパイルするホスト・プロセッサーで利用できる最上位の SIMD 命令を生成するよう -xhost オプションを追加しています。ILP64 インターフェイスを利用する場合、-DMKL_ILP64 を追加してください。
プロセッサー固有のコンパイラー・オプションは、コマンドラインで “icc –help” を実行するか、インテル® コンパイラーのドキュメントをご覧ください。
Fortran コンパイラーの設定は、numpy-x.x.x/numpy/distutil/fcompiler/intel.py にインテル® Fortran コンパイラー向けに以下のオプションを追加します:
IA32 とインテル® 64
1 | ifort -xhost -openmp -fp-model strict -fPIC |
最新のソースを使用している場合、この変更はすでに intel.py に反映されています。そのほかのコンパイラーの最適化オプションもここで設定できます。
インテル® MKL の ILP64 インターフェイスを利用する場合、-i8 オプションを追加してください。古いバージョンの NumPy/SciPy を使用している場合、最新の NumPy のバージョンに含まれる intel.py を参考にして、上記のコンパイラー・オプションを変更できます。
インテル® コンパイラーで NumPy をコンパイルしてインストールします: インテル® 64 プラットフォームでは次のコマンドを実行します:
1 | $Python* setup.py config --compiler=intelem build_clib --compiler=intelem build_ext --compiler=intelem install |
IA32 では以下を実行します:
1 | $Python* setup.py config --compiler=intel build_clib --compiler=intel build_ext --compiler=intel install |
異なる点は、IA32 向けには “intel” を指定し、インテル® 64 向けには “intelem” を指定していることです。–prefix=<インストール先> を指定すると、任意のディレクトリーにインストールできます。
SciPy のビルドとインストール
64 ビットビルド向けにインテル® コンパイラーで SciPy をコンパイルしてインストールします:
1 | $Python* setup.py config --compiler=intelem --fcompiler=intelem build_clib --compiler=intelem --fcompiler=intelem build_ext --compiler=intelem --fcompiler=intelem install |
IA32 ビルドでは以下を実行します:
1 | $Python* setup.py config --compiler=intel --fcompiler=intel build_clib --compiler=intel --fcompiler=intel build_ext --compiler=intel --fcompiler=intel install |
インテル® MKL とインテル® コンパイラー向けにライブラリーのパスを設定します
インテル® 64 プラットフォーム向けに NumPY/SciPy をビルドするには、次の設定を行います:
1 | $ export LD_LIBRARY_PATH= /opt/intel/composer_xe_2015/mkl/lib/intel64 : /opt/intel/composer_xe_2015/lib/intel64 :$LD_LIBRARY_PATH |
IA32 プラットフォーム向けには次のように設定します:
1 | $ export LD_LIBRARY_PATH= /opt/intel/composer_xe_2015/mkl/lib/ia32 : /opt/intel/composer_xe_2015/lib/ia32 :$LD_LIBRARY_PATH |
インテル® MKL とインテル® コンパイラーをデフォルト以外の場所にインストールしている場合、LD_LIBRARY_PATH を正しく設定しないと問題が発生する可能性があります。私たちが確認した常にうまく機能する解決策は、Python、NumPy そして SciPy の環境変数 LD_RUN_PATH を設定することです。例えば、IA32 プラットフォームでは次のように設定します:
1 | $ export LD_RUN_PATH= /opt/intel/composer_xe_2013/lib/ia32 : /opt/intel/composer_xe_2015/mkl/lib/ia32 |
注: NumPy は CBLAS を使用しているため、より良いパフォーマンスを得るには、配列を定義する際に、列優先の Fortran スタイルよりも、行優先の C スタイルを利用することを推奨します。
付録 A: 例
以下に、Numpy とインテル® MKL がインストールされた環境で、行列乗算を行う Python* スクリプトの例を示します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | import numpy as np import time N = 6000 M = 10000 k_list = [ 64 , 80 , 96 , 104 , 112 , 120 , 128 , 144 , 160 , 176 , 192 , 200 , 208 , 224 , 240 , 256 , 384 ] def get_gflops(M, N, K): return M * N * ( 2.0 * K - 1.0 ) / 1000 * * 3 np.show_config() for K in k_list: a = np.array(np.random.random((M, N)), dtype = np.double, order = 'C' , copy = False ) b = np.array(np.random.random((N, K)), dtype = np.double, order = 'C' , copy = False ) A = np.matrix(a, dtype = np.double, copy = False ) B = np.matrix(b, dtype = np.double, copy = False ) C = A * B start = time.time() C = A * B C = A * B C = A * B C = A * B C = A * B end = time.time() tm = (end - start) / 5.0 print ( '{0:4}, {1:9.7}, {2:9.7}' . format (K, tm, get_gflops(M, N, K) / tm)) |
付録 B: パフォーマンスの比較
LU 分解、コレスキー分解、そして SVD 分解の例をダウンロードするには、Examples.py をクリックしてください。
この記事中のパフォーマンス・チャートは、インテル® MKL 11.1 update 1 を使用して計測しています。
付録 1:
既知の問題:
ifort のコンパイラー・オプションに -O3 もしくは -O2 (デフォルト) を指定した場合、SciPy のテストの 1 つが失敗することが知られています。-O1 オプションを使用することでこれを回避できます。
GNU* コンパイラー・チェーンによるビルド:
前述のように、site.cfg ファイルのインテル® MKL セクションを変更します。GNU* コンパイラーで NumPy と SciPy をビルドするには、site.cfg ファイルで mkl_rt とのリンクのみを指定します。
コンパイラー・オプションを export します:
1 2 3 4 | $ export CFLAGS= "-fopenmp -m64 -mtune=native -O3 -Wl,--no-as-needed" $ export CXXFLAGS= "-fopenmp -m64 -mtune=native -O3 -Wl,--no-as-needed" $ export LDFLAGS= "-ldl -lm" $ export FFLAGS= "-fopenmp -m64 -mtune=native -O3" |
それぞれのソース・ディレクトリーで、NumPy と SciPy の config、build そして install を実行します。
インテルの OpenMP* の代わりに GNU* OpenMP* を利用する場合、MKL_THREADING_LAYER=GNU を設定する必要があります。
NumPy と SciPy は両方とも線形代数関数を持っているため、NumPy BLAS もしくは SciPy BLAS のどちらかを呼び出します。同時に両方を利用するのは MKL でサポートされていないため、両方から呼び出した場合クラッシュする可能性があります。
SciPy BLAS を利用するには、MKL_INTERFACE_LAYER=GNU を設定します。
MKL_THREADING_LAYER と MKL_INTERFACE_LAYER の 2 つの環境変数は、インテル® MKL 11.1 update 3 以降でのみサポートされます。
コンパイラーの最適化に関する詳細は、最適化に関する注意事項を参照してください