- 目次
- はじめに(謝辞)
- OpenMPとは
- OpenMP導入に関するメモ
- 古い情報
本ページではSMP環境(共有メモリ)で並列化を実現できる共有仕様
OpenMPによる第一原理電子状態計算プログラムの並列化について話ていきたい
と思います。
今回のOpenMPによる並列化は、基本的に本研究所の共通計算機導入過程にお
けるベンチマークテストにおいて、SGI(日本シリコングフィックスクレイ
←当時)社によって提出された資料(その他に一部COMPAQ〔旧DEC〕
社〔←当時↓〕によるものも参考にしている)を元にしています。ここに、S
GI及びCOMPAQ(旧DEC)の関係各位(営業、技術者の方々)に深く
感謝します。また、SGI社には本ウェブページへのベンチマークテスト結果
に関して快く掲載許諾してくれたことにも深く感謝する次第です。
まず、OpenMPに関してのウェブページとして、www.openmp.orgサイトがあります。
そのものずばりという感じで、OpenMPに関しての詳細で豊富な情報が入手出
来ます。
(SGI)
2009年4月から物質・材料研究機構のスーパーコンピュータが更新され、
新たにSGIのマシンが導入された。これを機に、筆者の持つバンド計算プロ
グラムコードを本格的に並列化対応させることを決めた(並列化に関してスパ
コン担当のSGIの方々の助言に深く感謝)。並列化は、ずっと以前に富士通の
VPPで行なった経験があるが、今回のマシ
ンにこれを適用すことは出来ない(VPP用の並列化指示注釈行は解釈出来な
い)。今回は、OepnMPによる並列化を行なうことにした。OpenMPによる並列化
は、並列化を指示する注釈行を、FORTRANのソースコードの当該箇所に挿入す
ることによって実現される。このため並列化出来ない環境下での流用も可能で
あるし、デバッグもし易い(並列計算、非並列計算の比較がし易い)。
既にサブルーチン、FORCE, FORZFB, KBINT, DIAGON, CHAVER, MSDについて、
OepnMPによる並列化指示行を加え、並列化をほぼ完了させた。OpenMP化におい
て、使用した並列化指示注釈行(例)は、
!$OMP THREADPRIVATE( /PSSNL/ )
(中略)
!$OMP PARALLEL DEFAULT(NONE)
!$OMP& COPYIN( SNL )
C!$OMP& FIRSTPRIVATE( )
!$OMP& PRIVATE( CS,CP,CD, I1,I2, L1,L2,L3, MM, IIBA, IIKB,
!$OMP& AKX,AKY,AKZ, LNUM,NNN, II, PPMT,
!$OMP& ZVN, ZZZ, ZAAA, PPM, IJG, EG,
!$OMP& ZAWORK,WWW,ZWW,ICON, KBAS,KGB,IOPT,EPS )
!$OMP& SHARED( KV3, WS,WP,WD, PAI4, GR, IG1,IG2,IG3, IGPO,
!$OMP& VX,VY,VZ,IBA,IBA2,NBASE,NBMAT,NBD1,NBD2,
!$OMP& ZCHGO, ZVXC, ZPSCC, ZFM3, ZZ2,EKK,
!$OMP& UNIVOL, KX1,KY1,KZ1, GX,GY,GZ, NLSPD )
!$OMP DO
(中略)並列化対象部分(k点に関するループ)
!$OMP END DO
!$OMP END PARALLEL
のようになる。FIRSTPRIVATEは、サブルーチンによって使う場合と使わない
場合がある。また上記以外に、CHAVERでは、!$OMP CRITICALと、!$OMP END
CRITICALを使用する箇所があった。FORCEサブルーチンでは、
REDUCTION(+:ZFORC2)を使用。CRITICAL, REDUCTIONは、k点に関しての和を正
しく計算するために必要な並列化指示。
PARALLEL DEFAULT(NONE)にしておくと、並列化対象部分内の全ての変数を、
PRIVATEかSHAREDに定義しておく必要があるが、定義洩れを探すには便利(コ
ンパイル時に未定義エラーが出る)である。DO 100 I=1,100(DOループ)にお
ける変数、"I"などはDEFAULT(NONE)でもPRIVATEとして解釈されるので、書い
てなくてもコンパイルは通る。
バンド計算においては、k点のループが最も独立性が高く、並列化もし易い
ので、今回もk点に関するループで並列化を行なった。OpenMPでは、並列化に
よってそれぞれ並列で動く部分をスレッドと呼んでいる。筆者が使用する環境
では、その各スレッドが各CPUに相当している。既に述べたように、並列化
したサブルーチンは、FORCE, FORZFB, KBINT, DIAGON, CHAVER, MSDである
(4/27、2009現在)。いずれも、k点に関してのループがあり、それ
が計算の大部分を占める。これは、VPPでも同様に並列化している。
今回(5/1、2009)OpenMPで並列化したサブルーチンの内容はそれぞれ、FORCE, FORZFB, KBINT, DIAGON, CHAVER, MSDとなります。
↑これらのプログラムソースは、無保証です(自己の責任において
参照、使用、利用して下さい)。筆者は、これらソースコードの使用、利用、
流用等によって生じる不利益、損害等に一切の責任を負いません。
"!$OMP"が、OpenMP並列化指示行。"C!$OMP"は、それに対する注釈(コメン
ト)になっていて、これは並列化に関与しません。筆者による並列化は場当り
的な部分がまだあり、必ずしも並列化が効率的、効果的でない部分(特にメモ
リに関して→データ分割が不十分、或いはデータ分割になっていない)があり
ます。
- (メモ1)新たに問題発生(解決)。
↑まだ確定的ではないが、おそらく問題点はk点に関する和の扱いの部分と
考えられる。力や電荷密度は、k点に関しての足し上げが必要。今回、電荷密
度は問題ない。問題となっているのは力の値。並列化計算によって得られる力
が微妙におかしい。正し結果との数値的な差は小さいが、有意に問題がある。
更に、更に問題を厄介にしているのは、テスト段階の計算では、力の値に問題
が生じない(ように見える。←並列、非並列で結果に差がない)。結果がおかしい場合に対し、ある対処法
を試行の結果、解決(力の計算←"REDUCTION")。
- (メモ2)並列化によって顕在化する問題あり。
- (メモ3)VPP用に作成したコード部分が、今回は使えない(←コードの
修正が必要)。並列化処方そのものは、VPPの場合とそう変わらない。
- (メモ4)フォートランコンパイラは、Intel FORTRANコンパイラ+Intel
MKL(Math Kernel Library)を使用。
- (メモ5)コンパイルオプション: -r8 -O3 -mcmodel=medium -i-dynamic -lsvml -openmp -lmkl - lguide -lpthread ← "-mcmodel"は大きな配列変数を扱う場合に必要。
↑"-openmp"が、OpenMP用のコンパイルオプション。
↑並列化とは直接関係ないが、-xSSE4.2というオプションを付けると速くな
る場合あり(使用する機種〔CPU〕等に依存)。
- (メモ6)残念ながら自動並列化(-parallelオプション)、並列化支援ソ
フト(コードを解析して、OpenMP用並列化指示行を挿入してくれるもの)は、
ほとんど役に立たないか、効果がなかった。強制的な指示を与えても並列化指
示行挿入しなかった(出来なかった)。
- (メモ7)OpenMP化は、正直試行錯誤による”場当り”的な対処による部分
あり。
- (メモ8)スタックの設定が必要な場合あり。←計算規模(PRIVATEで使用
する変数)を大きくしていくと既定値では足りなくなる。スタックが足りない
と、計算が途中で止まる(これは使っている計算環境、種類に依存すると思わ
れる)。止まった場合はスタックのサイズの設定をより大きくする(←
PRIVATEで使用する変数から見積り可能)。
- (メモ9)そもそも、OpenMPによる並列化は、少なくとも筆者のコードでは
大変メモリを浪費する。並列化の利点は、高速化(←これはそこそこ達成して
いる)以外により大きなメモリを使用可能にすることだが、現時点で筆者の並
列化コードはそうなっていない。
- (メモA)↑k点数を大きくしていくと、1CPUだけの計算では流れる計
算が、並列でメモリオーバーで止まる。
- (メモB)並列化でのCPU数(スレッド数)を増やしていくと、ある程度
以上数でむしろ遅くなる。←メモリ(本当の意味での共有ではない?)のアク
セスが足を引っ張る?。←並列計算するCPU数(スレッド数)を大きくする
と、むしろ遅くなる。
- (メモC)サブルーチンMSDのみを並列化させて実行させると、実行結果と
しての数値がおかしくなる(1CPUのみの実行〔非並列〕にすると正しい値
になる)。サブルーチンFORZFBも同時に並列化すると、値は正しくなる。原因
は現在調査中(6/3、2009)。
↑原因となる部分は判明。解決方法も存在。但し、何故この方法で正しい結
果を与えるのか判然としない。更にこの方法では、よりメモリを消費すること
となり、あまり良い解決策とは言い難い。解決方法:MSD以外に、FORZFBも並
列化させて実行させると正しい結果となる。どうもSNL配列を、THREADPRIVATE
にしておくことが必須な模様(←SHAREDにしたら正しい結果を与えない。更に、
THREADPRIVATEにしておけば、そのルーチンを実行しなくても正しい結果とな
る〔←非並列で等価なルーチンで実行〕)。
(追記:2/2、2016)新しい版のプログラムをOpenMPによって並列化
することを試みたところ、上記と同じ状況に遭遇した。サブルーチンMSD単独
で並列化を試みようとしたが、一向に数値が正しいものにならなかった
(sequentialでコンパイルした実行結果は正しい)。結局、サブルーチン
FORZFBで、SNL配列をTHREADPRIVATE指定すると、正しく動くようになった。こ
の時、FORZFBはこのTHREADPRIVATE指定だけでループの並列化は行なっていな
い。
(追追記:3/14、2016)電子状態計算のみでは、上記の
THREADPRIVATE指定だけで正しい結果を与えていたが、構造最適化を行なう段
階で全エネルギーが一致しなくなることが判明した。THREADPRIVATE指定以外
で、サブルーチンFORZFB部分を並列化対応させると正しい全エネルギーを与え
るようになった(どうしてこれでうまくゆくのかはまだ判然としていない。←
ひょっとしたらEQUIVALENCE関連〔配列〕かもしれない。←EQUIVALENCEは関係
なかった〔3/16、2016〕)。
- (メモD)どうも並列化した個々のサブルーチンは、相互に関係してるよう
に見える。並列化したサブルーチンMSDを単独で導入して動かすと、数値が一
致しない部分が生じる(収束値は一致する)。
そもそも積木を積むようにサブルーチン毎に並列化を行なったが、これには”
場当り”的な部分があった。更に、段階的に並列化した結果、全体としては正
しい結果を与えるが、個々の並列化されたサブルーチン単独では正しく動作し
ない可能性があることが判明した。各サブルーチンの並列化は独立に行なわれ
ているはずだが、互いに影響している可能性がある(←本当は”おかしい”)。
現段階では”だましだまし”使っていくしかない(←これで正しい結果を与え
ていることは確認)。更なる調査、検証が必要。
- (メモE)DIAGON,MSDサブルーチンにおいて、並列k点ループ内でZAJに直
接代入を行なうと、結果が正しくなくなる。PRIVATE,SHARED,THREADPRIVATE、
その他どのような設定でも正しい結果にならない。1CPUのみの実行では正し
い結果となる。ZAJと等価な配列を別途定義(COMMONでも、ローカルな定義で
もいずれでもOK)して、並列k点ルーチン内で、その別の配列に代入等を行
ない、並列ルーチンの外で、”ZAJ = 別の配列”で代入すると問題なく正しい
結果となる。但しこれは大変メモリーの無駄となる。今回(10/15、20
09)新たに改良ルーチンを考え試してみるも、現時点で失敗続き。うまく動
かない。
↑テスト段階では、うまく動くようになる。変更点は、FIRSTPRIVATEを使用
したこと。これで一気に解決した。MSD,DIAGONに関して改良を施したプログラ
ムでより実践的な場合の計算テストを開始。ZAJの変わりに、ZT1(但し、ZAJ
よりずっと小さい配列←並列数分)で並列計算を行なう(10/15、200
9)。
↑実践段階でも正しいことを確認(10/16、2009)。
↑残念ながら、省メモリとしては失敗だった。当該部分は省メモリになって
いるが、実際にメモリ不足で問題となっている部分は全く別の箇所だった(1
0/19、2009)。←勉強が足りない。
↑結局、並列化とは関係ないところで、省メモリ化出来た(←最初に用意す
る初期固有ベクトル生成のための対角化の行列を、平面波基底数の1/2から
1/4にした)。THREADPRIVATEは必須なのか?。更なる検討が必要(10/
30、2009)。
- (メモF)スパコン以外のPC上でも、KMP_STACKSIZEの指定が必要。OSやシェ
ルによって指定の仕方は異なる。筆者の場合は、setenv KMP_STACKSIZE '
128m'としている(Linux、tcsh)。unlimitだけでは動かなかった(セグメン
トエラーで止まる)。
- (メモG)少しメモリに関して進展あり。まだ検証中ながらプログラム
の版によっては、更なる省メモリ化が可能であることが判明。ZAJ、ZZZを
EQUIVALENCEにしても正しく計算出来ることが分かった(サブルーチンMSD上)。
実は、これによって大幅な省メモリ化となる(4/5、2010)。←検証中
(何故、版によってEQUIVALENCEが有効なのかもよく分かっていない)。
- (メモH)OpenMPとは直接関係はないが、最近HP社のZ400という機種を
導入、それにIntel FORTRAN ver. 11を導入した(大変苦労、消耗した)ので、
これをここに記しておきたい。
- 機種: Z400(HP)、ソフトウェア: Intel FORTRANコンパイラー 11.1
Linux版。
- 試したOS:Vine Linux 5 (32 bit, 64 bit)、SUSE Linux (64 bit)、
Fedora Core 12 (32 bit, 64 bit)など。目的は、Z400にIntel FORTRANコンパ
イラー(64 bit版、EMT-64用)を導入(インストールして正しく動作させる)
ことである。従って、32 bit版のOSは、テスト用などの目的で試用した。結局、
最終的に目的を達成したのは(筆者の場合)、Fedora Core 12 (64 bit)のみ
であった。他は、Intel FORTRANコンパイラーが導入出来なかったり、OSの導
入(インストール段階)で失敗したりした。
- 各OSは、それぞれの配布サイトからisoイメージをダウンロード、DVD
等に書き込んだ(書き込みの種類に注意。単なるデータ、ファイルとしてのコ
ピーではない)。この時、当然書き込み可能な、DVD/CD装置が存在、使用出来
ないといけない。
- Intel FORTRANコンパイラー導入時のエラーは、libstdc++,
libstdc++5, glibc, libgcc(ライブラリ)の32 bit版が無いというものだっ
た。これらのライブラリの導入は、(筆者にとって)本当に大変だった。
- Fedoraでは、yumと言うコマンドで導入が出来た。yum install
compat-libstdc++-33。yum.conf(/etc)の設定し直しが必要。他に、yum
install libstdc++、yum install libstdc++.so.5を実行(この二つがいずれ
も必要かどうかは未確認。少なくとも筆者野場合、後者は必要だった)。
- オンライン上の情報は大変有用かつ、決定的だったが、類似した情報
が多く、最終的な目的情報に辿り着く(気が付く)までかなり苦労した。
他のOSでは、apt-getというコマンドが使えるが、筆者の場合ではうまく動
かなかった(途中で挫折)。
- Intel FORTRANは以前の版(バージョン)と、ライセンスの認証の仕
方が異なる。
- Fedora Core 9 (64 bit版)でも、Intel FORTRAN 11.1のインストー
ルに成功した(導入可能)。事前に、yumで必要なライブラリをインストール
しておいた(3/8、2010)。
- Fedora 22 (64 bit版)でも、Intel FORTRAN 11.1のインストールに
成功。CDの場所は、/mediaではなく、/run/mediaだった。他は、これまでの手
順とほぼ同じ要領でできた(2/4、2016)。
- ネットワーク設定も重要。画面が狭くて、"OK"ボタンが出てこない時、
tabキーで移動させてリターン。
- SElinuxの設定(Fedoraの場合、"permissive")。←(備忘)後で元
に戻す。
- ディスプレイ設定がうまくいかず、800x600で作業。Fedoraではこれ
で最初、インストール途中で画面が真っ暗になり、にっちもさっちもいかなく
なった。何か最初のブート時の選択で2番目(basicな画面設定?)を選ぶと
OKとなる。
- ケーブル(特にディスプレイ関連)の問題(ピン数)。
- 参考文献は、日経Linux(日経BP社、付録DVD等も含む)など。
- オンライン等を含め有用な情報などに深く感謝(3/4、2010)。
- MKLへのリンクに失敗する。ld: cannot find -lmklと言われる。勿論、
LD_LIBRARY_PATHなどはちゃんと設定してある(はず)。一応、これはオンラ
イン上の情報から1CPU動作(非並列)では正しく動かすことに成功。しか
し、-openmpオプションではどうなるか?(規模が小さな系ではOK)。
- ↑参考
サイト(インテルのMKL link line advisorのページ)を発見。このペー
ジにある、各選択肢を選んでいくと、必要なライブラリを表示して(書き出し
て)くれる(有用)。一応、書き出された内容でMakefileを作成、コンパイル
+リンクは通った。現在、実行検証中(3/5、2010)。
- ↑必要なライブラリの設定で、intergers lengthは、32 bitを選択す
る。64 bitだと筆者の環境では、正しく動かない(3/8、2010)。
- (メモI)[msd版]24GBメモリ、8CPU並列で、80回/24時間、[omp版]48GBメモリ、8CPU並列で、401回/8時間半。→およそ14倍の速度差がある。msd版は、省メモリ版のプログラムで並列化率は低い。omp版は、メモリを浪費するが並列化率は高い(10/18、2010)。
- (メモJ)新しいバージョンでは、REDUCTIONで配列変数が指定出来る
模様。オンライン上の資料等を調べてみると、確かに”スカラー変数”のみと
いう記述も散見されるが、10年以上前の資料(にあるバージョン)でも配列
変数が使用可能という記述があり、相当古いバージョン(版)以外は問題なさ
そう(10/20、2011)。
- (メモK)(共用)機種更新により、Intel FORTRANコンパイラや、MKLのバージョンが更新された。途端に、OpenMPの並列計算の結果が合わなくなった。第1回目の全エネルギーは一致するが、2回目以降一致しなくなる。十分に収束させた値は、十分(?)に一致する。コンパイラのオプションをいろいろ変えて試してみたが症状は変わらなかった。で、"$OMP"の部分を見て、註釈化("C$OMP")されていた部分の1行に注目し、その註釈を外して計算したところ、値が一致するようになった(この時の一致の基準は、1CPUのみでの単一実行の結果)。外した、$OMP文は、COPYINだった。因に、この註釈は、以前の機種、バージョンでは、註釈があっても、なくても同じ結果となること(勿論、単一実行結果と一致の意味)も確認した(3/17、2020)。
(追記)Intel FORTRANコンパイラとは異なるコンパイラで、コンパイルすると、当該するCOPYINの註釈を外すとエラーとなる(3/25、2020)。
↑ただ、他のコンパイラで、コンパイルすると、並列計算では正しい結果を与えない(1CPUのみでも、openmpオプションでコンパイルしてあると駄目)。openmpオプションなしの単一CPU動作では正しい結果を与える。更に検証を継続中(3/30、2020)。
- (メモL)新しいプログラムの並列化を試みた。規模の大きなサブルーチンに、2つ並列化可能なループが存在し、両方に並列化を試みた。結果として、より規模の大きいループの、OpenMPによる並列化に成功した(5/15、2020)。
計算条件に依存するが、あるテスト計算全体(当該並列化部分以外の計算時間も含む)での高速化は、3.5倍計算時間を短くできた。更に、当該並列化部分のみで考えれば、48並列でおよそ28.5倍の高速化(概算値)が達成された(5/20、2020)。
並列化させるループの規模は、全原子数×全k点数×全バンド数×平面波数×原子メッシュ数とかなり大きなループ。これのk点ループに関して並列化を施した(5/21、2020)。
(メモ:無保証)並列化されるループ内で代入される変数→PRIVATE
(メモ:無保証)上記以外で、並列化されるループ内で(初期値が)不定になると困る変数→SHARED
↑全てがそうという訳ではない(5/26、2020)。
(メモ:無保証)REDUCTION対象が複数の場合:"DO REDUCTION(+:A),REDUCTION(+:B)"でOK(6/4、2020)。
- (メモ∞)↑以上、メモC、Dより、これら各サブルーチンで使用されている並列化指示注釈行部分に関して、(FORTRANソースコード部分も含めて)全くの無保証です。
- (参考サイト)
- [Club-HPC](Club-HPCのペー
ジ。大変参考になる)←現在、アクセス不能(10/24、2012)
(COMPAQ)
COMPAQマシン上でのコンパイルは、オプションで-ompと指定すると
OpenMP用の並列化指示行を加えたソースプログラムを解釈して並列実行させる
ことが可能です。
動作環境は、本所COMPAQのalphaチップマシン(SMPマシン)です。
それは最新のFORTRAN90コンパイラが備わっており、それはOpenMPに対応して
います(COMPAQ〔旧DEC〕のDigital FORTRAN90コンパイラでは、
ver5.1以降から、-ompオプションに対応しています。また、このバージョンの
コンパイラが動作するためにはver4.0以上のDigital UNIX OSが必要です)。
このオプション-ompが使用できるのは(ここでは)f90(つまりFORTRAN90対
応コンパイラのみ)で、f77(FORTRAN77コンパイラ)ではOpenMPとして並列化
実行ファイルは作成できません。コードそのものは77仕様でも、それに
OpenMP用並列化指示行を挿入してf90でコンパイルすることは可能で(f90は7
7仕様のコードも通す)、それによって生成された実行形式ファイルは、並列
で実行可能です。
(↓古い情報2↓〔SGI関連〕:今後大幅改訂予定)
ベンチマークテストにおける計算環境は、
SGIのOrigin2000システムで、CPUはMIPS R10000で、全プロセッサ
数は32です。
筆者のプログラムrevpe_d.fにOpenMPによる並列化指示行を加えたコードを
どのようにコンパイル、実行させたかは、以下のmakefileの内容を参照して下
さい。
SHELL= /bin/csh
#
# makefile - Generated Jun 01, 1998 by fmaker V1.3 BMTOOLS (C)1992
#
BIN = a.scs
MP = -mp -mpio
FFLAGS = -c -O3 -r8 -OPT:IEEE_arith=3:ro=3
LFLAGS = -w -O3 -r8 $(MP) -Wl,-Xlocal,work8_,-Xlocal,div_,-Xlocal,nonlc_,-Xlocal,recip_
CF77 = f77
LIB = -lscs_mp -lfastm
SRC= \
apbo2.f basnum.f bccm.f c2fft.f c3fft.f chaver.f chgavr.f chobsd.f \
clockm.f conv2.f dffctr.f diagon.f dlgama.f dsj0.f dsj1.f dsjn.f \
dsjnv.f energy.f erf.f evin.f evou2.f evout.f ewvec.f ewvmd.f \
fccm.f fermi.f force.f forces.f forloc.f form.f forzfb.f gsfsca.f \
gstep1.f gstepf.f gstsca.f hexm.f hpsort.f infout.f input1.f intchg.f \
kbint.f kbmat.f kpmsf.f kpmwbz.f kstep.f latsca.f lattic.f main.f \
md.f mffta4.f mffta5.f mffta6.f mffta7.f mffta8.f mffta9.f mfftb4.f \
mfftb5.f mfftb6.f mfftb7.f mfftb8.f mfftb9.f mfftc4.f mfftc5.f mfftc6.f \
mfftc7.f mfftc8.f mfftc9.f mfftdm.f mfftds.f mfftdv.f mfftim.f mfftis.f \
mfftiv.f mfftom.f mfftov.f mfftp.f mfftp1.f mfftp2.f mfftp3.f mfftp4.f \
mfftrd.f mfftri.f mfftrp.f mfftz0.f msd.f opgr.f opmtrx.f pcc.f \
pselmd.f pseudo.f r2fft.f r3fft.f sccm.f simp.f stress.f strnl.f \
symm.f symsca.f tetrah.f time.f width2.f xcfft.f xstpc.f
OBJ= \
apbo2.o basnum.o bccm.o c2fft.o c3fft.o chaver.o chgavr.o chobsd.o \
clockm.o conv2.o dffctr.o diagon.o dlgama.o dsj0.o dsj1.o dsjn.o \
dsjnv.o energy.o erf.o evin.o evou2.o evout.o ewvec.o ewvmd.o \
fccm.o fermi.o force.o forces.o forloc.o form.o forzfb.o gsfsca.o \
gstep1.o gstepf.o gstsca.o hexm.o hpsort.o infout.o input1.o intchg.o \
kbint.o kbmat.o kpmsf.o kpmwbz.o kstep.o latsca.o lattic.o main.o \
md.o mffta4.o mffta5.o mffta6.o mffta7.o mffta8.o mffta9.o mfftb4.o \
mfftb5.o mfftb6.o mfftb7.o mfftb8.o mfftb9.o mfftc4.o mfftc5.o mfftc6.o \
mfftc7.o mfftc8.o mfftc9.o mfftdm.o mfftds.o mfftdv.o mfftim.o mfftis.o \
mfftiv.o mfftom.o mfftov.o mfftp.o mfftp1.o mfftp2.o mfftp3.o mfftp4.o \
mfftrd.o mfftri.o mfftrp.o mfftz0.o msd.o opgr.o opmtrx.o pcc.o \
pselmd.o pseudo.o r2fft.o r3fft.o sccm.o simp.o stress.o strnl.o \
symm.o symsca.o tetrah.o time.o width2.o xcfft.o xstpc.o
$(BIN): $(OBJ)
f77 $(LFLAGS) -o $(BIN) $(OBJ) $(LIB)
.f.o:
$(CF77) $(FFLAGS) $*.f
msd.o: msd.f
$(CF77) $(FFLAGS) $(MP) msd.f
diagon.o: diagon.f
$(CF77) $(FFLAGS) $(MP) diagon.f
kbint.o: kbint.f
$(CF77) $(FFLAGS) $(MP) kbint.f
kbmat.o: kbmat.f
$(CF77) $(FFLAGS) $(MP) kbmat.f
force.o: force.f
$(CF77) $(FFLAGS) $(MP) force.f
forzfb.o: forzfb.f
$(CF77) $(FFLAGS) $(MP) forzfb.f
chaver.o: chaver.f
$(CF77) $(FFLAGS) $(MP) chaver.f
clean:
-rm -f core
clobber: clean
-rm -f $(BIN) $(OBJ)
void:
-rm -f makefile $(SRC)
残念ながら以上は、SGI社内におけるベンチマークテスト用のものであり、
筆者はSGI製のSMPマシンを利用できないので、これを実際に自分で検証
することはできていません。
(オプションの簡単な説明)
-r8:倍精度化オプション、REAL、COMPLEXをREAL*8、COMPLEX*16として扱う。
-mp,-mpio:並列化指示文(行)による並列化を指示
-Wl,-Xlocal,COMMON名:並列実行において指示したCOMMON変数をロー
カル変数として扱う。
-lscs_mp -lfastm:科学計算ライブラリのリンク
既に、全節で示してある通り、revpe_d.fが並列化の対象となっています。
これは筆者ウェブページで既に公開しているものとほぼ同じものです。既に、VPP
用に並列化が施されています。ベンチマークテストでは、SGI、COMPA
Q(旧DEC)とも、このソースコードにOpenMP用の並列化指示行を挿入してい
きました。
VPP(富士通のベクトル並列型スパコン)では、富士通による講習会、講
習会資料を元にほぼ自力でVPP用並列化コードを作成しました([参照1][参照2
])。一方、SX(NECのベクトル並列型スパコン)では、原研との共
同研究により並列化の支援を受け、最初はrevpe_d.fコードの一部のルーチン
を並列化してもらい、それを元にして、こちらで並列化を進めました(未完結、
[参照])。
今回は、先にも述べたようにベンチマークテストによって、SGI、COM
PAQ側にOpenMPによる並列化コードを作成するという形になりました(ベン
チマークの条件として、OpenMPによる並列化と、その実行テストを課した)。
従って、(3/3、1999段階)筆者はこれらOpenMPによって並列化された
コードについてはほとんど手を付けていません。OpenMPに対しての知識もVP
P、SXそれぞれ独自の並列化指示行と比べれば非常に貧弱です。これから筆
者もOpenMPによる並列化指示行を加えられたソースコード(revpe_d.f)を解
析しながら、勉強していくことになります(3/4、1999)。
(3/5、1999)、具体的なOpenMP化されたコードの部分を提示しなが
ら、説明していきたいと思います。OpenMP化されたコードはSGIによるもの
と、COMPAQ(旧DEC)によるものと2種類あるのですが、まず最初は、
当然すんなり動いたCOMPAQによるものから説明を行ないたいと思います。
SGIのコードは並列化以前に、Digital UNIX上のFORTRANコンパイラでは通
らない数値演算用のライブラリなどを使っていて、それらの問題に対処する必
要があるため後で詳しく話すことにします。
実際のOpenMPの並列化指示行によって並列化されたルーチンを示してみます。
以下は、サブルーチンDIAGON
(ここのものとはバージョンは若干異なります)のOpenMP部分とその周辺を抜
粋したものです。現在使っている注釈行は、"!$OMP"となっている(5/
1、2009)。
C ////////////////////////////
C // DIAGONALIZE AT K-POINT //
C ////////////////////////////
C VPP-PARALLEL START
C!XOCL PARALLEL REGION
!XOCL SPREAD NOBARRIER DO /IP
C$OMP PARALLEL SHARED(EKK,SSS,ZZ2,KZ1,KY1,KX1,UNIVOL,PAI4,NBMAT,
C$OMP& IBA2,IBA,NBASE,NBD2,NBD1,ZCHGO,ZPSCC,NLSPD,WD,WP,WS,ZVXC,
C$OMP& ZFM3,VZ,VY,VX,IGPO,IG3,IG2,IG1,GR,GZ,GY,GX)
C$OMP& PRIVATE(EPS,IOPT,KGB,KBAS,MM,I2,PPMT,II,L1,L2,L3,I1,LNUM,
C$OMP& CD,CP,CS,IIBA,IIKB,AKZ,AKY,AKX,IJG,PPM,EG,ZZZ,ZVN,ZAWORK,
C$OMP& ZWW,WWW,ZAAA,CWL,ICON)
C$OMP DO
DO 100 NNN=1,KNV3
C IWRT(NNN) =NNN
AKX = VX(NNN)
AKY = VY(NNN)
AKZ = VZ(NNN)
IIKB = IBA(NNN)
IIBA = IBA2(NNN)
これをみると、OpenMPによる指示行は、C$OMPで始まり、それがOpenMPによ
る指示行であるとコンパイラーが判定していることが推定されます。
C$OMP PARALLEL SHARED、C$OMP& PRIVATE(&記号は継続行を意味します)の
部分は、データ分割に関しての指示と思われます。
そして、これにはVPP用の並列化指示行も併記されているのですが、VP
Pの場合と同じく、D0 100のループ(バンド計算上でのk点に関してのループ
です)に並列化が施されています。そしてこれは、
231 CONTINUE
100 CONTINUE
C$OMP END DO
C$OMP END PARALLEL
!XOCL END SPREAD
C!XOCL END PARALLEL
RETURN
END
で閉じられています。
COMPAQ(旧DEC)マシンのソフトウェアに関してのマニュアルをお
持ちの場合、User Manual for DIGITAL UNIX Systemsの”DIGITAL Fortran 90”、
March 1998年版の6ー1、’Using Parallel Compiler Directives’を参照し
て下さい。
OpenMPでも、これまで扱ってきたVPPやSXでの並列化指示行形式と同じ
く、データに関しての分割と、手続きに関しての分割があるようです。この場
合の手続きの分割は既にあるVPP用の並列化指示と同じDOループに施され
ています。データの分割は、一見するとかなり面倒なことをやっているように
見えます。
ただ、VPPでもSXでも、そしてこのOpenMPでも全て指示行形式なので、
指示行を解釈しないマシン上では注釈行として解釈されるます。
個々の指示行の分析
(3/26、1999)OpenMPで使用している指示行の説明を行なってみよ
うと思います。
データ(配列など)分割部分
C$OMP PARALLEL SHARED(EKK,SSS,ZZ2,KZ1,KY1,KX1,UNIVOL,PAI4,NBMAT,
C$OMP& IBA2,IBA,NBASE,NBD2,NBD1,ZCHGO,ZPSCC,NLSPD,WD,WP,WS,ZVXC,
C$OMP& ZFM3,VZ,VY,VX,IGPO,IG3,IG2,IG1,GR,GZ,GY,GX)
C$OMP& PRIVATE(EPS,IOPT,KGB,KBAS,MM,I2,PPMT,II,L1,L2,L3,I1,LNUM,
C$OMP& CD,CP,CS,IIBA,IIKB,AKZ,AKY,AKX,IJG,PPM,EG,ZZZ,ZVN,ZAWORK,
C$OMP& ZWW,WWW,ZAAA,CWL,ICON)
手続き分割部分
C$OMP DO
C$OMP END DO
C$OMP END PARALLEL
OpenMP実行上の不具合修正(1/14、2000)
並列化している部分ではないですが、あるサブルーチンの局所配列で、それ
をメインルーチンに引き渡しておく必要があったのにそれを怠っていました。
この場合、次のイタレーションで、その配列の値は本当は(サブルーチン内だ
けの局所的なものなので)不定になっているはずなのですが、これまでの単一
のCPU動作では前のイタレーションの値は保持されていました(単なる偶然?)。
幸いこの局所配列の値そのものは保持されていても、されていなくても実害の
ないものだったのですが、OpenMPによる並列計算では、実行時におそらくこの
配列に絡む計算のところでエラーが生じ、実行が停止していました。
当該配列変数を、メインルーチンへ正しく引き渡せるように書き直すことで、
このエラーによる実行停止はなくなりました(1/14、2000)。
(1/17、2000)正しく計算されていることを確認。尚、このバグの
詳細は、最近やらかした計算上のバグ、失敗のレポート1/17、2000を参照。
↑上記と同じ過ちを再び犯す(4/27、2009)。
(文章移動)
(1/30、2009)今や、Core2duoやQuad core(Intel)など、1チップ
上に2ないし4個のCPUが載ったものが普通に存在し、Intel FORTRANコン
パイラも、普通に並列計算に対応している。隔世の感あり。
(4/27、2009)筆者によるプログラムコードのOpenMP化を本格的に
始めている(開始は、4/7頃より)。既に、FORCE, FORZFB, KBINT,
DIAGON, CHAVER, MSDについて、OpenMP化した。テスト計算段階で、速度は1
CPUの場合と比べて、8CPU並列実行で、およそ5.5倍の速度向上が実現
した。
(5/12、2009)データ分割に問題あり。
[先頭][総目次
][最初に戻る][VPP並列化][V
PP並列化2][SX4並列化][並列化情報]