EIC TOP

並列実行プログラムの最適化

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

自動並列化

parallelオプションの指定により、コンパイラがソースコード内の全ループに対して、並列化が可能か否かの解析を行います。

  • -parallel
    • ソースファイル内の全てのループを解析し、安全に並列化できるループがあれば並列バイナリを生成します。
  • -par-threshold[n]
    • 自動並列化の性能向上の見込みのしきい値(確信度)を設定します。([n]は0~100まで) デフォルトは100。
    • n が 0 のとき、ループは、計算量にかかわらず、並列化可能ならば常に自動並列化されます。 n が 100 のとき、並列化が可能でかつ並列化による性能向上が見込まれる場合のみ自動並列化されます。
  • -qopt-report[=n] -qopt-report-phase=par (-qopt-report[=n]は省略可)
    自動並列化の診断情報を出力します。
    • n=1:並列化されたループを出力します。
    • n=2:レベル1の詳細に加えて、並列化されなかったループとその簡単な理由を出力します。
    • n=3:レベル2の詳細に加えて、private、shared、reduction として分類されているメモリー位置を出力します。
    • n=4:レベル3と同じ
    • n=5:レベル4の詳細に加えて、並列化を妨げている依存関係を出力します。
    • デフォルトはn=2。
      (*)コンパイラのバージョン15以降、診断情報を出力する -opt-reportオプションが -qopt-reportに変わりました。また、-par-reportオプションが-qopt-report-phase=parに変わりました。-opt-report、-par-reportもお使い頂けますがワーニングメッセージが出力されます。
      (*)診断情報は、標準出力ではなく「バイナリ名.optrpt」ファイルに出力されます。
  • 例)
    $ cat mxm.f
    
      1       SUBROUTINEMXM(A,B,C,L,M,N,N1)
      2       DIMENSION A(M,L),B(N1,M),C(N1,L)
      3       DO  K =1,L
      4         DO  I =1,N
      5           C(I,K)=0.
      6         ENDDO
      7       ENDDO
      8       DO K =1,L
      9         DO I =1,N
     10           DO J =1,M
     11             C(I,K)=C(I,K)+B(I,J)*A(J,K)
     12           ENDDO
     13         ENDDO
     14       ENDDO
     15       RETURN
     16       END
    
    $ ifort  -c  -O3  -xAVX -parallel  -qopt-report -qopt-report-phase=par mxm.f
    ifort: remark #10397: optimization reports are generated in *.optrpt files in the output location
    
    mxm.optrptファイルに診断情報が出力されます。
    8行目のループが並列化されたことがわかります。
    
    $ ifort  -c  -O3  -xAVX  -parallel  -par-threshold0 -qopt-report -qopt-report-phase=par  mxm.f
    ifort: remark #10397: optimization reports are generated in *.optrpt files in the output location
    
    mxm.optrptファイルに診断情報が出力されます。
    3行目と8行目のループが並列化されたことがわかります。
  • -par-threshold100(デフォルト)の場合は、初期化ループ(3行目)には充分な処理量が無く、性能向上が確実ではないと判断し、並列化しません。
  • -par-threshold0の場合は、性能向上の見込み値には関係なく、安全に並列化できるループは全て並列化します。

OpenMP

qopenmpオプションの指定により、ソースコード内のOpenMP指示行を有効にします。
(*)コンパイラのバージョン15以降、OpenMP指示行を有効にするオプションが -openmp から -qopenmp へ変わりました。-openmp もお使い頂けます。
(*)診断情報は、「バイナリ名.optrpt」ファイルに出力されます。

  • -qopenmp
    • OpenMP指示行を有効にします。
  • -qopt-report[=n] -qopt-report-phase=openmp (-qopt-report[=n]は省略可)
    • OpenMP並列化の診断情報を出力します。
    • n=1:正常に並列化されたループ、領域、セクション、タスクを出力します。
    • n=2:1の情報に加えて、正常に処理された MASTER 構造、SINGLE 構造、CRITICAL 構造、ORDERED 構造、ATOMIC 宣言子などを示す診断メッセージを出力します。
    • デフォルトはn=2。
      (*)コンパイラのバージョン15以降、診断情報を出力する -opt-reportオプションが -qopt-reportに変わりました。また、-openmp-reportオプションが-qopt-report-phase=openmp に変わりました。-opt-report、-openmp-reportもお使い頂けますがワーニングメッセージが出力されます。
  • 例)
    $ cat mxm2.f
    
      1       SUBROUTINE MXM (A,B,C,L,M,N,N1)
      2       DIMENSION A(M,L),B(N1,M),C(N1,L)
      3 !$OMP PARALLEL DO
      4       DO  K =1,L
      5         DO  I =1,N
      6           C(I,K)=0.
      7         ENDDO
      8       ENDDO
      9 !$OMP PARALLAL DO
     10       DO K =1,L
     11         DO I =1,N
     12           DO J =1,M
     13             C(I,K)=C(I,K)+B(I,J)*A(J,K)
     14           ENDDO
     15         ENDDO
     16       ENDDO
     17       RETURN
     18       END
    
    $ ifort -c  -O3 -xAVX  -qopenmp  -qopt-report -qopt-report-phase=openmp mxm2.f
    ifort: remark #10397: optimization reports are generated in *.optrpt files in the output location
    
    mxm2.optrptファイルに診断情報が出力されます。

