*シングルプロセッサ実行プログラムの最適化 [#o49b266c]
#contents

旧システムからのプログラムの移行についてまとめましたので、[[「旧システムからのプログラムの移行」>旧システムからのプログラムの移行#j40218a9]]を参照下さい。

**コンパイラ [#d40f52cd]
-ifort
--Fortranをサポート
-icc
--Cをサポート
-icpc
--C++をサポート

最良のパフォーマンスを得るためにIntelCompilerを推奨致しますが、GNUツールであるgfortran、gcc、g++もお使い頂けます。このガイドでは、IntelCompiler ifort、icc、icpcのオプションをご紹介します。尚、-helpオプションを指定して頂くとコンパイラオプションの一覧が表示されます。

**コンパイラオプション [#b1dc8d3f]
-最適化オプション
--推奨するオプション~
デバッグが終わり正しい結果が得られているプログラムに対して、推奨するオプションは以下の通りです。eic、eichとeicpで搭載するプロセッサが異なるため、[[プロセッサに特化したオプション>#p94bc2d0]]が異なります。
---eic or eich
 -O3 -xAVX

---eicp
 -O3 -xCORE-AVX2


--最適化レベルオプション
|~オプション|~内容|
|-O0|全ての最適化を無効にします。|
|-O1|保守的な最適化を行います。|
|-O2|積極的な最適化を行います。(デフォルトの最適化レベル)|
|-O3|-O2の最適化に加えて、プリフェッチ、ループの交換などを行います。|

&aname(p94bc2d0);
--プロセッサに特化したオプション
|~オプション|~内容|
|-xAVX|AVX命令を生成します。eic、eichに搭載されているXoen E5-4627v2はAVX命令をサポートしています。|
|-xCORE-AVX2|AVX2命令を生成します。eicpに搭載されているXeon E5-2680v3はAVX2命令をサポートしています。|
~
AVXでは浮動小数点演算のベクトル長が256ビットです。4つの倍精度実数データ(64ビット)の演算が可能です。

---8並列の単精度浮動小数点演算(8x32 bit = 256 bit)
---4並列の倍精度浮動小数点演算(4x64 bit = 256 bit)
~
#ref(AVX.jpg,left,nowrap,80%)
~
AVX2はさらに乗加算演算をサポートしています。
~
A=A*B+C
~
この演算を1回で行います。

---eic、eichは -xAVX オプションの指定が可能
---eicpは -xAVXと-xCORE-AVX2 オプションのどちらの指定も可能

--浮動小数点演算オプション
|~オプション|~内容|
|-no-prec-div|[最適化優先]:除算を逆数の乗算にするなどの最適化が有効になります。|
|-fp-model fast [=1/2]|[最適化優先]:浮動小数点データにより強力な最適化を有効にします。|
|-fp-model precise|[精度優先]:精度に影響する最適化を無効にします。|
デフォルトでは fp-model fast=1 が設定されており、最適化を行っています。

-デバッグオプション
--ここで紹介するオプションは、ifort で有効なオプションです。~
|~オプション|~内容|
|-traceback -g|Segmentation Faultなどのエラー終了時にエラーの発生箇所を表示します。|
|-traceback -g&br;-check  bounds|実行時に配列の領域外参照を検出すると、エラー終了し発生箇所を表示します。&br;3つのオプションを同時に指定してください。|
|-traceback -g -fpe0|オーバーフロー、ゼロ割り、不正な処理を検出するとエラー終了し、発生箇所を表示します。&br;アンダーフローはゼロに置き換えて処理を続行します。&br;3つのオプションを同時に指定してください。|
※)-gオプションを指定すると、デフォルトの最適化オプションが-O0になるのでご注意ください。
&br;最適化オプションが指定されている場合には、指定されたオプションが有効です。
&br;デバッグオプションを指定するとプログラムの性能が落ちる可能性がありますので、
&br;デバッグが終りましたら、デバッグオプションははずして下さい。

**Intel64におけるメモリモデル [#u84a3078]
デフォルトでは、データの大きさとコードの大きさはそれぞれ2GBの制限があります。2GBを越えているとリンク時に以下のメッセージが出力されます。
 relocation  truncated  to  fit: R_X86_64_32S against  `.bss'
 relocation  truncated  to  fit: R_X86_64_32S  against  `.bss'
 
このメッセージが出力されたときは、-mcmodelオプションを指定して2GBの制限を解除して下さい。(-mcmodelのデフォルト値はsmallなので、2GBの制限があります)
~
尚、-mcmodelオプションを指定したときは、-shared-intelオプションも指定して下さい。
|~オプション|~内容|
|-mcmodel=small(デフォルト)|コードの大きさとデータの大きさはそれぞれ2GBに制限されます。|
|-mcmodel=medium|コードの大きさには2GBの制限がありますが、データには2GBの制限はありません。|
|-mcmodel=large|コードの大きさにもデータの大きさにも2GBの制限はありません。|
|~オプション|~内容|
|-shared-intel |インテルが提供するライブラリーをすべて動的にリンクします。|

**数値計算ライブラリ [#c9bf52ae]
-Intelが提供するMKLが利用できます。MKLが提供するルーチンは以下の通りです。

--BLAS
--BLACS
--LAPACK
--ScaLAPACK
--PBLAS
--スパースソルバー 
--ベクトル数学ライブラリー (VML)
--ベクトル統計ライブラリー (VSL)(乱数生成ルーチンを含む)
--離散フーリエ変換とクラスター対応の離散フーリエ変換
--FFTWラッパーインターフェース
~
など

-シングルスレッド実行とマルチスレッド実行が可能です。それぞれ下記のようにリンクします。
--シングルスレッド実行
 $ ifort -o a.out -mkl=sequential
--マルチスレッド実行
 $ ifort -o a.out -mkl=parallel

-例1)sdotルーチンを使ってベクトルの内積計算
 $ cat test1.f
     program test1
     real x(10), y(10), sdot, res
     integer n, incx, inxy, i
     external sdot
     n = 5
     incx = 2
     incy = 1
     do i = 1, 10
        x(i) = real(i)
        y(i) = 1.0e0
     enddo
     res = sdot(n, x, incx, y, incy)
     print*,'SDOT = ', res
     stop
     end
 
 $ ifort  -O3 -xAVX test1.f  -mkl=sequential
 $ dplace ./a.out
 
 SDOT =    25.00000

-例2)ラッパーを使用してFFTWルーチンをMKLで実行
 $ cat test2.f
 
 .... FFTWを使用したソースコード ......
 
 $ ifort -O3 -xAVX test2.f -I${MKLROOT}/include/fftw  -mkl=sequential
 $ dplace ./a.out


**時間計測関数 [#jccde2f3]
-Fortranの関数
--dclock関数~
当日0時00分からの経過時間を秒単位で返します。返値はreal(8) 型です。
 real(8) time1, dclock
 time1 = dclock()
例)
 $ cat test3.f
 
     program test3
     real*8 dclock, t1, t2
     t1 = dclock()
     call sub()
     t2 = dclock()
      write(6,*) "time :", t2 - t1
     end
 
     subroutine sub()
     call system("sleep 3")
     return
     end
 
 $ ifort -O3  -xAVX test3.f
 $ dplace ./a.out
  time :   3.01978499999677
(*)日にちを跨いでも正しく時間が計測できるように、fortranプログラムからC/C++の時間計測関数gettimeofdayを呼び出す方法をご紹介します。
dclock.cはgettimeofdayの返値を秒単位に変換するルーチンです。
 
 $ cat dclock.c
 #include<stdio.h>
 #include<sys/time.h>
  double  dclock_()
 {
      struct timeval tp;
      struct timezone tzp;
      gettimeofday(&tp,&tzp);
      return((double)tp.tv_sec+(double)tp.tv_usec*1.e-6);
 }
 
上記dclock.cをコンパイルし、Fortranプログラムと共にリンクします。
ここでは、dclock関数の説明で示したプログラム例 test3.fをコンパイルします。
 
 $ icc  -c  dclock.c
 $ ifort  -O3 -xAVX  -o  a.out  test3.f  dclock.o
 $ dplace  ./a.out
 
  time :   3.01569199562073
 
上記の例のように、fortranプログラムと共にdclock.cをリンクすると、fortranライブラリの
dclock関数ではなく、dclock.cで呼び出しているgettimeofdayで時間計測を行います

-C/C++の関数
--gettimeofday~
1970年1月1日00:00:00からの経過時間をマイクロ秒単位で計測します。~
返値は整数型で、実行に成功すれば0、失敗すると-1を返します。~
 #include<sys/time.h>
 
 structtimevaltp;
 structtimezonetzp;
 gettimeofday(&tp,&tzp);
 
例)経過時間を秒単位で返すルーチン
 
 $ cat elapsed.c
      #include<stdio.h>
      #include<sys/time.h> 
 
      double elapsed()
 {
      struct timeval tp;
      struct timezone tzp;
      gettimeofday(&tp,&tzp);
      return((double)tp.tv_sec+(double)tp.tv_usec*1.e-6);
 }
 
 $ cat test5.c
 
 #include<stdio.h>
 #include<sys/time.h>
      int main(void)
 {
      int i;
      float s=0; 
      double ts, te;
      double elapsed();
      ts=elapsed();
      for(i=0;i<1000000;i++);
           s=s+(float)i;te=elapsed();
      printf("%10.6en",te-ts);
      exit(EXIT_SUCCESS)
 }
----
**性能解析ツール [#r917c8bf]
-SGI Perfsuite
--実行時間がかかっている箇所を探す~
psrunコマンドを指定してプログラムを実行します。プログラムの実行が終わると解析結果ファイルが作られるので、psprocessコマンドを使って整形してください。~
例)~
 $ dplace psrun ./a.out
 
実行が終わるとカレントディレクトリに解析結果ファイルが作られます。
 
 $ ls *.xml
 a.out.78075.eicp1.xml
 
解析結果ファイルは、
~
「バイナリ名.PID.ホスト名.xml」
~
です。
 
 $ psprocess a.out.78075.eicp1.xml
 
解析結果ファイルの内容が出力されます。
 Samples   Self   Total %  Function
    3770   69.43%   69.43%  FUNC1__
     420    7.73%   77.16%  FUNC3_
     412    7.59%   84.75%  FUNC-tmp4_
     262    4.83%   89.58%  SUB-diff_
     133    2.45%   92.03%  SUB_init_
      11    2.03%   94.05%  SUB_out_
Samples  : サンプリングのカウント数~
Self %   : 全体に対する割合~
Total %  : 積算~
Function : プログラム内の関数名
~
コンパイルオプション-gを指定すると、行毎の解析結果も表示します。
 Samples    Self%   Total%   Function:  File:Line
     601  10.20%  10.20%   FUNC1:/home/t2.f:556
     466   7.91%  18.12%   FUNC1:/home/t2.f:389
     258   4.38%  22.50%   FUNC1:/home/t2.f:383
     252   4.28%  26.77%   FUNC1:/home/t2.f:451
     233   3.96%  30.73%   FUNC1:/home/t2.f:178

トップ   編集 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