JAWS-UG HPC #2 LT 並列処理・MPIの第一歩
-
Upload
sei-ichi-tanabe-tanabu -
Category
Technology
-
view
961 -
download
2
Transcript of JAWS-UG HPC #2 LT 並列処理・MPIの第一歩
並列処理・ MPI の第一歩Introduction to
Message Passing Interface
23 October 2015 / 田名部 誠一 , Sei-Ichi Tanabe-Tanabu
※ 本資料内容および本自己紹介は所属組織の統一的見解ではなく、個人的見解によるものです。
@n_scattering .
seiichi.tanabetanabu .
JAWS-UG HPC 専門支部 #2 LT
2
自己紹介
田名部 誠一 ( たなべ / たなぶ せいいち )• 所属 :– ビジュアルテクノロジー株式会社
HPC 事業本部 テクニカル & サポート部• 役割 :– HPC に有用な (?) 技術の調査、プログラムの開発
社内情報システム管理、極端に広く浅く• 好きな AWS サービス :– Amazon EC2 ( というか、それしか使ったことがない )
• 参加 JAWS-UG:– 初心者 ・中央線 に、 JAWS Days 2015 以降
参加2015/10/23 /30
AWS Summit Tokyo 2015After party - JAWS DAYS にて
JAWS-UG HPC 専門支部 #2 LT
3
趣味 (?) にしていること
頻度が高めな順に
• Ingress (#0 の自己紹介参照 )–運動療法として始めたが、歩き過ぎに注意
• 各種 IT 勉強会 (JAWS-UG なども含む )• 発達障害 ( 自閉症スペクトラム ) ・双極性障害の
当事者会への参加• 乗り鉄 ( なかなかできない )• 研究所・研究施設等の一般公開の見学
2015/10/23 /30JAWS-UG HPC 専門支部 #2 LT
4
• 学部・大学院での研究 : – 理論系 物理学 ( 原子衝突 ) ・化学 ( 分子ダイナミクス )
→ 大規模計算…じゃなかった。
– Pentium !!!, Pentium4 計算機 1 台でできる小規模な計算
– 一応プログラム ( 主に Fortran, C など ) やシェルスクリプト (# シェル芸 , CLI) は理解できる
• 最初の職場、前職など :– 全くもって HPC とは無縁な職場だった (Ex. 回路設計、 PG)
• 研究室と師匠との縁で、今の職場に :– http://v-t.jp/jp/profile/shain-ta.php ( 行儀の良い社員紹介 )
2015/10/23 /30JAWS-UG HPC 専門支部 #2 LT
私と High-Performance Computing (HPC) との関わり
5
なぜ HPC か、並列処理か?
• 並列計算の経験がない!これはまずい!• 計算機周辺の性能の向上
• CPU 、メモリ、ストレージ、ネットワーク…
• だけど、ユーザーの要求も高い!• そこで、並列計算! ( 計算機の共同作業! )–計算時間の短縮• N並列ならば、 1/Nの計算時間になるのが理想
だが、そうはいかないのが実情… (チューニングなどの工夫 )
–大容量のメモリを必要とする計算も可能• 1 台でできないけど、クラスタにすればできる
2015/10/23 /30JAWS-UG HPC 専門支部 #2 LT
6
並列計算機について
• 並列ではない計算機 (昔の PC)• 共有メモリ型並列計算機 ( 最近の PC も )
• 1筐体にプロセッサ■ (コア ) が複数• 全プロセッサが 1つのメモリ■を共有• 並列化の手段 : MPI 、 OpenMP
• 分散メモリ型並列計算機 ( クラスタ構成 )• 筐体 ( ノード ) が複数。ネットワーク接続• 各筐体が独自にメモリ■を所有• 並列化の手段 : MPI• →ノード間で通信をすることで、
全ノードのメモリが使えるようになる
2015/10/23 /30JAWS-UG HPC 専門支部 #2 LT
メモリー
7
MPI とは?
• Message Passing Interface分散メモリ間のメッセージ通信の規格
• 実装としては MPICH 、 OpenMPI が有名https://www.mpich.org/http://www.open-mpi.org/
• プログラマが細かなチューニングを行える• 明示的に手続きを記述する必要がある
2015/10/23 /30JAWS-UG HPC 専門支部 #2 LT
8
MPI 関数の紹介
• MPI 関数は数百種類。必要最低限の関数• 1. システム関数– MPI_Init; MPI_Comm_rank; MPI_Comm_size;
MPI_Finalize;• 2. 1対 1通信関数– MPI_Send; MPI_Recv;
• 3-1. 通信の同期– MPI_Barrier
• 3-2. 時間計測関数– MPI_Wtime
2015/10/23 /30JAWS-UG HPC 専門支部 #2 LT
9
A. MPI_INIT
2015/10/23 /32JAWS-UG HPC 専門支部 #2 LT
• MPI環境の初期化。• すべての MPI ルーチンの最初に 1 回だけ必ずコールする必要がある。
• CALL MPI_INIT(ierr)– ierr: 完了コードが戻る
10
B. MPI_FINALIZE
2015/10/23 /32JAWS-UG HPC 専門支部 #2 LT
• MPI環境の終了処理。• すべての MPI ルーチンの最後に 1 回だけ必ずコールする必要がある。
• CALL MPI_FINALIZE(ierr)– ierr: 完了コードが戻る
11
C. MPI_COMM_RANK
2015/10/23 /32JAWS-UG HPC 専門支部 #2 LT
• コミュニケーター comm で指定したグループ ( 職場 ) 内での自分 (=コールしたプロセス ) のランク (「名前・社員番号」 )を取得する。
• CALL MPI_COMM_RANK(comm,rank,ierr)– comm: コミュニケーター ( 職場 )を指定( ここでは MPI_COMM_WORLD 、全体を指定します )
– rank: comm で指定したグループ内での自分 (=コールしたプロセス ) のランク ( 名前・社員番号 )
– ierr: 完了コードが戻る
12
D. MPI_COMM_SIZE
2015/10/23 /32JAWS-UG HPC 専門支部 #2 LT
• コミュニケーター comm で指定したグループ ( 職場 ) に含まれるプロセスの数を得る。
( プロセッサ数、並列数、「従業員数」 )• CALL MPI_COMM_SIZE(comm,procs,ierr)– comm: コミュニケーター ( 職場 )を指定( ここでは MPI_COMM_WORLD 、全体を指定します )
– procs: comm で指定したグループ内に含まれるプロセスの数 (「従業員数」 )
– ierr: 完了コードが戻る
13
並列版 Hello プログラムの説明 (1)( プログラム 1, Fortran)
program main include "mpif.h" common /mpienv/myid,numprocs
integer myid, numprocs integer ierr
call MPI_INIT(ierr) call MPI_COMM_RANK(MPI_COMM_WORLD, myid, ierr) call MPI_COMM_SIZE(MPI_COMM_WORLD, numprocs, ierr)
print *, "Hello parallel world! Myid:", myid
call MPI_FINALIZE(ierr)
stop end
2015/10/23 /32JAWS-UG HPC 専門支部 #2 LT
14
並列版 Hello プログラムの説明 (2) ( プログラム 1, Fortran)
program main include "mpif.h" common /mpienv/myid,numprocs
integer myid, numprocs integer ierr
call MPI_INIT(ierr) call MPI_COMM_RANK(MPI_COMM_WORLD, myid, ierr) call MPI_COMM_SIZE(MPI_COMM_WORLD, numprocs, ierr)
print *, "Hello parallel world! Myid:", myid
call MPI_FINALIZE(ierr)
stop end
2015/10/23 /32JAWS-UG HPC 専門支部 #2 LT
このプログラムは、全プロセス( 全従業員 ) で起動される
A. MPI の初期化
C. 自プロセスの ID番号「社員番号」(myid)を取得します。
( 各プロセス・従業員で番号が異なります。 )
D. 全体のプロセッサ台数「従業員数」(numprocs)を取得します。
( 各プロセス・従業員で値は同じ )B. MPI の終了
15
並列版 Hello プログラムの説明(C言語、参考 )
#include <stdio.h>#include "mpi.h"
int main(int argc, char* argv[]) {
int myid, numprocs; int ierr, rc;
ierr = MPI_Init(&argc, &argv); ierr = MPI_Comm_rank(MPI_COMM_WORLD, &myid); ierr = MPI_Comm_size(MPI_COMM_WORLD, &numprocs);
printf("Hello parallel world! Myid:%d \n", myid);
rc = MPI_Finalize();
}
2015/10/23 /32JAWS-UG HPC 専門支部 #2 LT
C言語では、関数名 (MPI_Init など ) の大文字・小文字の使い方が異なります
C言語では、完了コード (ierr)を得る方法が異なります
16
並列版 Hello 実行結果
2015/10/23 /32JAWS-UG HPC 専門支部 #2 LT
[tanabe@tanabe sample]$ mpif90 sample1.f90 -o sample1(コンパイル )
[tanabe@tanabe sample]$ mpirun -n 2 sample1(2 並列「従業員数 2 名」で実行 )
Hello parallel world! Myid: 0 Hello parallel world! Myid: 1[tanabe@tanabe sample]$
( 全プロセス「従業員」に対して Hello parallel world!と、ランク「名前・社員番号」を表示する。同じ処理を実行しているが、 Myid の値で結果が変わる。 )
17
E. MPI_SEND
2015/10/23 /32JAWS-UG HPC 専門支部 #2 LT
• 1対 1ブロッキング通信サブルーチン (送信 )
• 送信メッセージを宛先プロセスに送信。–特定の従業員に「仕事を指示する」作業
• ただし、その人が聞いているとは限らない。→指示した従業員に案件番号を指定し指示を聞いてもらう作業が必要
• 送信したメッセージは MPI_RECV で受信する。
Myid=0
Myid=1
Myid=2
MPI_SEND!!
MPI_RECVで受信 !!
メッセージ
18
E. MPI_SEND
2015/10/23 /32JAWS-UG HPC 専門支部 #2 LT
• CALL MPI_SEND(buf,count,datatype, dest,tag,comm,ierr)– buf: 送信バッファーの先頭アドレス (変数 )– count: 送信メッセージの要素数 (※バイト数ではない )
– datatype: 送信メッセージのデータ型– dest: 宛先プロセスの comm内のランク ( 名前・社員番号 )
– tag: 送信メッセージの種類を区別するタグメッセージの「案件番号」
– comm: コミュニケーター「職場」を指定(ここでは MPI_COMM_WORLD 、全体を指定します )
– ierr: 完了コードが戻る
19
F. MPI_RECV
2015/10/23 /32JAWS-UG HPC 専門支部 #2 LT
• 1対 1ブロッキング通信サブルーチン (受信 )
• 送信元プロセスから送信されたメッセージを受信する。–特定の誰かから「仕事の依頼を受ける」作業
• ただし、その人への指示、受けるべき依頼とは限らない。→受けるべき特定の誰かからの指示、案件内容が必要
• MPI_SEND で送信したメッセージを受信する。
Myid=0
Myid=1
Myid=2
MPI_SENDで送信した !!MPI_RECVで受信 !!
メッセージ
20
F. MPI_RECV
2015/10/23 /32JAWS-UG HPC 専門支部 #2 LT
• CALL MPI_RECV(buf,count,datatype, source,tag,comm,status,ierr)– buf: 受信バッファーの先頭アドレス (変数 )– count: 受信バッファーの要素数 (※バイト数ではない )
– datatype: 受信メッセージのデータ型– source: 送信するプロセスの comm 内のランク (名前・社員番
号 )
– tag: 送信メッセージの種類を区別するタグ「案件番号」
– comm: コミュニケーター「職場」を指定( ここでは MPI_COMM_WORLD 、全体を指定します )
– status: 受信状況に関する情報 (整数配列 )– ierr: 完了コードが戻る
21
並列版送受信プログラムの説明 (1)( プログラム 2, Fortran)
program main include “mpif.h” common /mpienv/myid,numprocs
integer myid, numprocs integer isbuf, irbuf, ierr integer istatus(MPI_STATUS_SIZE)
call MPI_INIT(ierr) call MPI_COMM_RANK(MPI_COMM_WORLD, myid, ierr) call MPI_COMM_SIZE(MPI_COMM_WORLD, numprocs, ierr)
if (myid.eq.0) then isbuf = 19750617 endif
(続く )
2015/10/23 /32JAWS-UG HPC 専門支部 #2 LT
myid( ランク・社員番号 ) が 0 のプロセスの変数 isbuf の変数を代入
MPI_RECV の処理で必要な変数受信状況に関する情報 ( 整数配列 )
準
備
22
並列版送受信プログラムの説明 (2)( プログラム 2, Fortran)
(続く ) if (myid.eq.0) then call MPI_SEND (isbuf,1,MPI_INTEGER,1,1,MPI_COMM_WORLD,ierr)
elseif (myid.eq.1) then call MPI_RECV (irbuf,1,MPI_INTEGER,0,1,MPI_COMM_WORLD, istatus, ierr)
endif
if (myid.eq.1) then write(*,*) "IRBUF =",irbuf endif
call MPI_FINALIZE(ierr)
stop end2015/10/23 /32JAWS-UG HPC 専門支部 #2 LT
Myid( ランク・社員番号 ) が 1 のプロセスの変数 irbuf の内容を確認する。Myid=0 のプロセス ( 従業員 ) から、Myid=1 のプロセス ( 従業員 ) にデータが送信されている!
0 から1に送信 !!
0 から来たメッセージを1が受信 !!
処理の決定「案件番号」は 1
23
並列版送受信実行結果
2015/10/23 /32JAWS-UG HPC 専門支部 #2 LT
[tanabe@tanabe sample]$ mpif90 sample2.f90 -o sample2(コンパイル )[tanabe@tanabe sample]$ mpirun -n 2 sample2(2 並列、従業員数 2 名で実行 )IRBUF = 19750617(従業員 Myid=1 に対して、従業員 Myid=0 から送信された整数値を受信できたことを確認する。 )
Myid=0
Myid=1
MPI_SENDで送信した !!
MPI_RECVで受信 !!
19750617 確認
24
G. MPI_BARRIER
2015/10/23 /32JAWS-UG HPC 専門支部 #2 LT
• コミュニケーター comm「職場」内の全プロセス「全従業員」間で同期をとる関数–ある職場の共同作業で、全部の結果が揃わな
いと次の作業ができない場合に、最後まで待つ
• CALL MPI_BARRIER(comm, ierr)– comm:コミュニケーター「職場」を指定( ここでは MPI_COMM_WORLD 、全体を指定します )
– ierr: 完了コードが戻る
25
H. MPI_WTIME
2015/10/23 /32JAWS-UG HPC 専門支部 #2 LT
• 時刻を得る関数。 (※ たぶん Unix 時間 )
• 経過時間の測定をしたい部分の前後で実行し、得られた値 elp の差を取ると、その部分の実行時間が得られる。
• elp = MPI_WTIME ()– elp: ある過去の時点からの経過時間 (秒 )
26
時刻同期プログラムの説明 (1)( プログラム 3, Fortran)
program main implicit none include "mpif.h" common /mpienv/myid,numprocs
integer myid, numprocs integer ierr integer*8 i, j, iinput, ioutput real*8 elp1, elp2
call MPI_INIT(ierr) call MPI_COMM_RANK(MPI_COMM_WORLD, myid, ierr) call MPI_COMM_SIZE(MPI_COMM_WORLD, numprocs, ierr)(続く )
2015/10/23 /32JAWS-UG HPC 専門支部 #2 LT
計算で必要な変数時間計測で必要な変数
心
の
準
備
27
時刻同期プログラムの説明 (2)( プログラム 3, Fortran)
(承前 )! preparation elp1 = MPI_WTIME() iinput=0 do i=1, 50000*(myid+1) do j=1, 50000 iinput = iinput + 1 enddo enddo
! mpi_barrier call MPI_BARRIER(MPI_COMM_WORLD, ierr)
! summation ioutput=0 do i=1, 50000 do j=1, 50000 ioutput = ioutput + 1 enddo enddo write(*,*) iinput, ioutput, 'myid=' , myid (続く )
2015/10/23 /32JAWS-UG HPC 専門支部 #2 LT
( 作業 1) Myid( ランク ) の値に応じた回数だけ足し算を行う。( 従業員により、かかる時間が異なる )
( 作業 2) 決まった回数だけ足し算を行う。( 従業員間でかかる時間はあまり変わらない )
結果の確認
全プロセスの同期を取る( 全従業員の作業が終わるまで待つ )
時間の測定 ( 計算前 )
作業1
作業2
28
時刻同期プログラムの説明 (3)( プログラム 3, Fortran)
2015/10/23 /32JAWS-UG HPC 専門支部 #2 LT
• MPI_BARRIER で同期
• 同期しない場合
Myid=0
Myid=1
Myid=2
MPI_BARRIER で全プロセスの同期を取る( 全従業員の作業が終わるまで待つ )
作業 1
作業 2経過時間
Myid=0
Myid=1
Myid=2
作業 2 を行うためには、作業 1 を終わらせなくてはいけない!そのために、同期が必要なはず。意図した動作が行われない!!
29
(承前 )
elp2 = MPI_WTIME()
write(*,*) 'ELAPSE=', elp2-elp1, 'myid=',myid call MPI_FINALIZE(ierr)
stop end
時間の測定 ( 計算後 )
時刻同期プログラムの説明 (4)( プログラム 3, Fortran)
2015/10/23 /32JAWS-UG HPC 専門支部 #2 LT
計算前後時間の差を取る ( 経過時間 )
30
並列版時刻同期実行結果
2015/10/23 /32JAWS-UG HPC 専門支部 #2 LT
[tanabe@tanabe sample]$ mpif90 sample3.f90 –o sample3(コンパイル )
[tanabe@tanabe sample]$ mpirun –n 2 sample3(2 並列、「従業員数 2 名」で実行 ) 5000000000 2500000000 myid= 1 ELAPSE= 31.489058017730713 myid= 1 2500000000 2500000000 myid= 0 ELAPSE= 33.371865987777710 myid= 0
MPI_BARRIERをしなかった場合 2500000000 2500000000 myid= 0 ELAPSE= 19.314102172851563 myid= 0 5000000000 2500000000 myid= 1 ELAPSE= 28.772753953933716 myid= 1
同期がとれていて、プロセス間で経過時間の違いは ( そんなに ) ない。
同期がとれていないので、プロセスごとに経過時間がバラバラ。
31
最後に
2015/10/23 /32JAWS-UG HPC 専門支部 #2 LT
• HPC 、大規模計算のためには並列化、特にメモリ分散型計算機 ( クラスター )を使います。
• メモリ分散型計算機で並列計算を行うためには MPI による実装が ( 今のところ )必須です。
• MPI のサブルーチンの数は多いが、少数の基礎的なもので入門可能です。
• この業界にいながら、職種の関係でクラスター構築の経験がほぼないのが悩み。
32
参考となりそうな文献など
2015/10/23 /32JAWS-UG HPC 専門支部 #2 LT
• スパコンプログラミング入門 : 並列処理と MPI の学習 (片桐 孝洋 著、東京大学出版会 )※他にも、 OpenMP などに着目した著書などもあり
• 並列プログラミング虎の巻MPI版(青山 幸也 著、高度情報科学技術研究機構 )※OpenMP 、チューニングのテキストもありhttp://www.hpci-office.jp/pages/seminar_text
• MPICH サイトhttps://www.mpich.org/
• OpenMPI サイトhttp://www.open-mpi.org/ などなど
• サンプルプログラムは、 Github にありますhttps://github.com/sittncs/hpcstudy/