(*) -parallelと-qopenmpを同時に指定したとき
コンパイラは全ループに対して並列化可能か否かの解析を行い、可能であれば並列化します。
OpenMP指示行が指定されたループは、-qopenmpによって並列化さます。

  • 例)
    $ cat mxm3.f
    
      1       SUBROUTINE MXM (A,B,C,L,M,N,N1)
      2       DIMENSION A(M,L),B(N1,M),C(N1,L)
      3       DO  K =1,L
      4         DO  I =1,N
      5           C(I,K)=0.
      6         ENDDO
      7       ENDDO
      8 !$OMP PARALLEL DO
      9       DO K =1,L
     10         DO I =1,N
     11           DO J =1,M
     12             C(I,K)=C(I,K)+B(I,J)*A(J,K)
     13           ENDDO
     14         ENDDO
     15       ENDDO
     16       RETURN
     17       END
    
    $ ifort -c -O3 -xAVX -parallel  -par-threshold0  -qopt-report \
    -qopt-report-phase=par -qopenmp  -qopt-report-phase=openmp  mxm3.f
    ifort: remark #10397: optimization reports are generated in *.optrpt files in the output location
    
    mxm3.optrptファイルに診断情報が出力されます。
    
  • 3行目と9行目のループが自動並列化され、8行目のOpenMP指示行が有効になります。
  • 9行目のループは自動並列化とOpenMPの両方から並列化されますが、環境変数OMP_NESTED=falseがデフォルトで設定されているため、環境変数OMP_NUM_THREADS で指定したスレッド数で実行されます。
  • OMP_NESTED=falseは入れ子になった並列処理を無効にします。

OMP_NUM_THREADSについては、「自動並列化/OpenMPプログラムの実行スレッド数」を参照下さい。

自動並列化/OpenMPプログラムの実行スレッド数

  • 環境変数OMP_NUM_THREADSに実行スレッド数を指定します。
    $ setenv OMP_NUM_THREADS 4
    
    ジョブスクリプト、ジョブ投入方法については、「利用方法」を参照下さい。

自動並列化/OpenMPによる並列プログラムのデータ分散

  • EICシステムでは、「ファーストタッチ」を採用しています。データは、最初にそのデータにタッチ(書き込みまたは読み込み)したプロセスのローカルメモリに配置されるというものです。もし、配列(配列Aとする)を初期化しているループが並列化されていないと1CPUコア実行であるために、配列Aはある1つのノードに配置されます。配列Aを処理する並列実行領域では、複数のプロセッサが1つのノードへアクセスすることになります。このような状況ではプログラムの性能向上は望めません。可能なかぎり初期化ループも並列化してください。
    例)
       real*8 A(n), B(n), C(n), D(n)
    
        do i=1, n
            A(i) = 0.
            B(i) = i/2
            C(i) = i/3
            D(i) = i/7
        enddo
    !$omp parallel do
        do i=1, n
            A(i) = B(i) + C(i) + D(i)
        enddo

    first_touch1.JPG

        real*8 A(n), B(n), C(n), D(n)
    !$omp parallel do
        do i=1, n
            A(i) = 0.
            B(i) = i/2
            C(i) = i/3
            D(i) = i/7
        enddo
    !$omp parallel do
        do i=1, n
            A(i) = B(i) + C(i) + D(i)
        enddo
    first_touch2.JPG

