Show page source of インテル謹製の数値演算ライブラリ「MKL」を使ってプログラムを高速化_p3 #49698

[[PageNavi(NavigationList)]]



==== MKLのパフォーマンスを調べる - 高速フーリエ変換 ====


 続いて、高速フーリエ変換(FFT)のパフォーマンスを確認してみよう。FFTは信号処理や画像/音声処理などの分野で多く用いられている処理で、データの周波数特性を分析するために使われる解析処理である。FFTを実装したフリーのライブラリとしては、GPLで提供されている[http://www.fftw.org/ FFTW]がある。ここではその最新版であるFFTW Version 3.2と、MKLのフーリエ変換ライブラリを比較してみよう。


 FFTWは、マサチューセッツ工科大学(MIT)のMatteo Frigo氏とSteven G. Johnson氏によって開発されたライブラリで、各種Linux/UNIXおよびWindowsで利用できる。CPUが備えるSSEやSSE2、3dNow!、Altivecなどの数値演算機能を利用した高速な演算が可能なほか、任意サイズのデータに対してフーリエ変換/逆フーリエ変換の両方が行えるといった特徴を持ち、各種数値計算ツールなどでも多く採用されている。


 MKLに含まれるFFT関数はFFTWとの互換性はないものの、FFTWと同様のインターフェイスを持つラッパーライブラリのソースコードが付属しており、これを利用することでFFTWを簡単にMKLに置き換えることができる。今回はこのラッパーライブラリを使用してFFTWで行っていたプログラムのFFT処理部分をMKLに置き換え、処理時間がどのくらい変わるのか調べてみよう。


 なお、このラッパーライブラリはデフォルトでは「C:\Program Files\Intel\Compiler\11.0\066\cpp\mkl\interfaces\fftw3xc」ディレクトリにインストールされるのだが、ソースコードのみしか含まれていないため、ライブラリを利用するためにはコマンドラインでnmakeコマンドを実行してコンパイルする必要がある。Windows環境の場合、スタートメニューの「Intel Software Development Tools」内にある「IA-32 対応アプリケーション用 C++ ビルド環境」を実行してコマンドプロンプトを開き、下記のように実行すればよい。
{{{
 cd C:\Program Files\Intel\Compiler\11.0\066\cpp\mkl\interfaces\fftw3xc
 nmake lib32
}}}


 これにより「C:\Program Files\Intel\Compiler\11.0\066\cpp\mkl\ia32\lib\」ディレクトリ以下に「fftw3xc_intel.lib」というライブラリが作成される。あとは「C:\Program Files\Intel\Compiler\11.0\066\cpp\mkl\include\fftw」以下にある「fftw3.h」をC/C++ソースコード内でインクルードし、上記で作成したfftw3xc_intel.libと、MKLのライブラリ「mkl_intel_c.lib」および「mkl_intel_thread.lib」、「mkl_core.lib」、「libguide40.lib」をリンクすれば、FFTWを利用するプログラムをそのままMKLを使って動かすことができる。

==== FFTWとMKLの処理速度を比較する ====


 処理速度比較に使用するプログラムは指定したモノクロ画像に対して2次元のFFT処理を行うもので、幅3072ドット、高さ2304ドットの画像をFFT処理し、処理にかかった時間を測定するものだ('''リスト2''')。


====== リスト2 サンプルコードのFFT処理部分(抜粋) ======

{{{
  /* 作業用メモリを割り当て */
  in  = fftw_malloc(sizeof(fftw_complex) * width * height);
  out = fftw_malloc(sizeof(fftw_complex) * width * height);

  /* データを作業用メモリにコピー */
  for( n = 0; n  width*height; n++ ) {
    in[n][0] = (float)input_image_buf[n];
    in[n][1] = 0.0;
  }

  /* FFTエンジンを初期化 */
  p = fftw_plan_dft_2d(height, width, in, out, FFTW_FORWARD, FFTW_ESTIMATE);

  /* FFTを実行 */
  fftw_execute(p);
}}}

※サンプルプログラム全文は[「最適化・並列化コードを生み出す最新コンパイラ「インテル_コンパイラー」サンプルコード_p3 こちら]

 なお、FFTWはWindows環境でもコンパイルできるが、GCC向けに最適化を行っているために他のコンパイラではコンパイルできなかったり、パフォーマンスが落ちるという問題があるようだ。そのため、今回はFFTWのWebサイトで配布されているバイナリ版DLLを使用した。


 テストでは、FFTWを使ったプログラムをGCC 4およびVisual C++ 2008でコンパイルしたものと、MKLを用いたプログラムをインテル C++ コンパイラーでコンパイルしたものを用い、それらの処理時間を比較した。それぞれのコンパイルはコマンドラインで下記のように行った。
{{{
GCCでのコンパイル:
 gcc-4.exe -L. -o fft1_gcc.exe -lfftw3-3 -lm -O3 -march=core2 fft1.c

Visual C++でのコンパイル:
 cl.exe /Ox /Oi /Ot libfftw3-3.lib /Fefft1_vc.exe fft1.c
}}}


 さて、それぞれの実行時間をまとめたものが'''表4'''である。MKLを使用したプログラムは、FFTWを使ったものと比べて約60%高速に動作するという結果となった。
{{{ html
<h6>表4 3072×2304サイズの画像のFFT処理にかかった時間</h6>
<table class="wikitable" border="1">

<tr><th>プログラム</th><th>1回目</th><th>2回目</th><th>3回目</th><th>平均</th></tr>
<tr><td>GCC 4 + FFTW</td><td>1.576秒</td><td>1.513秒</td><td>1.513秒</td><td>1.534秒</td></tr>
<tr><td>Visual C++ + FFTW</td><td>1.326秒</td><td>1.279秒</td><td>1.263秒</td><td>1.289秒</td></tr>
<tr><td>インテル C++ コンパイラー +MKL</td><td>0.733秒</td><td>0.873秒</td><td>0.780秒</td><td>0.795秒</td></tr>

</table>
}}}


 FFT処理についても先のBLASの例と同様、複数のCPUコアを使って並列処理を行うことで、高速な処理を実現しているようだ('''図2''')。
[[Thumb(75cc9635e0c8a0e9c2b2f55f6ea82cb5.png, caption=図3 FFTプログラム実行時のCPU負荷)]]



[[PageNavi(NavigationList)]]