FORTRN90の高速化のための手法

プログラミング手法は、コンパイラオプションの最適化のレベルを上げることによってコンパイラが自動的に修正してくれる可能性があるが、作成する段階でコンパイラに頼らず、工夫しておいたほうが良い性能が得られるであろう。また、コンパイラによって、最適なプログラミングは流儀が違うのでマニュアルを確かめる必要がある。ここではDEC(現compaq)-αシリーズのコンパイラを例とする。また、高速化する必要があるのは、少なくとも5分程度以上計算時間がかかるものに限られる。

  1. メモリーを多用すること
    1. 出入力(画面出力も含む)はプログラムを最も遅くする処理である。出力する情報は必ず一旦メモリに落とし、計算の最後にファイルに落とす。この処理にするだけで性能は格段に上がる。
    2. アロケーションは多めに取っておいてデアロケーションはしない。配列が想定される大きさを超えた場合はエラーになるルーチンを入れておけばよい。最大配列サイズと、現在使っている配列サイズを使い分ければ問題ない。
  2. 深いルーチン、深いIF文は作らない。高次元配列は避ける。
    プログラムのミスにもつながるし、コンパイラがうまく高速化してくれないかもしれない。また、知らない内に演算量が莫大になることがあるので注意が必要
  3. 可能な限り、数値計算ライブラリの高速ルーチンを使う。
    数値計算ライブラリーをハードに合わせてチューンしている場合があるので、自作は絶対かなわない。Compaq-Fortranには、cxmlライブラリがついている。-cxmlをつけてコンパイルすれば使用可能である。例えばFFT、連立一次方程式、逆行列などは必ずライブラリを使おう。
  4. 時間がかかる関数・割り算・べき乗の計算は極力さける。
    ・割り算の回数を減らす。 /2.0d0 --> *0.5d0
    ・sinθ を計算したら、cosθはsinθから計算する。sin2θは加法定理を使う。
    ・acos などはなるべく使わず、rad系で計算する
    ・**はなるべく使わない。aa**2.0d0 --> aa*aa
  5. 5、配列は順序がある。先頭を大きいものから(データ構造の観点より有利)
    a(1,100,10) --> a(100,10,1)
    a(1,3,500) --> a(500,3,1)
  6. 二度手間計算は避ける
    (遅)
    do i = 1,10
    rc1 = d1 / dsin(fai)
    enddo

    (速)
    sinfai=1.0d0/dsin(fai)
    do i = 1,10
    rc1 = d1 * sinfai
    enddo

  7. 異なる種類の数を演算しない
    aa = dsita * i --> aa = dsita * float(i)
    (double)*(integer)
  8. コンパイラオプションの例
    Compaq-α
    %fort -fast *.f
    Intel
    % ifc -O3 -tpp7 -xW -Vaxlib
  9. 数値計算パッケージを利用する際のコンパイル
    Compaq-α
    %fort -fast -lcxml *.f
    Intel
    % ifc -tpp7 -xiMKW -O3 prog.F90 -o prog -L/opt/intel/mkl/lib/32/ -lmkl_lapack -lmkl_p4 -lpthread