Oakforest-PACSにおける · Oakforest-PACSにおける LAMMPS ReaxFFの高度化支援...
Transcript of Oakforest-PACSにおける · Oakforest-PACSにおける LAMMPS ReaxFFの高度化支援...
Oakforest-PACSにおけるLAMMPSReaxFFの高度化支援 高度情報科学技術研究機構(RIST)
井上 義昭青柳 哲雄
小林 寛(発表)2018年3月23日
内容 • 依頼内容と測定環境
• 性能評価– asis版の性能評価
– VtuneAmplifierの紹介
• 実行環境の見直し– メモリーモード
– 環境変数
• チューニング– チューニング箇所の確認
– 単体性能の向上
• まとめ 2
依頼内容と測定環境
3
依頼内容
• 高度化支援 依頼主は住友ベークライト株式会社殿• Oakleaf-FX、Oakbrigde-FX(FX-10)、およびOakforest-PACS(IntelXeonPhiKNL)を用いた全分子動力学シミュレーションを検討中
• 使用ソフトウェアはLAMMPS– AMBER系の古典力学(GAFF)と、反応力場(ReaxFF)を検討中。
• 計算の想定スケールは、23万粒子
• 今回は、Oakforest-PACSでのLAMMPSReaxFFを用いた計算の高度化支援(性能評価/高速化)を依頼。
4
測定環境
• システム:Oakforest-PACS(IntelXeonPhiKNL)• ソフトウエア:LAMMPS(version:11Aug17(stable))
– 分子動力学シミュレータ– 高並列性能– C++– オープンソース
• 力場:ReaxFFOMP版• 原子数:228,401(住友ベークライト殿提供)• 計算モデル:全原子• 並列化手法:ハイブリッド並列 (OpenMPxMPI)
– [node数]x64proc/nodex4thread/proc
• 実行ステップ数:0.25x1000ステップ 5
性能評価
6
性能評価~asis版の性能評価~
423
261181
131
217
144
112
102
650
411
299
2391.0
1.6
2.2
2.7
0.0
0.5
1.0
1.5
2.0
2.5
3.0
0
100
200
300
400
500
600
700
4 8 16 32
速度向上率
経過時間[s](MPItask)
ノード数
ノード数 vs経過時間[s](MPItask)
Other
Modify
Output
Comm
Neigh
Pair速度向上率
※プログラムが出力する標準出力データより 7
66 40 28 20
5839
30 25
58
3523
12
143
77
4326
19
14
13
12
124
69
39
24
10
12
17
24
9
7
11
10
23
24
25
25
657
421
311
248
0
100
200
300
400
500
600
700
4 8 16 32
rank
0の経過時間[s
]
ノード数
ノード数 vsrank0の経過時間[s](主要な処理にタイマーを挿入)
<OTHER>
<MOD_end.6>*other
<MOD_end.6>FRC_RecB
<MOD_end.6>comp_RDF.1+2
<MOD_pre.4>*other
<MOD_pre.4>FQR_CG.forwardCom
<MOD_pre.4>FQR_CG.reverseCom
<MOD_pre.4>FQR_CG.allreduce
<MOD_pre.4>FQR_CG.3+5+7+9
<MOD_pre.4>FQR_sparse_mat
<MOD_pre.4>FQR_pre_inmatv
<PAIR>*other
<PAIR>Tori_Ang
<PAIR>Val_Ang
<PAIR>BOOMP
<PAIR>Cmp_Tot
<PAIR>TvdWC_Ene
<PAIR>IForce_noQE.3
<PAIR>IForce_noQE.2
<PAIR>PRCO_wrxl
性能評価~asis版の性能評価~
8
modify
Pair
性能評価~VtuneAmplifierの紹介~
• インテルが提供するプロファイラ• CPU、GPU両方に対応。• スレッド並列/プロセス並列に対応。• ホットスポットやスケーラビリティ、キャッシュ利用等、チューニングの際に参考になる情報をGUI/テキストで確認可能。
9
性能評価~VtuneAmplifierの注意点1~
• X-windowではなくVNCを使う。– X-windowでは、プロファイリングデータのロードに時間がかかり、並列規模によっては、Vtuneを使うことが出来ない。
• オーバーヘッドに注意。• リソースの節約の観点より、タイムステップループのループ長を短めにしてプロファイリングデータを取得するのが良い。– マシンにかかる負荷も高いので、試す際は注意が必要。
• ファイナライズ処理に時間がかかる。– amplxe-clオプションの -finalization-mode=deferredあるいは-
no-auto-finalizeを使う。• -no-auto-finalizeの方がリソースの節約となる。ただし、-no-auto-
finalizeオプションを使用すると、標準出力データに「非推奨のため使用すべきではない」という内容のWarningが出力されるので注意。
• -finalization-mode=noneを使用するとジョブが終了しなかったので注意。10
性能評価~VtuneAmplifierの注意点2~
• 解析タイプ(collectオプション)はhрc-performanceがおすすめ– ホットスポットやメモリ情報等、解析に必要な全般的な情報を取得可能。– 多くのメモリを使うため、使用する際は注意が必要。
• -data-limit=<integer>でプロファイリングデータの上限値を変更可能(単位はMB、デフォルトは500)。0に設定すると、無制限にプロファイリングデータを取得する。
• すでに取得したい情報が決まっている場合は、それに沿った解析タイプ(hotspotsやmemory-access)を使ったほうが良い。
• Vtuneを使う時は、プリポストノードを使ったほうが良い。$ pjsub--interact-gxxx-Lrscgrp=prepost,node=1,elapse=6:00:00--X11$ moduleloadvtune$ amplxe-gui
• Vtuneで、全ノードまとめて結果を参照する方法は無い。– 全ノードまとめて結果を参照したい場合は、「TraceAnalyzer&Collector」あるいは簡易解析「ApplicationPeformanceSnapshot」を使う必要がある。• 出力内容が異なるため、VtuneAmplifierの代用にはならない事に注意。• 簡単な利用例については、付録参照
11
性能評価~VtuneAmplifierパフォーマンスの確認~
12
• 経過時間や、スレッド間のインバランス、キャッシュの情報等、解析に必要な様々な情報を参照可能。
• モジュール単位、プロセス単位等、指定して参照可能。
性能評価~VtuneAmplifierホットスポットの特定~
13
• 経過時間の情報を中心にホットスポットの特定が可能。• モジュール単位、プロセス単位等、指定して参照可能。
性能評価~VtuneAmplifierメモリの使用状況~
14
• メモリ/キャッシュの使用状況(ヒット率やミス率等)が確認可能。
• モジュール単位、プロセス単位等、指定して参照可能。
実行環境の見直し
15
実行環境の見直し
• メモリモード– asis版はFlatモードを使用。– 有効なメモリモード/設定について調査する。
• 環境変数– asis版は特別な環境変数は設定していない。– 東京大学情報基盤センターが公開している「Oakforest-PACSチューニングガイド」を元に、効果のある環境変数を設定する。
• 参考資料– Oakforest-PACSチューニングガイド
• https://www.cc.u-tokyo.ac.jp/system/ofp/tuning-guide-pub.pdf
– KNL実践(定期的に開催されている講習会の資料)• https://www.cc.u-tokyo.ac.jp/support/kosyu/94/20180214-1.pdf
16
実行環境の見直し~メモリモード~
• 以下のメモリモードを試し、asis版と比較– Flatモードで、MCDRAMを優先的にメモリとして使用する(numactl--preferred=1)
– MDCRAMをキャシュ的に利用する(Cacheモード)
17
実行環境の見直し~メモリモード~
18
131
65 65
102
84 81
239
153 1501.0
1.6 1.6
0.0
0.2
0.4
0.6
0.8
1.0
1.2
1.4
1.6
1.8
0
50
100
150
200
250
300
Flatモード (asis) Flatモード+preferred=1 Cacheモード
速度向上率
経過時間[s](MPItask)
メモリモード
メモリモード vs経過時間[s](MPItask)(32nodex64proc/nodex4thread/proc)
Other
Modify
Output
Comm
Neigh
Pair速度向上率
Cacheモード使用で、1.6倍高速化
実行環境の見直し~環境変数~
• 東京大学情報基盤センターが公開している「Oakforest-PACSチューニングガイド」を元に、効果のある環境変数を調査。以下の環境変数を設定することで、チューニング効果が見込めることが分かった。– exportKMP_AFFINITY=scatter
• スレッドをどの物理コアに割り当てるかの指定。
• scatterが設定されている場合、システム全体にわたってスレッドが均等に分配される様、物理コアに割り当てられる。
• Oakforest-PACSの場合、デフォルト値はcompact• scatterに変えた事による効果は非常に小さい(1%弱程度)
– exportI_MPI_PIN_PROCESSOR_EXCLUDE_LIST=0,1,68,69,136,137,204,205• OSジッタを避けるため、物理コア0はタイマ割り込みを受ける設定になっている。
• L2キャッシュを共有しているコア1の使用を避ける。• 各コアに割り当て可能な4つのハイパースレッディングコアの使用も避ける。
19
実行環境の見直し~環境変数~
20
131
65 64
102
81 75
239
150 1431.0
1.61.7
0.0
0.2
0.4
0.6
0.8
1.0
1.2
1.4
1.6
1.8
0
50
100
150
200
250
300
Flatモード (asis) Cacheモード Cacheモード+環境変数
速度向上率
経過時間[s](MPItask)
メモリモード+環境変数
メモリモード+環境変数 vs経過時間[s](MPItask)(32nodex64proc/nodex4thread/proc)
Other
Modify
Output
Comm
Neigh
Pair速度向上率
Cacheモード+環境変数の設定で、1.7倍高速化
実行環境の見直し~まとめ~
• 実行環境の見直しを行った。
• メモリモードをCacheモードに変更することで、32ノードasis版との比較で1.6倍の高速化。
• Cacheモード下で、有効な環境変数を設定することで、32ノードasis版との比較で1.7倍の高速化。
• 以下「実行環境の見直し」を行ったものをenv版とする。
21
チューニング
22
66 40 28 20
5839
30 25
58
3523
12
143
77
4326
19
14
13
12
124
69
39
24
10
12
17
24
9
7
11
10
23
24
25
25
657
421
311
248
0
100
200
300
400
500
600
700
4 8 16 32
rank
0の経過時間[s
]
ノード数
ノード数 vsrank0の経過時間[s](主要な処理にタイマーを挿入)
<OTHER>
<MOD_end.6>*other
<MOD_end.6>FRC_RecB
<MOD_end.6>comp_RDF.1+2
<MOD_pre.4>*other
<MOD_pre.4>FQR_CG.forwardCom
<MOD_pre.4>FQR_CG.reverseCom
<MOD_pre.4>FQR_CG.allreduce
<MOD_pre.4>FQR_CG.3+5+7+9
<MOD_pre.4>FQR_sparse_mat
<MOD_pre.4>FQR_pre_inmatv
<PAIR>*other
<PAIR>Tori_Ang
<PAIR>Val_Ang
<PAIR>BOOMP
<PAIR>Cmp_Tot
<PAIR>TvdWC_Ene
<PAIR>IForce_noQE.3
<PAIR>IForce_noQE.2
<PAIR>PRCO_wrxl
チューニング~チューニング箇所の確認~
23
Modify
Pair 1 2
3
• 今回は、現状のサイズ(23万粒子)が計算出来れば十分- 単体性能向上を中心にチューニング
• ホットスポットの内、高速化が望めそうな箇所(3箇所)をチューニング。
1. [Pair]PRCO_wrxl:SIMD化の促進2. [Pair]Iforce_noQE:クリティカルセクション除去3. [Modify]sparse_matvec:スレッド競合回避
チューニング~単体性能向上~
1. [Pair]PRCO_wrxl:SIMD化の促進write_reax_lists()最内ループ内にある小さな関数get_distance()やset_far_nbr()を手動でインライン展開し、SIMD化を促進する。
24
intPairReaxCOMP::write_reax_lists(){…for(itr_j=0;itr_j<numneigh[i];++itr_j){j=jlist[itr_j];j&=NEIGHMASK;get_distance(x[j],x[i],&d_sqr,&dvec);if(d_sqr<=cutoff_sqr){dist=sqrt(d_sqr);set_far_nbr(&far_list[num_nbrs_offset[i]+num_mynbrs],j,dist,dvec);++num_mynbrs;}}
asis/env版 pair_reaxc_omp.cpp
チューニング~単体性能向上~
1. [Pair]PRCO_wrxl:SIMD化の促進write_reax_lists()最内ループ内にある小さな関数get_distance()やset_far_nbr()を手動でインライン展開し、SIMD化を促進する。
25
ループの開始 pair_reaxc_omp.cpp(565,5)リマーク #15523:ループ はベクトル化されませんでした:ループ制御変数 itr_jは見つかりましたが、ループ を実行する前にループの反復数を計算できません。リマーク #25456:ループで置換された配列参照スカラーの数:1ループの終了
asis/env版 pair_reaxc_omp.optrpt
※コンパイルオプションに-qopt-report=5を追加してコンパイル mpiicpc-qopenmp…-qopt-report=5-cpair_reaxc_omp.cpp
最内ループはSIMD化(ベクトル化)されていない
チューニング~単体性能向上~
1. [Pair]PRCO_wrxl:SIMD化の促進write_reax_lists()最内ループ内にある小さな関数get_distance()やset_far_nbr()を手動でインライン展開し、SIMD化を促進する。
26
intPairReaxCOMP::write_reax_lists(){…for(itr_j=0;itr_j<numneigh[i];++itr_j){j=jlist[itr_j];j&=NEIGHMASK;doubletx=dvec[0]=x[j][0]-x[i][0];doublety=dvec[1]=x[j][1]-x[i][1];doubletz=dvec[2]=x[j][2]-x[i][2];d_sqr=tx*tx+ty*ty+tz*tz;if(d_sqr<=cutoff_sqr){far_neighbor_data*fdest=&far_list[num_nbrs_offset[i]+num_mynbrs];fdest->nbr=j;fdest->d=sqrt(d_sqr);fdest->dvec[0]=dvec[0];fdest->dvec[1]=dvec[1];fdest->dvec[2]=dvec[2];fdest->rel_box[0]=0;fdest->rel_box[1]=0;fdest->rel_box[2]=0;++num_mynbrs;}}
get_distance()をインライン展開
set_far_nbr()をインライン展開
tune版 pair_reaxc_omp.cpp
チューニング~単体性能向上~
1. [Pair]PRCO_wrxl:SIMD化の促進write_reax_lists()最内ループ内にある小さな関数get_distance()やset_far_nbr()を手動でインライン展開し、SIMD化を促進する。
27
ループの開始 pair_reaxc_omp.cpp(570,5)リマーク #15389:ベクトル化のサポート:参照 jlist[itr_j]にアラインされていないアクセスが含まれています。 [pair_reaxc_omp.cpp(571,11)]…リマーク #15300:ループがベクトル化されました。リマーク #15442:すべてのループは剰余ループとして実行されます。…リマーク #15475:---ベクトルのコストサマリー開始 ---リマーク #15476:スカラーのコスト:88リマーク #15477:ベクトルのコスト:56.060リマーク #15478:スピードアップの期待値:1.390リマーク #15488:---ベクトルのコストサマリー終了 ---リマーク #15498:ベクトル展開:1ループの終了
tune版 pair_reaxc_omp.optrpt ※コンパイルオプションに-qopt-report=5を追加してコンパイル mpiicpc-qopenmp…-qopt-report=5-cpair_reaxc_omp.cpp
最内ループがSIMD化(ベクトル化)されている
チューニング~単体性能向上~
1. [Pair]PRCO_wrxl:SIMD化の促進write_reax_lists()最内ループ内にある小さな関数get_distance()やset_far_nbr()を手動でインライン展開し、SIMD化を促進する。
28
4nodeenv
4nodetune
8nodeenv
8nodetune
16nodeenv
16nodetune
32nodeenv
32nodetune
PairReaxCOMP::write_reax_lists
40.4 17.5 26.7 11.2 19.9 8.3 14.9 6.2
PairReaxCOMP::write_reax_listsの経過時間[s] 2.3倍高速化
ノード数に依らず、約2.4倍高速化
2.4倍高速化 2.4倍高速化 2.4倍高速化
チューニング~単体性能向上~
2. [Pair]IForce_noQE:クリティカルセクション除去アトミック演算 (__sync_val_compare_and_swap)を用いることで、 クリティカルセクションを除去する。
29
voidInit_Forces_noQEq_OMP(…){…#ifdefined(_OPENMP)#pragmaompforschedule(dynamic,50)reduction(+:num_bonds)#endiffor(i=0;i<system->N;++i){…for(pj=start_i;pj<end_i;++pj){nbr_pj=&(far_nbrs->select.far_nbr_list[pj]);if(nbr_pj->d<=cutoff){j=nbr_pj->nbr;…//Updateindicesincriticalsection#ifdefined(_OPENMP)#pragmaompcritical#endif{btop_i=End_Index(i,bonds);btop_j=End_Index(j,bonds);Set_End_Index(j,btop_j+1,bonds);Set_End_Index(i,btop_i+1,bonds);}//ompcritical
asis/env版 reaxc_forces_omp.cpp
inlineintEnd_Index(inti,reax_list*l){returnl->end_index[i];}inlinevoidSet_End_Index(inti,intval,reax_list*l){l->end_index[i]=val;}
• jに関する更新は、スレッド競合が発生する可能性があるため、criticalセクションを使用している。
チューニング~単体性能向上~
2. [Pair]IForce_noQE:クリティカルセクション除去アトミック演算 (__sync_val_compare_and_swap)を用いることで、 クリティカルセクションを除去する。
30
voidInit_Forces_noQEq_OMP(…){…//Updateindicesincriticalsection{intoldval;oldval=End_Index(i,bonds);do{btop_i=oldval;oldval=__sync_val_compare_and_swap(&(bonds->end_index[i]),btop_i,btop_i+1);}while(oldval!=btop_i);oldval=End_Index(j,bonds);do{btop_j=oldval;oldval=__sync_val_compare_and_swap(&(bonds->end_index[j]),btop_j,btop_j+1);}while(oldval!=btop_j);}
tune版 reaxc_forces_omp.cpp
• type__sync_val_compare_and_swap(type*ptr,typeoldval,typenewval,…)
• アトミック(不可分)操作(操作中は他のスレッドによる影響を受けない)
• *ptrの値とoldvalの値が等しい場合は*ptrにnewvalを代入する。
• 戻り値は初期値の*ptrの値。• アトミック演算(__sync_val_compare_and_swap)を使って、排他的にbonds->end_index[]の値を更新。
• doループは、他のスレッドによって更新がなされていた場合の対応
チューニング~単体性能向上~
2. [Pair]IForce_noQE:クリティカルセクション除去アトミック演算 (__sync_val_compare_and_swap)を用いることで、 クリティカルセクションを除去する。
31
4nodeenv
4nodetune
8nodeenv
8nodetune
16nodeenv
16nodetune
32nodeenv
32nodetune
Init_Forces_noQEq_OMP
46.3 41.2 30.6 26.9 22.7 19.7 16.9 14.6
Init_Forces_noQEq_OMPの経過時間[s] 1.1倍高速化
ノード数に依らず、約1.2倍高速化。
1.1倍高速化 1.2倍高速化 1.2倍高速化
チューニング~単体性能向上~
3. [Modify]sparse_matvec:スレッド競合回避行列計算(疎行列とベクタの乗算)で、b_temp[tid][]を使った、スレッド競合回避のため処理が複雑。AjiをAijと同じ構造で(2重に)データを持たせることで、単純な計算方式 にでき、スレッド競合が回避可能.
32
voidFixQEqReaxOMP::sparse_matvec(sparse_matrix*A,double*x,double*b){…#pragmaompforschedule(dynamic,50)for(i=0;i<NN;++i)for(intt=0;t<nthreads;t++)b_temp[t][i]=0.0;//Waitforbaccumulatedandb_tempzeroed.#pragmaompbarrier#pragmaompforschedule(dynamic,50)for(ii=0;ii<nn;++ii){i=ilist[ii];if(atom->mask[i]&groupbit){for(itr_j=A->firstnbr[i];itr_j<A->firstnbr[i]+A->numnbrs[i];itr_j++){j=A->jlist[itr_j];b[i]+=A->val[itr_j]*x[j];b_temp[tid][j]+=A->val[itr_j]*x[i];}}}//Waittillb_tempaccumulated#pragmaompbarrier#pragmaompforschedule(dynamic,50)for(i=0;i<NN;++i)for(intt=0;t<nthreads;++t)b[i]+=b_temp[t][i];}//endompparallel
asis/env版 fix_qeq_reax_omp.cpp
• b_temp[tid][]を使った、スレッド競合回避のための処理が複雑。
• b_temp[tid][]でキャッシュミスが起こっている可能性が高い
チューニング~単体性能向上~
3. [Modify]sparse_matvec:スレッド競合回避行列計算(疎行列とベクタの乗算)で、b_temp[tid][]を使った、スレッド競合回避のため処理が複雑。AjiをAijと同じ構造で(2重に)データを持たせることで、単純な計算方式 にでき、スレッド競合が回避可能.
33
• CPUTimeがとても高い値を示している。• L1キャッシュミスが少し発生している様子。• L2HWプリフェッチの回数が非常に多い。
L2HWプリフェッチが多発しており、それがCPUTimeを高い値にしている。L2ヒット率が高いのは、プリフェッチの効果に依るものだと考えられる。
チューニング~単体性能向上~
3. [Modify]sparse_matvec:スレッド競合回避行列計算(疎行列とベクタの乗算)で、b_temp[tid][]を使った、スレッド競合回避のため処理が複雑。AjiをAijと同じ構造で(2重に)データを持たせることで、単純な計算方式 にでき、スレッド競合が回避可能.
34
voidFixQEqReaxOMP::sparse_matvec(sparse_matrix*A,double*x,double*b){…#pragmaompforschedule(dynamic,50)for(ii=0;ii<nn;++ii){i=ilist[ii];if(atom->mask[i]&groupbit){#pragmaivdepfor(itr_j=A->firstnbr[i];itr_j<A->firstnbr[i]+A->numnbrs[i];itr_j++){j=A->jlist[itr_j];b[i]+=A->val[itr_j]*x[j];//b_temp[tid][j]+=A->val[itr_j]*x[i];}}}#pragmaompbarrier#pragmaompforschedule(dynamic,50)for(j=0;j<A->znum;j++){#pragmaivdepfor(intjj=A->zfirstnbr[j];jj<A->zfirstnbr[j]+A->znumnbrs[j];jj++){i=A->zjlist[jj];b[j]+=A->zval[jj]*x[i];}}
tune版 fix_qeq_reax_omp.cpp
• b_temp[][]を経由せず、直接計算結果をb[]に代入。• ループに必要な各種変数(zxxx)は、構造体
sparse_matrixに用意し、FixQEqReax::allocate_matrix関数で領域確保、FixQEqReaxOMP::compute_H関数で値を設定する。• 詳細は付録参照
チューニング~単体性能向上~
3. [Modify]sparse_matvec:スレッド競合回避行列計算(疎行列とベクタの乗算)で、b_temp[tid][]を使った、スレッド競合回避のため処理が複雑。AjiをAijと同じ構造で(2重に)データを持たせることで、単純な計算方式 にでき、スレッド競合が回避可能.
35
4nodeenv
4nodetune
8nodeenv
8nodetune
16nodeenv
16nodetune
32nodeenv
32nodetune
FixQEqReax::allocate_matrix 0.003 0.006 0.001 0.003 0.0005 0.001 0.0001 0.0002 FixQEqReaxOMP::compute_H 18.3 28.3 9.4 14.4 5.2 7.7 2.7 3.9 FixQEqReaxOMP::sparse_matvec 40.3 29.0 25.4 16.4 17.4 9.6 13.2 6.6 Total 58.6 57.2 34.8 30.8 22.5 17.3 15.9 10.5
FixQEqReaxOMP::sparse_matvec他の経過時間[s]
32ノードで、約1.5倍高速化
1.02倍高速化 1.13倍高速化 1.30倍高速化 1.51倍高速化
チューニング結果
423
207 177261
128 109181
89 75131
64 53
217
127126
144
94 90
112
84 77
102
75 71
650
341309
411
226 203
299
177 156
239
143 128
0
100
200
300
400
500
600
700
asis env tune asis env tune asis env tune asis env tune
4node 8node 16node 32node
経過時間[s](MPItask)
ノード数
ノード数 vs経過時間[s](MPItask)
Other
Modify
Output
Comm
Neigh
Pair
2.1倍高速化
2.0倍高速化
1.9倍高速化 1.9倍高速化
ノード数に依らず、約2倍高速化
まとめ
37
まとめ
38
• 標準出力データとタイマーを使い、性能評価を行った。• 実行環境の見直しを行った。
– 32ノードasis版と比較して、1.7倍高速化
• 単体性能向上のためのチューニングを行った。– 「[Pair]PRCO_wrxl:SIMD化の促進」により、修正箇所がノード数に依らず、約2.4倍高速化。
– 「[Pair]IForce_noQE:クリティカルセクション除去」により、修正箇所がノード数に依らず、約1.2倍高速化。
– 「[Modify]sparse_matvec:スレッド競合回避」により、修正箇所が32ノードで、約1.5倍高速化。
• ノードに依らず、asis版と比較して、約2倍高速化。
付録
39
TraceAnalyzer&Collector利用例
40
• インタラクティブジョブで測定する方法1. インタラクティブジョブを実行する2. itacをモジュールロードし、MPI実行する
[username@c0001work]$moduleloaditac[username@c0001work]$mpiexec.hydra-trace-n"プロセス数"./a.out
3. 多数のa.out.stf*のファイルが実行ディレクトリに作成されている事を確認する。
• 結果のGUI出力方法(ログインノードで実行可能)
1. X11Forwardingを有効にするか、VNCを利用可能にする。2. Oakforest-PACSログインノードでGUI出力する。
[username@ofp01work]$moduleloaditac[username@ofp01work]$traceanalyzera.out.stf※ログインノードで実行可能だが、メモリ多く使うため、プリポストノードで実行することをお勧めします。
ApplicationPeformanceSnapshotの利用例
41
• インタラクティブジョブで測定する方法1. インタラクティブジョブを実行する2. vtuneをモジュールロードし、MPI実行する
[username@c0001work]$moduleloadvtune[username@c0001work]$mpiexec.hydra-n"プロセス数"aps./a.out
3. ディレクトリaps_result_YYYYMMDDが実行ディレクトリに作成されている事を確認する。
• 結果のGUI出力方法(ログインノードで実行可能)
1. Oakforest-PACSログインノードで以下のコマンドを実行する。[username@ofp01work]$moduleloadvtune[username@ofp01work]$aps--report=aps_result_YYYYMMDD
2. 結果が標準出力される。また、同様の情報が確認できるHTMLファイルが実行ディレクトリに出来ていることを確認する。
sparse_matvec:スレッド競合回避 詳細 3. [Modify]sparse_matvec:スレッド競合回避
行列計算(疎行列とベクタの乗算)で、b_temp[tid][]を使った、スレッド競合回避のため処理が複雑。AjiをAijと同じ構造で(2重に)データを持たせることで、単純な計算方式 にでき、スレッド競合が回避可能.
42
typedefstruct{intn,m;int*firstnbr;int*numnbrs;int*jlist;double*val;//2017-12-07RISTintz,znum;int*zfirstnbr;int*znumnbrs;int*zjlist;double*zval;//}sparse_matrix;
tune版 fix_qeq_reax.h
構造体 sparse_matrixに新しい変数(zxxx)を追加
sparse_matvec:スレッド競合回避 詳細 3. [Modify]sparse_matvec:スレッド競合回避
行列計算(疎行列とベクタの乗算)で、b_temp[tid][]を使った、スレッド競合回避のため処理が複雑。AjiをAijと同じ構造で(2重に)データを持たせることで、単純な計算方式 にでき、スレッド競合が回避可能.
43
FixQEqReax::FixQEqReax(LAMMPS*lmp,intnarg,char**arg){…H.zfirstnbr=NULL;H.znumnbrs=NULL;H.zjlist=NULL;H.zval=NULL;
voidFixQEqReax::allocate_matrix(){…intz=atom->nmax;intz_cap=MAX((int)(z*safezone),MIN_NBRS);H.z=z_cap;memory->create(H.zfirstnbr,z_cap,"qeq:H.zfirstnbr");memory->create(H.znumnbrs,z_cap,"qeq:H.znumnbrs");memory->create(H.zjlist,m_cap,"qeq:H.zjlist");memory->create(H.zval,m_cap,"qeq:H.zval");
voidFixQEqReax::deallocate_matrix(){…memory->destroy(H.zfirstnbr);memory->destroy(H.znumnbrs);memory->destroy(H.zjlist);memory->destroy(H.zval);
構造体 sparse_matrixの変数初期化
構造体 sparse_matrixの領域確保
構造体 sparse_matrixの領域解放
tune版 fix_qeq_reax.cpp
sparse_matvec:スレッド競合回避 詳細 3. [Modify]sparse_matvec:スレッド競合回避
行列計算(疎行列とベクタの乗算)で、b_temp[tid][]を使った、スレッド競合回避のため処理が複雑。AjiをAijと同じ構造で(2重に)データを持たせることで、単純な計算方式 にでき、スレッド競合が回避可能.
44
voidFixQEqReaxOMP::compute_H(){…memset(H.znumnbrs,0,H.z*sizeof(H.znumnbrs[0]));intznum=0;for(intii=0;ii<inum;ii++){inti=ilist[ii];if(mask[i]&groupbit){for(intjj=H.firstnbr[i];jj<H.firstnbr[i]+H.numnbrs[i];jj++){intj=H.jlist[jj];if(j>znum)znum=j;H.znumnbrs[j]++;}}}H.znum=znum+1;num_nbrs=0;for(intj=0;j<H.znum;j++){H.zfirstnbr[j]=num_nbrs;num_nbrs+=H.znumnbrs[j];}---(次ページへ続く)---
tune版 fix_qeq_reax_omp.cpp
• mask[i]を考慮に入れながら、H.jlist[j]の最大値をznumに設定する。
• H.znumnbrs[j]に値を仮設定する。• H.znumに znum+1を設定する。
• H.zfirstnbr[j]に値を設定する。
sparse_matvec:スレッド競合回避 詳細 3. [Modify]sparse_matvec:スレッド競合回避
行列計算(疎行列とベクタの乗算)で、b_temp[tid][]を使った、スレッド競合回避のため処理が複雑。AjiをAijと同じ構造で(2重に)データを持たせることで、単純な計算方式 にでき、スレッド競合が回避可能.
45
memset(H.znumnbrs,0,H.znum*sizeof(H.znumnbrs[0]));for(intii=0;ii<inum;ii++){inti=ilist[ii];if(mask[i]&groupbit){#pragmaivdepfor(intjj=H.firstnbr[i];jj<H.firstnbr[i]+H.numnbrs[i];jj++){intj=H.jlist[jj];H.zjlist[H.zfirstnbr[j]+H.znumnbrs[j]]=i;H.zval[H.zfirstnbr[j]+H.znumnbrs[j]]=H.val[jj];H.znumnbrs[j]++;}}}
tune版 fix_qeq_reax_omp.cpp
• mask[i]を考慮に入れながら、H.zjlist[]、H.zval[]、H.znumnbrs[]の値を設定する。
sparse_matvec:スレッド競合回避 詳細 3. [Modify]sparse_matvec:スレッド競合回避
行列計算(疎行列とベクタの乗算)で、b_temp[tid][]を使った、スレッド競合回避のため処理が複雑。AjiをAijと同じ構造で(2重に)データを持たせることで、単純な計算方式 にでき、スレッド競合が回避可能.
46
voidFixQEqReaxOMP::sparse_matvec(sparse_matrix*A,double*x,double*b){…#pragmaompforschedule(dynamic,50)for(ii=0;ii<nn;++ii){i=ilist[ii];if(atom->mask[i]&groupbit){#pragmaivdepfor(itr_j=A->firstnbr[i];itr_j<A->firstnbr[i]+A->numnbrs[i];itr_j++){j=A->jlist[itr_j];b[i]+=A->val[itr_j]*x[j];//b_temp[tid][j]+=A->val[itr_j]*x[i];}}}#pragmaompbarrier#pragmaompforschedule(dynamic,50)for(j=0;j<A->znum;j++){#pragmaivdepfor(intjj=A->zfirstnbr[j];jj<A->zfirstnbr[j]+A->znumnbrs[j];jj++){i=A->zjlist[jj];b[j]+=A->zval[jj]*x[i];}}
tune版 fix_qeq_reax_omp.cpp
• b_temp[][]を使って計算していた部分を、直接b[]に計算結果を代入する形に変更。