東京大学地震研究所地震火山情報センター

シングルプロセッサプログラムの最適化

シングルプロセッサプログラムの最適化についてご説明致します。

コンパイラ

  • ifort

    • Fortran 77 90 95をサポート
    • Fortran 2003の一部をサポート (詳細はリリースノートを参照下さい)
  • icc
    • Cをサポート
  • icpc
    • C++をサポート

IntelFortranCompilerはFortran77/90/95をサポートしますので、どの規格に沿って書かれたソースプログラムでもコンパイル可能です。Fortran95はFortran90に対して、Fortran90はFortran77に対して上位互換であるため、それぞれの規格が混在しているようなソースプログラムもコンパイルできます。


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


                                                Topへ戻る

データサイズ

           C
       bit      
      fortran
char
8
CHARACTER
short int
16
INTEGER(KIND=2)
int
32
INTEGER(KIND=4)
long int
64
INTEGER(KIND=8)
pointer
64
POINTER
float
32
REAL(KIND=4)
double
64
REAL(KIND=8)

コンパイルオプション

最適化オプション

  • 推奨するオプション

デバッグが終わり正しい結果が得られているプログラムに対して、推奨するオプションは

-O3 -xSSE4.2

です。積極的な最適化を行います。

  • 最適化レベルオプション

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

オプション
内容
-xSSE4.2
Xeon 7500番台向けの最適化を行い、SSE4.2命令を生成します。
  • 浮動小数点演算オプション

オプション
内容
-no-prec-div
除算を逆数の乗算にするなどの最適化が有効になります。
-no-prec-sqrt
より高速で精度が少し低い平方根計算を使用します。
-fpmodel  fast [=1|2]
浮動小数点データにより強力な最適化を有効にします。(デフォルトは1)

デバッグオプション

ここで紹介するオプションは、ifort で有効なオプションです。
オプション
Insert text here
-traceback  -g
Segmentation Faultなどのエラー終了時にエラーの発生箇所を表示します。
-traceback  -g 
-check  bounds
(-CB)
実行時に配列の領域外参照を検出すると、エラー終了し発生箇所を表示します。
3つのオプションを同時に指定してください。
-traceback  -g  -fpe0
オーバーフロー、ゼロ割り、不正な処理を検出するとエラー終了し、発生箇所を表示します。
アンダーフローはゼロに置き換えて処理を続行します。
3つのオプションを同時に指定してください。
(*)-gオプションを指定すると、デフォルトの最適化オプションが-O0になるのでご注意ください。

Intel64におけるメモリモデル

Intel64ビットコンパイラは32ビットの拡張版です。デフォルトでは、データの大きさとコードの大きさはそれぞれ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の制限はありません。

Topへ戻る

数値計算ライブラリ

Intelが提供するMKLとVisualNewmericsが提供するIMSLをご利用頂けます。旧システムでSGIが提供しておりましたSCSLはご利用頂けません。SCSLルーチンからMKLルーチンへの移行については、「旧システムからの移植について」を参照下さい。

MKL

MKLに含まれるルーチンは以下の通りです。

  • BLAS
  • BLACS
  • LAPACK
  • ScaLAPACK
  • PBLAS
  • スパースソルバ
  • VectorMathLibrary(VML):ベクトル数学ライブラリ
  • VectorStatisticalLibrary(VSL):ベクトル統計ライブラリ(乱数生成ルーチンを含む)
  • FFT
  • など
下記のようにMKLをリンクします。
  • シングルプロセス版
$ ifort -o a.out -lmkl_intel_lp64 -lmkl_sequential -lmkl_core
  • 並列版
$ ifort -o a.out -lmkl_intel_lp64 -lmkl_intel_thread -lmkl_core -liomp5

リンクオプション-mklを用いてリンクすることも可能です。
  • シングルプロセス版
$ ifort -o a.out -mkl=sequential
  • 並列版
$ ifort -o a.out -mkl=parallel

