Xeon Phiのプログラミングについての情報(2) Offloadによるプログラミング
Xeon Phiを使ったプログラムの実行としては以下の方法がある。
今回はOffloadを使用したプログラムを作ったのでその解説を簡単にする。
Offloadを使用したプログラミングについて
Offloadを使用したプログラミングを簡単に説明するとGPUプログラミングのような使い方になる。
Intelが公開している資料等は以下のところにある。
実際のプログラミングはOpenMPの様にディレクティブを使ってXeon Phiへのデータ転送やプログラミングの指示を行う。
基本的な実行の流れは以下の通り。
今回Xeon Phiを使ったプログラムの練習とテストのために行列積のプログラムを書いた。コードは以下のところ。
Offloadによる記述の説明
Xeon Phiで実行する部分の指示
練習で書いたサンプルプログラムの中の./src/matrix_multiplication.cppのMultiplyMatricesMicImple()という関数の中で使っている。
まず以下のようなディレクティブによってXeon Phiで実行する部分を記述
#pragma offload target(mic) { // Xeon Phiで実行される部分 }
Xeon Phiが複数あり、実行するXeon Phiを指定する必要がある場合は以下の様にする
#pragma offload target(mic:0) { // Xeon Phiで実行される部分 }
上の例ではmic0というXeon Phiが使われる。この0で指定した部分には変数も使える。サンプルでは試しに変数で指定している。
Xeon Phi、CPU間のデータ転送
データを転送する場合は以下のようにして行う。
#pragma offload target(mic) \ in(matrix_a:length(column_a*row_a) alloc_if(1) free_if(1)) \ in(matrix_b:length(column_b*row_b) alloc_if(1) free_if(1)) \ out(matrix_c:length(column_a*row_b) alloc_if(1) free_if(1)) { // Xeon Phiで実行される部分 }
matrix_aはCPU側のポインタで、転送する要素数をlength(n)で指定、今は行列なのでcolumn_a*row_a個ある。その次のalloc_if(1) free_if(1)の部分ではディレクティブの開始時にメモリを確保、終了時に開放するように指定。指定しない場合と同じだが、今回は明示的にやっている。
メモリを使いまわすために確保、開放しない場合は1の部分を0にする。
そしてinはディレクティブの開始時にCPUからXeon Phiにメモリのコピーを、outは終了時にXeon PhiからCPUのメモリに転送を行うときに指定。
上の例ではmatrix_aとmatrix_bのデータを最初にCPUからXeon Phiに転送し、計算が終わり次第、matrix_cの内容をXeon PhiからCPUに転送していることになる。
他にもいろいろできるのでこれについては以下のチュートリアル資料等を参考に。
http://software.intel.com/sites/default/files/Beginning%20Intel%20Xeon%20Phi%20Coprocessor%20Workshop%20Offload%20Compiling%20Part%201.pdf
(ALLOC、FREEなどがdefineされてるらしいが、使うとコンパイル時にエラーになってできなかった・・・。だれか教えて)
Xeon Phiで処理するコード
ディレクティブ以下のブロック内については普通にOpenMPなどが使える。その部分についての説明は省略。
(今回のサンプルは何も考えずに普通にOpenMPで並列化したのでもっと頑張れよ!といわれるかもしれないがそのうち頑張ります。)
Offloadで書いたプログラムを実行する際の環境変数周り
OpenMPでスレッド数を指定する際に環境変数のOMP_NUM_THREASにスレッド数をセットするのが一般的だが、何もしないとCPUとXeon Phiで同じ環境変数を見にいってしまう。このため、Xeon Phiだけ指定したい場合はMIC_ENV_PREFIXを使う。
export MIC_ENV_PREFIX=M_
としておくと、M_から始まる環境変数がXeon Phiで使われる。
なのでXeon PhiでOpenMPのスレッド数を指定する場合は以下のようにする。
export MIC_ENV_PREFIX=M_
export M_OMP_NUM_THREAS=128
また、CPUやXeon Phiのデータのやり取りやXeon Phiの実行の様子を出力するには以下のように環境変数をセットする。
export OFFLOAD_REPORT=1 #2や3でより詳細なものが出せる
実験
2つの正方行列のサイズを1024*1024,2048*2048,4096*4096にしてその積を計算するときの計算時間を測定。
(CPUもBLASなどのライブラリを使っていませんのでその分も考慮してください)
実験環境
- CPU : Intel(R) Xeon(R) CPU E5-2670 0 @ 2.60GHz
- Xeon Phi™ コプロセッサー 5110P
- コンパイラ:インテル(R) 64 C コンパイラー XE バージョン 13.0.1.117 ビルド 20121010
行列サイズ | CPU 1コア (sec.) | Xeon Phi 236スレッド (sec.) | 高速化率 |
---|---|---|---|
1024*1024 | 2.1 | 1.4 | 1.5 |
2048*2048 | 17.8 | 1.7 | 10.5 |
4096*4096 | 728.4 | 3.5 | 208.1 |
最大約200倍、CPUのソケットで比較すると理想的には約26倍くらいは出る計算。なので割りと速い気も・・・GPUと比べたらどうかは試してみないとよくわからないが。
頑張ってチューニングしたらどうなるかはきっとHPC屋さんがわんさか?やってるのでそちらを参照。
まとめ
どういうふうに書けばいいかわかれば割りとすぐに使える感じ。そこそこ速くなりそうなので今回は満足。
今後研究に使うかは謎。
他にもいろいろな制御ができるので公式のサンプルコードやチュートリアルを参考に。
情報のリンクのまとめは以下のところにある。
http://d.hatena.ne.jp/ang65/20130402/1364873045