ct
は同期変数: pthread_cond_t ct –
などマルチスレッディングによる並列処理
34
MT -相互排除
#include <pthread.h>
#include <stdio.h>
extern int *sum(int *);
pthread_t th1, th2;
pthread_mutex_t mt = PTHREAD_MUTEX_INITIALIZER;
int gsum;
int main() {
int *ps1, *ps2;
int arg1[2]={1,5}, arg2[2] = {6,10};
pthread_create(&th1,NULL,(void*(*)(void*))sum,&arg1);
pthread_create(&th2,NULL,(void*(*)(void*))sum,&arg2);
pthread_join(th1, (void**)&ps1);
pthread_join(th2, (void**)&ps2);
printf("%d+..+%d=%d¥n", arg1[0], arg2[1], gsum);
free(ps1); free(ps2);
}
和を部分和として二つの スレッドで求めるプログラム
続く
または
pthread_mutex_init(&mt, NULL);
35
int *sum(int *arg_ptr) {
int lb = *arg_ptr;
int ub = *(arg_ptr+1);
int i, sum;
for (i=lb, sum =0; i<= ub; i++) { sum += i;}
pthread_mutex_lock(&mt);
gsum=gsum+sum;
pthread_mutex_unlock(&mt);
return 0;
}
MT -相互排除
和を部分和として二つの スレッドで求めるプログラム36
•
メッセージ通信ライブラリ(のAPI
仕様)プロセス間でのデータ授受のための通信関数のライブ ラリ(百数十) [1].
•
バージョン1994 May MPI 1.0
・・・
2015 June MPI 3.1 MPI 4.0
•
複数プロセスが協調して動作する並列実行モデル プログラム開始時に複数プロセスが一斉に実行を開 始し,一斉に終了する(MPI-1
)例)
mpirun –np 8 my_program
[1] http://www.mpi-forum.org/ MPI Forum
MPI(Message-Passing Interface)
37
•
メッセージは次の三つの組で指定される–
通信範囲を示すプロセスグループ(コミュニケータ)–
プロセスグループ中でのプロセスID
(ランク)–
通信の識別子(タグ)MPI(Message-Passing Interface)
38
MPI ー例題プログラム
#include “mpi.h”
int main(int argc, char **argv) { int myrank, error, buffer
MPI_Status status;
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &myrank);
if (myrank == 0) {
error = MPI_Send(&buffer, 1, MPI_INT,
1, 1234, MPI_COMM_WORLD);
} else if (myrank == 1) {
error = MPI_Recv(&buffer, 1, MPI_INT,
0, 1234, MPI_COMM_WORLD, &status);
}
MPI_Finalize();
}
プロセス間でデータを 授受するプログラム
39
MPI ー例題プログラム
#include “mpi.h”
int main(int argc, char **argv) { int myrank, error, buffer
MPI_Status status;
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &myrank);
if (myrank == 0) {
error = MPI_Send(&buffer, 1, MPI_INT,
1, 1234, MPI_COMM_WORLD);
} else if (myrank == 1) {
error = MPI_Recv(&buffer, 1, MPI_INT,
0, 1234, MPI_COMM_WORLD, &status);
}
MPI_Finalize();
}
MPI
プログラムの全体の枠組み ヘッダファイルの読み込みMPI
ライブラリの初期化MPI
ライブラリの終了処理40
MPI ー例題プログラム
#include “mpi.h”
int main(int argc, char **argv) { int myrank, error, buffer
MPI_Status status;
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &myrank);
if (myrank == 0) {
error = MPI_Send(&buffer, 1, MPI_INT,
1, 1234, MPI_COMM_WORLD);
} else if (myrank == 1) {
error = MPI_Recv(&buffer, 1, MPI_INT,
0, 1234, MPI_COMM_WORLD, &status);
}
MPI_Finalize();
}
バッファの指定:先頭アドレス
,
個数,
型 メッセージの送受信送受信で指定する情報
相手と文脈の指定:ランク
,
タグ,
コミュニケータ41
MPI ー例題プログラム
#include “mpi.h”
int main(int argc, char **argv) { int myrank, error, buffer
MPI_Status status;
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &myrank);
if (myrank == 0) {
error = MPI_Send(&buffer, 1, MPI_INT,
1, 1234, MPI_COMM_WORLD);
} else if (myrank == 1) {
error = MPI_Recv(&buffer, 1, MPI_INT,
0, 1234, MPI_COMM_WORLD, &status);
}
MPI_Finalize();
}
バッファの指定:先頭アドレス
,
個数,
型受信状態 メッセージの送受信
送受信で指定する情報
相手と文脈の指定:ランク
,
タグ,
コミュニケータ受信メッセージのランクやタグ(ワイルドカード受信の際に利用)など
42
MPI ー例題プログラム
#include “mpi.h”
int main(int argc, char **argv) { int myrank, error, buffer
MPI_Status status;
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &myrank);
if (myrank == 0) {
error = MPI_Send(&buffer, 1, MPI_INT,
1, 1234, MPI_COMM_WORLD);
} else if (myrank == 1) {
error = MPI_Recv(&buffer, 1, MPI_INT,
0, 1234, MPI_COMM_WORLD, &status);
}
MPI_Finalize();
}
自プロセスのランクの取得 自分のランクが
0
の場合プロセスの識別
プログラム中の各プロセスにラ ンクが付加されそれで区別する
自分のランクが
1
の場合43
MPI ー双方向通信例題プログラム
•
双方向送受信をしたい.次のコードは動作するか?if (myrank == 0) {
MPI_Send(&sb, 1, MPI_INT,
1, 1234, MPI_COMM_WORLD);
MPI_Recv(&rb, 1, MPI_INT,
1, 1234, MPI_COMM_WORLD, &status);
} else if (myrank == 1) {
MPI_Send(&sb, 1, MPI_INT,
0, 1234, MPI_COMM_WORLD);
MPI_Recv(&rb, 1, MPI_INT,
0, 1234, MPI_COMM_WORLD, &status);
}
ブロッキングsend/receiveのためデッドロック!
44
MPI ー双方向通信例題プログラム
•
双方向送受信をしたい.次のコードは動作するか?if (myrank == 0) {
MPI_Recv(&rb, 1, MPI_INT,
1, 1234, MPI_COMM_WORLD, &status);
MPI_Send(&sb, 1, MPI_INT,
1, 1234, MPI_COMM_WORLD);
} else if (myrank == 1) {
MPI_Recv(&rb, 1, MPI_INT,
0, 1234, MPI_COMM_WORLD, &status);
MPI_Send(&sb, 1, MPI_INT,
0, 1234, MPI_COMM_WORLD);
}
send/receiveの順序を入れ替えてもだめ
45
MPI ー双方向通信例題プログラム
•
双方向送受信をしたい.次のコードは動作するか?if (myrank == 0) {
MPI_Send(&sb, 1, MPI_INT,
1, 1234, MPI_COMM_WORLD);
MPI_Recv(&rb, 1, MPI_INT,
1, 1234, MPI_COMM_WORLD, &status);
} else if (myrank == 1) {
MPI_Recv(&rb, 1, MPI_INT,
0, 1234, MPI_COMM_WORLD, &status);
MPI_Send(&sb, 1, MPI_INT,
0, 1234, MPI_COMM_WORLD);
}
双方の順序を逆にする必要
46
MPI ー双方向通信例題プログラム
ノンブロッキングのIsendとWait
if (myrank == 0) {
MPI_Isend(&sb, 1, MPI_INT,
1, 1234, MPI_COMM_WORLD, &id);
MPI_Recv(&rb, 1, MPI_INT,
1, 1234, MPI_COMM_WORLD, &rstatus);
MPI_Wait(&id, &wstatus);
} else if (myrank == 1) {
MPI_Isend(&sb, 1, MPI_INT,
0, 1234, MPI_COMM_WORLD, &id);
MPI_Recv(&rb, 1, MPI_INT,
0, 1234, MPI_COMM_WORLD, &status);
MPI_Wait(&id, &wstatus);
}
Isendではブロッキングせずにreceiveに移行
47
MPI ー双方向通信例題プログラム
双方向送受信を指示する関数
if (myrank == 0) {
MPI_Sendrecv(&sb, 1, MPI_INT, 1, 1234,
&rb, 1, MPI_INT, 1, 1234, MPI_COMM_WORLD, &status);
} else if (myrank == 1) {
MPI_Sendrecv(&sb, 1, MPI_INT, 0, 1234,
&rb, 1, MPI_INT, 0, 1234, MPI_COMM_WORLD, &status);
}