例1)
$ cat test1.f
     program test1
     real x(10), y(10), sdot, res
     integer n, incx, inxy, i
     external sdot

     n = 5
     incx = 2
     ncy = 1
     do i = 1, 10
        x(i) = 2.0e0
        y(i) = 1.0e0
     enddo
     res = sdot(n, x, incx, y, incy)
     print*,'SDOT = ', res
     stop
     end
 $ ifort  -O3 -xSSE4.2   test1.f  -mkl=sequential
 $ dplace ./a.out

 SDOT =    10.00000

例2)
$ cat rsi_pcg_f77_test.f
****************************************************************************
*
*Copyright(C)2001-2005IntelCorporation.AllRightsReserved
*Thesourcecodecontainedordescribedhereinandalldocumentsrelatedto
*thesourcecode("Material")areownedbyIntelCorporationoritssuppliers
*orlicensors.TitletotheMaterialremainswithIntelCorporationorits
*suppliersandlicensors.TheMaterialcontainstradesecretsandproprietary
*andconfidentialinformationofInteloritssuppliersandlicensors.The
*Materialisprotectedbyworldwidecopyrightandtradesecretlawsand
*treatyprovisions.Nopartof the Material may be used, copied, reproduced,
* modified, published, uploaded, posted, transmitted, distributed or disclosed
* in any way without Intel's prior express written permission.
* No license under any patent, copyright, trade secret or other intellectual
* property right is granted to or conferred upon you by disclosure or delivery
* of the Materials, either expressly, by implication, inducement, estoppel or
* otherwise. Any license under such intellectual property rights must be
*express and approved by Intel in writing.
*
****************************************************************************
*
*Ccontent:IntelMKLRCI(P)CGFortran-77example
*
****************************************************************************
*
C---------------------------------------------------------------------------
CExampleprogramforsolvingsymmetricpositivedefinitesystemof
Cequations.
C---------------------------------------------------------------------------
     PROGRAMrci_pcg_f77_test
     IMPLICITNONE
C---------------------------------------------------------------------------
CDefinearraysfortheuppertriangleofthecoefficientmatrixandrhsvector
CCompressedsparserowstorageisusedforsparserepresentation
C---------------------------------------------------------------------------
     INTEGERN,RCI_request,itercount,i
     PARAMETER(N=8)
     DOUBLEPRECISIONrhs(N),solution(N)
     INTEGERia(9)
     INTEGERja(18)
     DOUBLEPRECISIONa(18)
C..Fillallarrayscontainingmatrixdata.
     DATAia/1,5,8,10,12,15,17,18,19/
     DATAja
     1/1,3,6,7,
     22,3,5,
     33, 8,
     4 4, 7,
     5 5,6,7,
     6 6, 8,
     7 7,
     8 8/
     DATA a
     1 /7.D0, 1.D0, 2.D0, 7.D0,
     2 -4.D0,8.D0, 2.D0,
     3 1.D0, 5.D0,
     4 7.D0, 9.D0,
     5 5.D0, 1.D0, 5.D0,
     6 -1.D0, 5.D0,
     7 11.D0,
     8 5.D0/
C---------------------------------------------------------------------------
C Allocate storage for the solver ?par and the initial solution vector
C---------------------------------------------------------------------------
     INTEGER length
     PARAMETER (length=128)
     DOUBLE PRECISION expected(N)
     DATA expected/1.D0, 0.D0, 1.D0, 0.D0, 1.D0, 0.D0, 1.D0, 0.D0/
     NTEGER ipar(length)
     DOUBLE PRECISION dpar(length),tmp(N,4)
C---------------------------------------------------------------------------
CInitializetherighthandsidethroughmatrix-vectorproduct
C---------------------------------------------------------------------------
     CALLMKL_DCSRSYMV('U',N,A,IA,JA,expected,rhs)
C---------------------------------------------------------------------------
CInitializetheinitialguess
C---------------------------------------------------------------------------
     DOI=1,N
     solution(I)=1.D0
     ENDDO
C---------------------------------------------------------------------------
CInitializethesolver
C---------------------------------------------------------------------------
     CALLdcg_init(N,solution,rhs,RCI_request,ipar,dpar,tmp)
     IF(RCI_request.NE.0)GOTO999