スレッドのスタックサイズ

  • 各ユーザが使用可能なスタックサイズの上限を4GBに設定しています(メモリ使用量の上限ではありません)。関数や手続きの中で宣言されるローカル変数がスタック領域にアロケーションされます。上限を越えてスタックに領域を確保しようとすると、AddressErrorまたは、SegmentationFaultでプログラムは終了します。この場合、データを静的にアロケーションするために、COMMONブロックでデータ(配列)を宣言して下さい。
  • 環境変数KMP_STACKSIZEには自動並列化/OpneMPプログラムのスレーブスレッドが使用できるスタック領域の最大容量を指定します。スレーブスレッドのプライベート変数が対象です。共有変数、マスタースレッドのプライベート変数は対象ではありません。デフォルトでは2GBが設定されています。
  • 単位として、k(キロバイト)、m(メガバイト)、g(ギガバイト)、t(テラバイト)が使えます。
  • シリアル実行で実行できたプログラムが、自動並列化/OpenMP並列化したときにエラー終了してしまったというような場合にはスレッドのスタック領域が不足している可能性がありますので、KMP_STACKSIZEを増やしてください。

    例)
    $setenv KMP_STACKSIZE 6g

MPI

コマンド行の末尾にMPIライブラリのリンクを指示してください。

例)

$ ifort  -O3  -xAVX  ex_mpi.f -lmpi

実行時にはmpiexec_mptコマンドを使ってジョブを起動してください。
ジョブスクリプト、ジョブ投入方法については、「利用方法」を参照下さい。

  • MPIのデータ型
    FortranプログラムでのMPIのデータ型とそれに対応するFortranでのデータ型は以下の通りです。
    MPIのデータ型Fortranのデータ型bit
    MPI_DATATYPE_NULL対応する型はありません
    MPI_INTEGERINTEGER32
    MPI_REALREAL32
    MPI_DOUBLE_PRECISIONDOUBLE_PRECISION64
    MPI_COMPLEXCOMPLEX64
    MPI_DOUBLE_COMPLEXDOUBLE_COMPLEX128
    MPI_LOGICALLOGICAL4
    MPI_CHARACTERCHARACTER1
    MPI_INTEGER1INTEGER(KIND=1)8
    MPI_INTEGER2INTEGER(KIND=2)16
    MPI_INTEGER4INTEGER(KIND=4)32
    MPI_INTEGER8INTEGER(KIND=8)64
    MPI_REAL2REAL(KIND=2)16
    MPI_REAL8REAL(KIND=8)64
    MPI_REAL16REAL(KIND=16)128
    MPI_BYTEBYTE1

    CプログラムでのMPIのデータ型とそれに対応するCでのデータの型は以下の通りです。
    MPIのデータ型Cのデータ型bit
    MPI_CHARchar8
    MPI_SHORTshort16
    MPI_INTint32
    MPI_LONGlong64
    MPI_UNSIGHNED_CHARunsighned char8
    MPI_UNSIGHNED_SHORTunsighned short16
    MPI_UNSIGHNEDunsighned int32
    MPI_UNSIGHNED_LONGunsighned long64
    MPI_FLOATfloat32
    MPI_DOUBLEdouble64
    MPI_LONG_DOUBLElong_double128
    MPI_BYTE対応する型はありません1
    MPI_PACKED対応する型はありません

ハイブリッド

並列化を有効にするコンパイルオプションを指定して、リンク時にMPIライブラリをリンクします。

例)

$  ifort  -O3  -xAVX -qopenmp  -qopt-report -qopt-report-phase=openmp hybrid.f  -lmpi


ジョブスクリプト、ジョブ投入方法は、「利用方法」」を参照ください。

