• 検索結果がありません。

MPI 集団通信に関するプログラムの実行

ドキュメント内 Reedbush-Uアカウントの発行 (ページ 34-64)

UNIX コマンド備忘録( 1/3 )

emacs

エディタの起動:

emacs

編集ファイル名

• ^x ^s

^

は「

control

を押しながら」) :テキストの保存

• ^x ^c

:終了

^z

で終了すると、スパコンの負荷が上がる。絶対にしないこと)

• ^g

:訳がわからなくなったとき

• ^k

:カーソルより行末まで消す。

消した行は一時的に記憶される。

• ^y

^k

で消した行を、現在のカーソルの場所にコピー

• ^s

文字列 :文字列の箇所まで移動(検索)

• ^M x goto-line

:指定した行まで移動

^M

ESC

キーを押して離す)

UNIX コマンド備忘録( 2/3 )

• rm

ファイル名 :ファイルを消す

• ls

:現在いるフォルダの中身を見る

• cd

ディレクトリ名 :ディレクトリに移動する

• cd ..

:一つ上のディレクトリへ移動する

• cd

:ホームディレクトリへ行く

• cat

ファイル名 :ファイルの中身を見る

• make

Makefile

がある場合、実行ファイルを作る

• make clean

:実行ファイルを消す

clean

Makefile

内で定義されていないと実行できない。)

UNIX コマンド備忘録( 3/3 )

• less

ファイル名 :ファイルの中身を見る

cat

では画面がいっぱいになってしますとき)

スペースキー :

1

画面スクロール

• /

文字列 :文字列の箇所まで移動

• q

:終了(訳がわからなくなったとき)

サンプルプログラム名

• C

言語版・

Fortran

版共通ファイル:

Samples.tar

• tar

で展開後、

C

言語と

Fortran

のディレクトリが作られる。

C/

C

言語用

F/

Fortran

上記ファイルが置いてある場所

/lustre/gt03/t03000

Samples.tar の中身

• Hello/

並列版

Hello

プログラム

• Mat-vec/

行列・ベクトル積の計算プログラム

• MPI/

• MPI

集団通信のサンプルプログラム

• Wa1/

逐次転送方法による総和演算プログラム

• Wa2/

二分木通信方式による総和演算プログラム

並列版 Hello プログラムをコンパイル( 1/2 )

1. cdw

コマンドを実行して

lustre

ファイルシステムへ移動

$ cdw

2.

サンプルプログラムの場所

/lustre/gt03/t03000

にある

Samples.tar

を自分のディレクトリにコピーする

$ cp /lustre/gt03/t03000/Samples.tar ./

3. Samples.tar

を展開する

$ tar xvf Samples.tar 4. Samples

ディレクトリへ移動

$ cd Samples

C

言語

$ cd C Fortran

$ cd F 5. Hello

ディレクトリへ移動

$ cd Hello

並列版 Hello プログラムをコンパイル( 2/2 )

6.

ソースファイルをコンパイルする。すでに

compile

ファイルとい う実行ファイルが用意されているので、それを実行する。

$ ./compile

(以下のコマンドでもコンパイル可)

C

言語

mpiicc hello.c –o hello Fortran

mpiifort hello.f –o hello 7.

実行ファイル(

hello

)ができていることを確認する

$ ls

並列版 Hello プログラムの実行(ピュア MPI )

このサンプルの

Job

スクリプトは

hello.bash

です。

サンプルでは、キュー名が

“u-lecture”

,グループ名が

“ gt00 ”

になっています。

• $ emacs hello.bash

で、キュー名とグループ名をそれぞれ書き換えてください。

u-lecture3

gt03

並列版 Hello プログラムの実行(ピュア MPI )

1. Hello

ディレクトリの中で以下を実行

$ qsub hello.bash

2.

自分の導入されたジョブを確認

$ rbstat

3.

実行が終了すると、以下のファイルが生成される

hello.bash.exxxxxx

hello.bash.oxxxxxx

xxxxxx

JobID

4.

上記の標準出力ファイルを見てみる

cat hello.bash.oxxxxxx

5. “ Hello parallel world! ”

36

プロセス×

8

ノード

=288

表示されていたら実行成功。

バッチジョブ実行時の標準出力と標準エラー出力

バッチジョブの実行が終了すると、標準出力ファイルと標準エ ラー出力ファイルがジョブ投入時のディレクトリに作成される。

標準出力ファイルにはジョブ実行中の標準出力、標準エラー出 力ファイルにはジョブ実行中のエラーメッセージが出力される。

ジョブ名

.oXXXXX ---

標準出力ファイル

ジョブ名

.eXXXXX ---