C---------------------------------------------------------------------------
CSetthedesiredparameters:
CLOGICALparameters:
Cdoresidualstoppingtest
Cdonotrequestfortheuserdefinedstoppingtest
CdoPreconditionedConjugateGradientiterations
CDOUBLEPRECISIONparameters
Csettherelativetoleranceto1.0D-5insteadof default value 1.0D-6
C---------------------------------------------------------------------------
     ipar(9)=1
     ipar(10)=0
     ipar(11)=1
     dpar(1)=1.D-5
C---------------------------------------------------------------------------
CCheckthecorrectnessandconsistencyofthenewlysetparameters
C---------------------------------------------------------------------------
     CALLdcg_check(N,solution,rhs,RCI_request,ipar,dpar,tmp)
     IF(RCI_request.NE.0)GOTO999
C---------------------------------------------------------------------------
CComputethesolutionbyRCIPCGsolver
CReverseCommunicationsstartshere
C---------------------------------------------------------------------------
     1CALLdcg(N,solution,rhs,RCI_request,ipar,dpar,tmp)
C---------------------------------------------------------------------------
CIfRCI_request=0,thenthesolutionwasfoundwiththerequiredprecision
C---------------------------------------------------------------------------
     IF(RCI_request.EQ.0)THEN
GOTO700
C---------------------------------------------------------------------------
CIfRCI_request=1,thencomputethevectorA*tmp(:,1)
Candputtheresultinvectortmp(:,2)
C---------------------------------------------------------------------------
     ELSEIF(RCI_request.EQ.1)THEN
     CALLMKL_DCSRSYMV('U',N,A,IA,JA,TMP,TMP(1,2))
     GOTO1
C---------------------------------------------------------------------------
CIfRCI_request=3,thencomputevectorpreconditionermatrixontmp(:,3)
Candputtheresultinvectortmp(:,4)
C---------------------------------------------------------------------------
     ELSE IF (RCI_request .EQ. 3) THEN
     CALL DCOPY(N, TMP(1,3),1, TMP(1, 4), 1)
     GOTO 1
     ELSE
C---------------------------------------------------------------------------
CIfRCI_request=anythingelse,thendcgsubroutinefailed
Ctocomputetheolutionvector:solution(N)
C---------------------------------------------------------------------------
     GOTO999
     ENDIF
C---------------------------------------------------------------------------
CReverseCommunicationendshere
CGetthecurrentiterationnumber
C---------------------------------------------------------------------------
700CALLdcg_get(N,solution,rhs,RCI_request,ipar,dpar,tmp,
&itercount)
C---------------------------------------------------------------------------
CPrintsolutionvector:solution(N)andnumberofiterations:itercount
C---------------------------------------------------------------------------
     WRITE(*,*)'Thesystemissuccessfullysolved'
     WRITE(*,*)'Thefollowingsolution obtained '
     WRITE(*,800)(solution(i),i =1,N)
     WRITE(*, *) ' Expected solution '
     WRITE(*,800)(expected(i),i =1,N)
800 FORMAT(4(F10.3))
     WRITE(*,900)(itercount)
900 FORMAT(' Number of iterations: ',1(I2))
     GOTO 1000
     999 WRITE(*,*) 'Solver returned error code ', RCI_request
     STOP
1000 CONTINUE
     read *
     END

IMSL

コンパイル・リンク方法
$ ifort  -o  実行モジュール名  $FFLAGS  ソース名  $LINK_FNL
リンク用環境変数$LINK_FNLを変更することによって、別のリンク方法でリンクできます。
環境変数
内容
$LINK_FNL
sharedリンク + Intel MKL使用 OpenMPの並列化
$LINK_FNL_STATIC
static  リンク + Intel MKL使用 OpenMPの並列化
$LINK_FNL_IMSL
sharedリンク + IMSL BLAS使用
$LIMK_FNL_STATIC_IMSL
staticリンク + IMSL BLAS使用