性能解析ツール

  • 実行時間のかかっている箇所を探します
  • 自動並列化/OpenMPプログラム
  • psrunコマンドにオプション -p を指定してください。 -p オプションの指定でマスタースレッドとスレーブスレッドの解析が可能です。
  • psrunコマンドと共に自動並列化/OpenMPプログラムを実行すると、OMP_NUM_THREADSで指定した数のスレッドの他に1つの管理スレッドが起動されます。そのため解析結果ファイルも実行スレッド数+1個作られますが、管理スレッドの解析結果ファイルには情報はありません。
  • 再コンパイルは必要ありません。ただし、行毎の解析を行いたいときには、-gオプションを指定してコンパイルしてください。

    例)
    $ setenv OMP_NUM_THREADS 4
    $ dplace -x5 psrun -p ./a.out

    実行終了後、解析結果ファイルがカレントディレクトリに作られます。
    $ ls*.xml
    a.out.3.4032.eich1.xml
    a.out.2.4032.eich1.xml
    a.out.4.4032.eich1.xml
    a.out.1.4032.eich1.xml
    a.out.0.4032.eich1.xml

    解析結果ファイル名は「バイナリ名.スレッド番号.PID.ホスト名.xml」です。
    psprocessコマンドで整形してください。
    $ psprocess  a.out.0.4032.eich1.xml

    (*)解析結果ファイルを複数指定して、全スレッドの解析結果を表示するということはできません。
    $ psprocess  a.out.0.4032.eich1.xml  a.out.2.4032.xml  a.out.3.4032.xml  <---不可

    例)
    行毎の解析を行うために -g オプションを指定し、並列化のために自動並列化オプションを指定してコンパイルします。
    $ ifort -g -O3 -xAVX -parallel -par-threshold0 -qopt-report -qopt-report-phase=par test.f
    $ dplace -x5 psrun -p ./a.out
    $ ls *.xml
    a.out.4.16904.eich1.xml
    a.out.3.16904.eich1.xml
    a.out.2.16904.eich1.xml
    a.out.1.16904.eich1.xml
    a.out.0.16904.eich1.xml
    $ psprocess  a.out.0.16904.eich1.xml
    
    ......
    Samples      Self%    Total%  Function  
         7922   87.82%   87.82%  L_jacobi__202__par_region0_2_137  
         1043   11.56%   99.38%  __intel_new_memcpy
           34    0.38%   99.76%  main$himenobmtxp_m_omp_$BLK
            6    0.07%   99.82%  _intel_fast_memcpy.J
    
    Samples     Self%  Total%   Function:File:Line
         1260  13.97% 13.97%   L_jacobi__202__par_:himeno_omp.f:215
         1162  12.88% 26.85%   L_jacobi__202__par_:himeno_omp.f:219
         1043  11.56% 38.41%   __intel_new_memcpy:??:0
          993  11.01% 49.42%   L_jacobi__202__par:himeno_omp.f:216
    .......
  • MPIプログラム
    MPIプログラムを解析するときはpsrunコマンドに-fオプションを指定してください。
  • ハイブリッドプログラム
    ハイブリッドプログラムを解析するときは、psrunコマンドに-fオプションと-pオプションを指定してください。
  • MPInside(MPIの通信時間を測る)
    MPInsideを使ってMPIルーチンの通信時間を知ることができます。
    コマンド名はMPInsideです。

    例)
    $ mpiexec_mpt -np 4 dplace -s1 MPInside a.out

    実行が終わるとカレントディレクトリに "mpinside_stats"というファイルが作成されます。
    .....
    >>>> Elapse times in (s) 0 1<<<<
    CPU   Comput   init     waitall  isend    irecv    barrier  bcast    allreduce
    0000 42.8395   0.0001   0.8088   0.9166   0.0817   0.0001   0.0001   0.1077
    0001 42.6846   0.0001   0.8629   0.9188   0.0706   0.0002   0.0161   0.1840 
    0002 42.5846   0.0001   1.0888   0.8851   0.0544   0.0002   0.0161   0.1294
    0003 42.6181   0.0001   0.9546   0.9162   0.0535   0.0002   0.0161   0.1331
    0004 42.4007   0.0001   1.1028   0.9472   0.0466   0.0003   0.0161   0.2360
    ......

    エクセルへコピーして面グラフで表示します。
    MPInside.jpg
  • 横軸がランク番号、縦軸が経過時間を表します。
  • MPIルーチンの実行時間が色分けされます。
  • 上図では、計算部分とMPI_Alltoallvの時間が大部分を占めていることがわかります。
  • MPIルーチンの実行時間には、実際の通信時間と待ち時間が含まれています。

添付ファイル: fileMPInside.jpg 238件 [詳細] filefirst_touch2.JPG 229件 [詳細] filefirst_touch1.JPG 235件 [詳細]

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