標準エラー出力ファイル

XXXXX

はジョブ投入時に表示されるジョブの

JobID

並列版 Hello プログラム( C 言語)

#include <stdio.h>

#include <mpi.h>

int main(int argc, char *argv[]){

int myid,nprc,ierr;

ierr=MPI_Init(&argc,&argv);

ierr=MPI_Comm_rank(MPI_COMM_WORLD,&myid);

ierr=MPI_Comm_size(MPI_COMM_WORLD,&nprc);

printf("Hello parallel world! MyID: %d %d¥n",myid, nprc);

ierr=MPI_Finalize();

return 0;

}

MPI

の初期化

自分の

rank ID

を取得

:各プロセスで値は異なる

全体のプロセッサ台数 を取得

:各プロセスで値は同じ

(演習環境では 最大

288

MPI

の終了

このプログラムは、全PEで起動される

program main implicit none include "mpif.h"

integer::myid,nprc,ierr call mpi_init(ierr)

call mpi_comm_rank(mpi_comm_world,myid,ierr) call mpi_comm_size(mpi_comm_world,nprc,ierr)

print *, "Hello parallel world! MyID:", myid, nprc call mpi_finalize(ierr)

stop

end program main

並列版 Hello プログラム( Fortran )

MPI

の初期化

自分の

rank ID

を取得

:各プロセスで値は異なる

全体のプロセッサ台数 を取得

:各プロセスで値は同じ

(演習環境では 最大

288

MPI

の終了

このプログラムは、全PEで起動される

MPI の集団通信プログラム

前回の資料(計算科学概論 0409.pdf )の 85 ページ からを参照

プログラムをよく読んで、コンパイル・実行し、結果

を確認してください。

サンプルプログラムの起動

3.行列・ベクトル積プログラムの実行

Samples.tar の中身

• Hello/

並列版

Hello

プログラム

• Mat-vec/

行列・ベクトル積の計算プログラム

• MPI/

• MPI

集団通信のサンプルプログラム

• Wa1/

逐次転送方法による総和演算プログラム

• Wa2/

二分木通信方式による総和演算プログラム

行列・ベクトル積の計算プログラム( Mat-vec )

実行結果が、

N = 10000

Elapsed time = 0.286047 [sec.]

699.185843 [MFLOPS]

OK!

N = 10000

Elapsed time[sec.] = 1.46469116210938 MFLOPS = 136.547557037191

OK!

(C言語)

Fortran

のような結果が出たらOK

サンプルプログラムの説明

本プログラムでは、全プロセスが行列

A

とベクトルxのデータ を持ち、

y=Ax

の計算をしている。

C

言語)

#define N 10000

Fortran

integer,parameter::N=10000 N

を変更すると、行列サイズを変更できます。

C

言語)

#define debug 1

Fortran

integer,parameter::debug=1

「1」としてコンパイルすると、演算結果が正しいことがチェッ クできます。

レポート課題( I )

下記について、実験環境(

8

ノード、

288

コア)を駆使して、問題サイズ や並列数を変化させるなどにより性能を評価し、レポートにまとめよ。

1.

サンプルプログラムを並列化せよ。このとき、行列

A

およびベクト ルx、yのデータは、全

PE

N

×

N

のサイズを確保してよい。

2.

サンプルプログラムを並列化せよ。このとき、行列

A

は、初期状態 では、各

PE

に割り当てられた分の領域しか確保してはいけない。

レポート課題( I )の注意

本課題では、

MPI

通信関数は不要です。

このサンプルプログラムでは、演算結果検証部分

debug=1

にした場合に実行される部分)が並列化され ていないため、

MatVec

関数のみを並列化しても、検証 部でエラーとなります。

検証部分も、計算されたデータに各PEで対応するよう に、並列化してください。検証部分においても、行列

-

ベ クトル積と同様のループとなります。

本実習プログラムの TIPS

• myid, nprc

は大域変数です

myid (=

自分の

ID)

、および、

nprc(=

全プロセス数

)

の変数 は大域変数です。

MyMatVec

関数内で、引数設定や宣 言なしに、参照できます。

• myid, nprc

の変数を使う必要があります

MyMatVec

関数を並列化するには、

myid

および、

nprc

変 数を利用しないと、並列化ができません。

並列化の考え方(C言語)

for ( j=0; j<N; j++) { 内積( j, i ) }

PE0

for ( j=0; j<N/4; j++) { 内積( j, i ) }

PE1

for ( j=N/4; j<(N/4)*2; j++) { 内積( j, i ) }

PE2

for ( j=(N/4)*2; j<(N/4)*3; j++) { 内積( j, i ) }