MPIプログラムの場合
$  ifort  -o  実行モジュール名  $FFLAGS  ソース名  $LINK_MPI
リンク用環境変数$LINK_MPIを変更することによって、別のリンク方法でリンクできます。
環境変数
内容
$LINK_MPI
MKLを使用 MPI並列化しているIMSLルーチンを呼び出すときに使用する
$LINK_MIPS
MKLを使用 MPI並列化したプログラムから逐次処理のIMSLルーチンを呼び出すときに使用する
$LINK_MPI_IMSL
IMSL BLASを使用 MPI並列化しているIMSLルーチンを呼び出すときに使用する
$LINK_MIPS_IMSL
IMSL BLASを使用 MPI並列化したプログラムから逐次処理のIMSLルーチンを呼び出すときに使用する


Topへ戻る

時間計測関数

Fortranの関数

dclock関数、etime関数をご紹介します。

dclock関数
0時00分からの経過時間を秒単位で返します。返値はreal*8 型です。

real(KIND=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  -xSSE4.2 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 -xSSE4.2  -o  a.out  test3.f  dclock.o
$ dplace  ./a.out

 time :   3.01569199562073

上記の例のように、fortranプログラムと共にdclock.cをリンクすると、fortranライブラリのdclock関数ではなく、dclock.cで呼び出しているgettimeofdayで時間計測を行います。

etime関数
プログラムの始めからのCPU時間を秒単位で返します。
配列の1番目の要素にユーザ時間、2番目の要素にシステム時間を返します。
自動並列化/OpenMP並列化プログラムを計測すると、プログラム全体のCPU時間を返します。

real*4time1,etime
real*4tarray(2)
time1=etime(tarray)

例)
$ cat test4.f

     program test4
     real*4 etime, time4, tarray(2),t1,t2
     t1 = etime(tarray)
     call sub()
     t2 = etime(tarray)
     print *, t2, t1, tarray(1), tarray(2)
     end

C/C++の関数

gettimeofday
1970年1月1日00:00:00からの経過時間をマイクロ秒単位で計測します。
返値は整数型で、実行に成功すれば0、失敗すると-1を返します。

#include<sys/time.h>

structtimevaltp;
structtimezonetzp;
gettimeofday(&tp,&tzp);
例)
elapsed.cは時間を秒単位で返すルーチンです。
$ 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)
}


Topへ戻る

性能解析ツール

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_
    110      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


MFLOPS値を測る


XeonプロセッサX7500番台では、浮動少数点演算にSSE4.2命令を採用しています。SSE命令は4つの単精度演算、または2つの倍精度演算を1命令で行います。従って、カウントされる演算数は実際の演算数よりも少なくなります。より正確な浮動少数点演算数をカウントしたいときには、コンパイル時にSSE4.2命令を無効にする-no-vecオプションを指定してください。(-xSSE4.2が指定されていなくても-no-vecオプションが必要です)
-xSSE4.2と-no-vecが同時に指定されたときには、-no-vecが優先されます。

-no-vecオプションは実行性能が落ちる場合がありますので、性能解析が終わりましたら、指定をはずしてください。

例)
$export PS_HWPC_CONFIG=${PS_DIR}papi3_mflops.xml
$dplace psrun ./a.out
実行が終わるとカレントディレクトリに解析結果ファイルが作られます。

$psprocess  a.out.78249.eich1.xml
解析結果ファイルの内容が出力されます。

Index Description                    CounterValue
===================================
   1Floatingpointoperations.......106322612754
   2Totalcycles.........................149762713500

EventIndex
===================================
   1:PAPI_FP_OPS        2: PAPI_TOT_CYC

Statistics
===================================
Counting domain...............................user
Multiplexed.........................................no
Floatingpointoperationspercycle.........0.710
MFLOPS(cycles)...........................1893.489  <---- MFLOPS値
MFLOPS(wallclock).......................1872.271  <----MFLOPS値
CPUtime (seconds)........................56.152
Wall clock time (seconds)................56.788
% CPU utilization...........................98.879


Topへ戻る