演習II (連続系アルゴリズム)
第1回: MPI
須田研究室 M2 本谷 徹
motoya@is.s.u-tokyo.ac.jp
演習II
●2つの講義の演習
●奇数回: 「連続系アルゴリズム」部分
●偶数回: 「計算量理論」部分
●連続系アルゴリズム部分は全8回を予定
●前半2回 … 高性能計算
●後半6回 … 数値計算
●4回以上の課題提出(プログラム+考察レポート)で単位
●http://olab.is.s.u-tokyo.ac.jp/~reiji/enshu2_12.html
高性能計算
●
高い計算性能を達成することを目的
MPIを用いた並列プログラミング
●
ネットワークで繋がれた並列環境が対象
●
分散メモリ型: 京, Blue Gene, TSUBAME
●
大規模、高性能な計算を目的としている
●
そのプロセス間通信に使われるライブラリ群
●
Message Passing Interface
MPIを用いた並列プログラミング
●
SPMD (Single Program Multiple Data)
●
各プロセスは全て同じプログラムを実行
●プロセスはシステムリソースを共有しない
–異なるプロセッサ, 異なるデータ
●C からは mpi.h を include して使用
●$ mpicc foo.c でコンパイル
●$ mpirun -np <np> a.out で実行
–-np <np> は起動するプロセスの数
MPI定義定数
●MPI_Comm MPI_COMM_WORLD
● 「コミュニケータ」 ● 通信グループとなるプロセスの情報が入っている ● MPI通信ライブラリを呼ぶときにはこれを必ず渡す ● 長くて不便? ●int MPI_SUCCESS
● MPI関数が成功したときに返る値●
MPI_Datatype MPI_CHAR, MPI_INT, MPI_DOUBLE, MPI_FLOAT …
● 対応する型を表す
●
MPI_Op MPI_MAX, MPI_MIN, MPI_SUM, MPI_PROD …
● 演算の種類を表す
● それぞれ 最大値, 最小値, 総和, 積
MPI基本API
●
int MPI_Init(int *argc, char ***argv)
●
全てのMPI関数を呼ぶ前に必ず1度だけ呼ぶ関数
●
int MPI_Finalize(void)
●
最後のMPI関数を呼んだ後に必ず1度だけ呼ぶ関数
●
int MPI_Comm_size(MPI_Comm comm, int *size)
●
size にプロセスの数が入って返ってくる関数
●
int MPI_Comm_rank(MPI_Comm comm, int *rank)
サンプルコード
#include <stdio.h> #include "mpi.h" int
main(int argc, char *argv[]){ int myid;
MPI_Init(&argc,&argv);
MPI_Comm_rank(MPI_COMM_WORLD,&myid); if(myid%10==1&&myid!=11)
printf ("I am %dst process\n", myid); else if(myid%10==2&&myid!=12)
printf ("I am %dnd process\n", myid); else if(myid%10==3&&myid!=13)
printf ("I am %drd process¥n", myid); else
printf ("I am %dth process¥n", myid); MPI_Finalize(); return 0; } hoge.c $ mpicc hoge.c $ mpirun -np 5 a.out I am 2nd process I am 1st process I am 0th process I am 3rd process I am 4thh process $ ●
実行例
・ csc では Torque の script に 実行コマンドを書いてください ・ {stderr, stdout}は (スクリプト名).{e, o}(ジョブid) に出力されますMPIでの時間計測
●以下のように時間を計測し、
全てのプロセスの最大経過時間を所要時間とする
MPI_Barrier(MPI_COMM_WORLD); t0 = MPI_Wtime(); /* ここで計算・通信をします */ MPI_Barrier(MPI_COMM_WORLD); t1 = MPI_Wtime(); elapsed_time = t1 - t0;MPI_Reduce(&elapsed_time, &max_time, 1, MPI_DOUBLE, MPI_MAX, 0, MPI_COMM_WORLD);
If (myrank==0){
printf(“elapsed time = %10.7e\n”, max_time); }
● double MPI_Wtime(void)
● 経過時間を秒で返す関数
● int MPI_Barrier(MPI_Comm comm)
MPI通信ライブラリ
●プロセス間通信関数には2種類存在
●1対1通信
●集団通信
–コミュニケータに属する全てのプロセスが参加
–通信しながら計算もしてくれるものも
●大抵はブロッキング通信
●通信が終わるまで処理が中断される
–デッドロックに注意
MPI1対1通信 (1)
●
int MPI_Send(void *buf, int count, MPI_Datatype datatype,
int dest, int tag, MPI_Comm comm)
●
int MPI_Recv(void *buf, int count, MPI_Datatype datatype,
int source, int tag, MPI_Comm comm, MPI_Status *status)
●
buf: 送受信バッファ, count: 要素数, datatype:型,
dest/source: 送信先/受信先, tag: 識別子, status: 受信結果
●
以下の例ではデッドロックします
If(myrank==0){
MPI_Send(sbuf, n, MPI_INT, 1, 0, MPI_COMM_WORLD);
MPI_Recv(rbuf, n, MPI_INT, 1, 0, MPI_COMM_WORLD, &status); }
Else if(myrank==1){
MPI_Send(buf, n, MPI_INT, 0, 0, MPI_COMM_WORLD);
MPI1対1通信 (2)
●
int MPI_Isend(void *buf, int count, MPI_Datatype datatype,
int dest, int tag, MPI_Comm comm,
MPI_Request *request)
●
int MPI_Irecv(void *buf, int count, MPI_Datatype datatype,
int source, int tag, MPI_Comm comm,
MPI_Status *status, MPI_Request *request)
●
ノンブロッキング通信
–すぐに戻ってくる
●request に状態が入る
●
int MPI_Wait(MPI_Request *request, MPI_Status *status)
●request の通信が完了するまでブロックする
MPI集団通信
● int MPI_Bcast (void *buf, int count, MPI_Datatype datatype, int root, MPI_Comm comm) ● int MPI_Reduce(void *sendbuf, void *recvbuf, int count,MPI_Datatype datatype,
MPI_Op op, int root, MPI_Comm comm)
● int MPI_Scatter(void *sendbuf, int sendcount, MPI_Datatype sendtype,
void *recvbuf, int recvcount, MPI_Datatype recvtype, int root, MPI_Comm comm)
● int MPI_Gather (void *sendbuf, int sendcount, MPI_Datatype sendtype,
void *recvbuf, int recvcount, MPI_Datatype recvtype, int root, MPI_Comm comm)
● int MPI_Allgather(void *sendbuf, int sendcount, MPI_Datatype sendtype,
void *recvbuf, int recvcount, MPI_ Datatype recvtype, MPI_Comm comm)
● int MPI_Reduce_scatter(void *sendbuf, void *recvbuf, int recvcnts, MPI_Datatype datatype,
MPI_Op op, MPI_Comm comm)
● int MPI_Allreduce(void *sendbuf, void * recvbuf, int count, MPI_Datatype datatype,
MPI_Op op, MPI_Comm comm)
● int MPI_Alltoall(void *sendbuf, int sendcount, MPI_Datatype sendtype, void *recvbuf,
int recvcount, MPI_Datatype recvtype, MPI_Comm comm)
第1回課題
●並列ソートを実装してください
●0.2 秒以下でソートできた最大の個数Nを報告
●学科計算機 csc 上にて P プロセスで実行するとする
–rand() 関数で各プロセスにN/P個の整数を発生させる
●0 ~ RAND_MAX の一様乱数
●各マシンで異なる seed を与える
–ソート終了時にも各マシンはN/P個の整数を持つ
–ソート終了時、ランク id のプロセスの整数で
ランク (id+1) の整数を超えるものは無い
–使用するノード数の上限は 8 とする
●工夫や考察をレポートにまとめてください
srand(pid)csc
●
情報科学科のGPUクラスタ
●
東工大GPUスパコン: TSUBAME 2.0 の 1 ラック
–
16 ノード
–