インテル® MKL を Numpy/Scipy に実装

インテル® DPC++/C++ コンパイラーインテル® Fortran コンパイラーインテル® oneMKL

この記事は、インテル® デベロッパー・ゾーンに公開されている「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 をご覧ください。

DGEMM

バージョン情報
このアプリケーション・ノートは、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 ファイルを解凍するには、次のコマンドを使用します。

$gunzip numpy-x.x.x.tar.gz $tar -xvf numpy-x.x.x.tar

解凍すると、numpy-x.x.x というディレクトリーが作成されます。
同様に、以下のコマンドで SciPy を解凍します。

$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 ビット版コンポーネントを使用することを仮定しています:

[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 をビルドするには、次の行を追加します。

[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 を変更します。

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

ifort -xhost -openmp -fp-model strict -fPIC

最新のソースを使用している場合、この変更はすでに intel.py に反映されています。そのほかのコンパイラーの最適化オプションもここで設定できます。

インテル® MKL の ILP64 インターフェイスを利用する場合、-i8 オプションを追加してください。古いバージョンの NumPy/SciPy を使用している場合、最新の NumPy のバージョンに含まれる intel.py を参考にして、上記のコンパイラー・オプションを変更できます。

インテル® コンパイラーで NumPy をコンパイルしてインストールします: インテル® 64 プラットフォームでは次のコマンドを実行します:

$Python* setup.py config --compiler=intelem build_clib --compiler=intelem build_ext --compiler=intelem install

IA32 では以下を実行します:

$Python* setup.py config --compiler=intel build_clib --compiler=intel build_ext --compiler=intel install

異なる点は、IA32 向けには “intel” を指定し、インテル® 64 向けには “intelem” を指定していることです。–prefix=<インストール先> を指定すると、任意のディレクトリーにインストールできます。

SciPy のビルドとインストール
64 ビットビルド向けにインテル® コンパイラーで SciPy をコンパイルしてインストールします:

$Python* setup.py config --compiler=intelem --fcompiler=intelem build_clib --compiler=intelem --fcompiler=intelem build_ext --compiler=intelem --fcompiler=intelem install

IA32 ビルドでは以下を実行します:

$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 をビルドするには、次の設定を行います:

$export LD_LIBRARY_PATH=/opt/intel/composer_xe_2015/mkl/lib/intel64:/opt/intel/composer_xe_2015/lib/intel64:$LD_LIBRARY_PATH

IA32 プラットフォーム向けには次のように設定します:

$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 プラットフォームでは次のように設定します:

$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* スクリプトの例を示します。

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
 

Cholesky

SVD

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 します:

$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 以降でのみサポートされます。

コンパイラーの最適化に関する詳細は、最適化に関する注意事項を参照してください

タイトルとURLをコピーしました