PE3

for ( j=(N/4)*3; j<N; j++) { 内積( j, i ) }

各PEで 重複して 所有する

行列A

ベクトルx

n

n

SIMD

アルゴリズムの考え方(4PEの場合)

並列化の考え方( Fortran 言語)

do j=1, N 内積( j, i ) enddo

PE0

do j=1, N/4 内積( j, i ) enddo

PE1

do j=N/4+1, (N/4)*2 内積( j, i )

enddo

PE2

do j=(N/4)*2+1, (N/4)*3 内積( j, i )

enddo

PE3

do j=(N/4)*3+1, N 内積( j, i )

enddo

各PEで 重複して

行列A 所有する

ベクトルx

n

n

SIMD

アルゴリズムの考え方(4PEの場合)

PE0 PE1 PE2 PE3

初心者が注意すること

A[N][N] A[N][N] A[N][N] A[N][N]

PE0 PE1 PE2 PE3

myid = 0 myid = 1 myid = 2 myid = 3

各PEでは、独立した配列が個別に確保されます。

myid

変数は、

MPI_Comm_rank()

関数が呼ばれた段階で、各PE

固有の値になっています。

1.

PE

で行列

A

N

×

N

の大きさ、ベクトルx、yを

N

の大きさ、確保してよいと する。

2.

PE

は、担当の範囲のみ計算するように、ループの開始値と終了値を変 更する。ブロック分散方式では、以下になる。

N

nprc

で割り切れる場合)

ib = N / nprc;

for ( nj=myid*ib; nj<(myid+ 1 )*ib; nj++) { … }

3.

(2の並列化が完全に終了したら)各

PE

で担当のデータ部分しか行列を確 保しないように変更する。上記のループは、以下のようになる。

for ( nj=0; nj<ib; nj++) { … }

並列化の方針(C言語)

1.

PE

で行列

A

N

×

N

の大きさ、ベクトルx、yを

N

の大きさ、確保してよいと する。

2.

PE

は、担当の範囲のみ計算するように、ループの開始値と終了値を変 更する。ブロック分散方式では、以下になる。

N

nprc

で割り切れる場合)

ib = N / nprc

do nj=myid*ib+ 1 , (myid+ 1 )*ib …. enddo

3.

(2の並列化が完全に終了したら)各

PE

で担当の データ部分しか行列を確保しないように変更する。

上記のループは、以下のようになる。

do nj= 1 , ib …. enddo

並列化の方針( Fortran 言語)

並列化の方針(行列 - ベクトル積)(C言語)

PE0

PE1

PE2

PE3 for ( nj=0; nj<(N/4); nj++) { 内積( nj, ni ) }

for ( nj=(N/4); nj<(N/4)*2; nj++) { 内積( nj, ni ) }

for ( nj=(N/4)*2; nj<(N/4)*3; nj++) { 内積( nj, ni ) }

for ( nj=(N/4)*3; nj<N; nj++) { 内積( nj, ni ) }

※各PEで使われない領域が出るが、担当範囲指定がしやすいので実装がしやすい。

PE

N

×

N

行列を持つ場合

並列化の方針(行列 - ベクトル積)( Fortran 言語)

PE0

PE1

PE2

PE3 do nj=1, N/4

内積( nj, ni ) enddo

do nj=N/4+1, (N/4)*2 内積( nj, ni )

enddo

do nj=(N/4)*2+1, (N/4)*3 内積( nj, ni )

enddo

do nj=(N/4)*3+1, N 内積( nj, ni )

enddo

PE

N

×

N

行列を持つ場合

※各PEで使われない領域が出るが、担当範囲指定がしやすいので実装がしやすい。

並列化の方針(行列 - ベクトル積)

PE0

PE1

PE2

PE3

この方針では、y=Axのベクトルyは、以下のように一部分しか計 算されないことに注意!

並列化時の注意

演習環境は、最大

288

PEです。

 並列化は、<できた>と思ってもバグっていることが多い!

このサンプルの検証部分(

debug=1

の時に実行される部分)は、

PE0

がベ クトルyの要素すべてを所有することが前提となっています。

出力結果を考慮して検証部分も並列化してください。

 N

を小さくして、

printf

で結果(ベクトルy)を目視することも、デバックになり ます。しかし、

N

を目視できないほど大きくする場合にバグることがありま す。目視のみデバックは、経験上お勧めしません。

数学ライブラリ開発では、できるだけ数学(線形代数)の知識を利用した 方法で、理論的な解と結果を検証することをお勧めします。

ドキュメント内 Reedbush-Uアカウントの発行 (ページ 34-64)

関連したドキュメント