Microsoft PowerPoint - 演習2:MPI初歩.pptx

Similar documents
演習準備

Microsoft PowerPoint - 講義:片方向通信.pptx

Microsoft PowerPoint - 演習1:並列化と評価.pptx

±é½¬£²¡§£Í£Ð£É½éÊâ

Microsoft PowerPoint _MPI-03.pptx

untitled

Microsoft PowerPoint - S1-ref-F.ppt [互換モード]

演習 II 2 つの講義の演習 奇数回 : 連続系アルゴリズム 部分 偶数回 : 計算量理論 部分 連続系アルゴリズム部分は全 8 回を予定 前半 2 回 高性能計算 後半 6 回 数値計算 4 回以上の課題提出 ( プログラム + 考察レポート ) で単位

2 T 1 N n T n α = T 1 nt n (1) α = 1 100% OpenMP MPI OpenMP OpenMP MPI (Message Passing Interface) MPI MPICH OpenMPI 1 OpenMP MPI MPI (trivial p

目 目 用方 用 用 方

演習1: 演習準備

WinHPC ppt


86

<4D F736F F F696E74202D D F95C097F D834F E F93FC96E5284D F96E291E85F8DE391E52E >

<4D F736F F F696E74202D C097F B A E B93C782DD8EE682E890EA97705D>

コードのチューニング

情報処理概論(第二日目)

untitled

Microsoft PowerPoint - MPIprog-F1.ppt [互換モード]

(Microsoft PowerPoint \211\211\217K3_4\201i\216R\226{_\211\272\215\342\201j.ppt [\214\335\212\267\203\202\201[\203h])

Microsoft PowerPoint 並列アルゴリズム04.ppt

並列計算導入.pptx

PowerPoint プレゼンテーション

¥Ñ¥Ã¥±¡¼¥¸ Rhpc ¤Î¾õ¶·

openmp1_Yaguchi_version_170530

内容に関するご質問は まで お願いします [Oakforest-PACS(OFP) 編 ] 第 85 回お試しアカウント付き並列プログラミング講習会 ライブラリ利用 : 科学技術計算の効率化入門 スパコンへのログイン テストプログラム起動 東京大学情報基盤セ

Fundamental MPI 1 概要 MPI とは MPI の基礎 :Hello World 全体データと局所データタ グループ通信 (Collective Communication) 1 対 1 通信 (Point-to-Point Communication)

C/C++ FORTRAN FORTRAN MPI MPI MPI UNIX Windows (SIMD Single Instruction Multipule Data) SMP(Symmetric Multi Processor) MPI (thread) OpenMP[5]

44 6 MPI 4 : #LIB=-lmpich -lm 5 : LIB=-lmpi -lm 7 : mpi1: mpi1.c 8 : $(CC) -o mpi1 mpi1.c $(LIB) 9 : 10 : clean: 11 : -$(DEL) mpi1 make mpi1 1 % mpiru

char int float double の変数型はそれぞれ 文字あるいは小さな整数 整数 実数 より精度の高い ( 数値のより大きい より小さい ) 実数 を扱う時に用いる 備考 : 基本型の説明に示した 浮動小数点 とは数値を指数表現で表す方法である 例えば は指数表現で 3 書く

PowerPoint Presentation

Fundamental MPI 1 概要 MPI とは MPI の基礎 :Hello World 全体データと局所データタ グループ通信 (Collective Communication) 1 対 1 通信 (Point-to-Point Communication)

コマンドラインから受け取った文字列の大文字と小文字を変換するプログラムを作成せよ 入力は 1 バイトの表示文字とし アルファベット文字以外は変換しない 1. #include <stdio.h> 2. #include <ctype.h> /*troupper,islower,isupper,tol

PowerPoint プレゼンテーション

memo

PowerPoint Presentation

Microsoft PowerPoint - 阪大CMSI pptx

Microsoft PowerPoint - MPIprog-F1.ppt [互換モード]

Microsoft PowerPoint - MPIprog-F2.ppt [互換モード]


MPI によるプログラミング概要 Fortran 編 中島研吾 東京大学情報基盤センター

120802_MPI.ppt

2007年度 計算機システム演習 第3回

MPI によるプログラミング概要 C 言語編 中島研吾 東京大学情報基盤センター

Microsoft PowerPoint - lec10.ppt

C プログラミング演習 1( 再 ) 2 講義では C プログラミングの基本を学び 演習では やや実践的なプログラミングを通して学ぶ

書式に示すように表示したい文字列をダブルクォーテーション (") の間に書けば良い ダブルクォーテーションで囲まれた文字列は 文字列リテラル と呼ばれる プログラム中では以下のように用いる プログラム例 1 printf(" 情報処理基礎 "); printf("c 言語の練習 "); printf

Microsoft Word - Cプログラミング演習(12)

Microsoft PowerPoint - MPIprog-C2.ppt [互換モード]

PowerPoint プレゼンテーション

Transcription:

演習 2:MPI 初歩 - 並列に計算する - 2013 年 8 月 6 日 神戸大学大学院システム情報学研究科計算科学専攻横川三津夫

MPI( メッセージ パッシング インターフェース ) を使おう! [ 演習 2 の内容 ] はじめの一歩課題 1: Hello, world を並列に出力する. 課題 2: プロセス 0 からのメッセージを受け取る (1 対 1 通信 ). 部分に分けて計算しよう課題 3:2 個のベクトルの内積を求める. 課題 4: 結果を配布する. 課題 5: 並列数を変えてみよう. π(=3.141592 ) を計算しよう. 課題 6: MPI の基本的な関数 ( サブルーチン ) を復習しながら進めます. 解説では,Fortran 言語によるプログラムを用います.C 言語版の資料は後半にあります. 演習用のプログラムファイルは, 以下のディレクトリに置いてありますので, 利用して下さい. Fortran 言語版 /tmp/school/ex2/fortran/ C 言語版 /tmp/school/ex2/c/ 2013/8/6 RIKEN AICS HPC Summer School 2013:MPI 初歩 1

Fortran 言語編 2013/8/6 RIKEN AICS HPC Summer School 2013:MPI 初歩 2

復習 MPI プログラムの基本構成 program main use mpi implicit none integer :: nprocs, myrank, ierr call mpi_init( ierr ) call mpi_comm_size( MPI_COMM_WORLD, nprocs, ierr ) call mpi_comm_rank( MPI_COMM_WORLD, myrank, ierr ) MPI を使うおまじない MPI で使う変数の宣言 MPI の初期化 ( おまじない 2) MPI で使うプロセス数を nprocs に取得自分のプロセス番号を myrank に取得 ( この部分に並列実行するプログラムを書く ) call mpi_finalize( ierr ) MPI の終了処理 ( おまじない 3) end program main それぞれのプロセスが何の計算をするかは,myrank の値で場合分けし, うまく仕事が割り振られるようにする. ( このファイルは,/tmp/school/ex2/fortran/skelton.f90 にあります ) 2013/8/6 RIKEN AICS HPC Summer School 2013:MPI 初歩 3

復習 MPI プログラムの基本構成 ( 説明 ) call mpi_init( ierr ) MPI の初期化を行う.MPI プログラムの最初に必ず書く. call mpi_comm_size( MPI_COMM_WORLD, nprocs, ierr ) MPI の全プロセス数を取得し,2 番目の引数 nprocs( 整数型 ) に取得する. MPI_COMM_WORLD はコミュニケータと呼ばれ, 最初に割り当てられるすべてのプロセスの集合 call mpi_comm_rank( MPI_COMM_WORLD, myrank, ierr ) 自分のプロセス番号 (0 から nprocs 1 のどれか ) を,2 番目の引数 myrank ( 整数型 ) に取得する. call mpi_finalize( ierr ) MPI の終了処理をする.MPI プログラムの最後に必ず書く. 2013/8/6 RIKEN AICS HPC Summer School 2013:MPI 初歩 4

課題 1 Hello, world を並列に出力する. プログラム hello.f90 を利用し, Hello, world from ( プロセス番号 ) を表示する並列プログラムを作成しなさい. 1 hello.f90 に,2 ページ MPI プログラムの基本構成 を参考にし, 並列化する. 2 print 文に, 自分のプロセス番号 (myrank) を出力するよう修正する. 3 プログラムを作成したら, コンパイルし,4 プロセスで実行せよ. 実行結果の例 必ずしも, プロセスの順番に出力されるとは限らない. Hello, world from 1 Hello, world from 0 Hello, world from 3 Hello, world from 2 ( このファイルは,/tmp/school/ex2/fortran/hello.f90 にあります ) 2013/8/6 RIKEN AICS HPC Summer School 2013:MPI 初歩 5

π- コンピュータでのプログラムの実行手順 1 プログラム作成 : エディタを用いてプログラム (xxx.f90) を作成 ( 修正 ) 2 プログラムのコンパイル :# mpifrtpx xxx.f90 入力コマンドです. a.out が作られる. 3 ジョブスクリプトを作成 : エディタを用いて,job.sh を作成 4 ジョブを投入 : # pjsub ( ジョブスクリプトファイル名 ) [INFO] PJM xxxx pjsub JOB nnnnn submitted. 注意 nnnnn がジョブ番号 ( ジョブに与えられたシステム内で唯一の番号 ) 5 ジョブ状態の確認 : # pjstat 6 結果の確認 : job.sh.onnnnn を確認する. 2013/8/6 RIKEN AICS HPC Summer School 2013:MPI 初歩 6

ジョブスクリプトファイル例 (job.sh) #!/bin/bash #PJM L rscgrp=school #PJM L node=8 #PJM L elapse=00:03:00 mpiexec n 4./a.out おまじない 1 おまじない 2: 実行キューの指定 利用する計算ノード数 (24 まで可能 ) 計算時間の予測値 ( 実際の計算時間よりも少し大きく ) MPI プログラムの実行. この例では,MPI プロセス数が 4 であることに注意 他の課題においても, このジョブスクリプトを適宜, 修正のこと. ( このファイルは,/tmp/school/ex2/fortran/job.sh にあります ) 2013/8/6 RIKEN AICS HPC Summer School 2013:MPI 初歩 7

復習 1 対 1 通信 送信関数 ( 送り出し側 ) mpi_send( buff, count, datatype, dest, tag, comm, ierr ) buff: 送信するデータの変数名 ( 先頭アドレス ) count: 送信するデータの数 ( 整数型 ) datatype: 送信するデータの型 MPI_INTEGER, MPI_DOUBLE_PRECISION, MPI_CHARACTER など dest: 送信先のプロセス番号 tag: comm: メッセージ識別番号. 送るデータを区別するための番号 コミュニケータ ( 例えば,MPI_COMM_WORLD) ierr: 戻りコード ( 整数型 ) 2013/8/6 RIKEN AICS HPC Summer School 2013:MPI 初歩 8

復習 1 対 1 通信 受信関数 ( 受け取り側 ) mpi_recv( buff, count, datatype, source, tag, comm, status, ierr ) buff: 受信するデータのための変数名 ( 先頭アドレス ) count: 受信するデータの数 ( 整数型 ) datatype: 受信するデータの型 MPI_INTEGER, MPI_DOUBLE_PRECISION, MPI_CHARACTER など source: 送信してくる相手のプロセス番号 tag: comm: メッセージ識別番号. 送られて来たデータを区別するための番号 コミュニケータ ( 例えば,MPI_COMM_WORLD) status: 受信の状態を格納するサイズ MPI_STATUS_SIZE の配列 ( 整数型 ) ierr: 戻りコード ( 整数型 ) 2013/8/6 RIKEN AICS HPC Summer School 2013:MPI 初歩 9

課題 2 プロセス 0 からのメッセージを受け取る (1 対 1 通信 ) MPI プロセス番号 0 から受け取ったメッセージに自分のプロセス番号を追加して表示するプログラムを作成せよ. プロセス 0 の処理と他のプロセスの処理は,myrank の値による場合分けを行う. プロセス番号 0 の処理 1 送るメッセージを作る. メッセージの長さはきめておく. - 例えば, Hello, world from (17 文字 ) 2 mpi_send 関数で他のプロセスにメッセージを送る. 他のプロセスの処理 1 プロセス番号 0 から送られてくるメッセージを,mpi_recv 関数で受け取る. 2 送られたメッセージに自分のプロセス番号を追加して出力する. 実行結果の例 Hello, world from 1 Hello, world from 3 Hello, world from 2 2013/8/6 RIKEN AICS HPC Summer School 2013:MPI 初歩 10

課題 3 2 個のベクトルの内積を求める. 次のプログラムは,2 個のベクトルの内積を計算するプログラムである. 並列化せよ. また, 並列化したプログラムにおいて, 赤で示した部分に相当する部分の計算時間を計測せよ. program InnerProduct implicit none integer :: i integer, parameter :: n=10000 real(kind=8) :: v(n), w(n) real(kind=8) :: ipr do i = 1, n v(i) = dsin(i*0.1d0) w(i) = dcos(i*0.1d0) enddo ipr = 0.0d0 do i = 1, n ipr = ipr + v(i)*w(i) enddo print *, ipr end program InnerProduct ベクトルの長さ ( 定数 ) 2 個のベクトルを格納する配列の宣言 2 個のベクトルを設定 倍精度のsin 関数倍精度のcos 関数 2 個のベクトルの内積を計算 計算結果の出力 ( このファイルは,/tmp/school/ex2/fortran/ipr.f90 にあります ) 2013/8/6 RIKEN AICS HPC Summer School 2013:MPI 初歩 11

課題 3 のヒント 1 各プロセスで部分和を計算する. n 個のデータを p 個のプロセスで分割した時の第 i プロセス (i は 0 から p 1) の部分和の区間は,[(i*n)/p+1, ((i+1)*n)/p] になる. ただし, この演習では, n は p で割り切れるものとする. 第 i プロセスの番号は,myrank と同じになることに注意. 例えば,n=10000 のベクトルを4 個のプロセスで計算する場合 プロセス0: 1 2500の部分和を計算 プロセス1: 2501 5000の部分和を計算 プロセス2: 5001 7500の部分和を計算 プロセス3: 7501 10000の部分和を計算 2 プロセス 1,2,3 は,mpi_send 関数で, 部分和をプロセス 0 に送る. 3 プロセス 0 は, 他のプロセスから送られた部分和を mpi_recv 関数で受け取り, 自分の部分和と足し合わせ, 最終的な総和を計算し, 出力する. プロセス 0 の処理と他のプロセスの処理は,myrank の値による場合分けを行う. 2013/8/6 RIKEN AICS HPC Summer School 2013:MPI 初歩 12

課題 3 のヒント 計算時間の計測をする方法 real(kind=8) :: time0, time2 call mpi_barrier( MPI_COMM_WORLD, ierr ) time0 = mpi_wtime() 計測のための変数を倍精度実数で宣言する. MPI_barrier 関数で, 開始の足並みを揃える. mpi_wtime 関数で開始時刻を time0 に設定 ( 計測する部分 ) call mpi_barrier( MPI_COMM_WORLD, ierr ) time1 = mpi_wtime() (time1 time0 を出力する ) 全プロセスで終了の足並みを揃える. mpi_wtime 関数で終了時刻を time1 に設定 time1 time0 が計測した部分の計算時間となる. mpi_barrier(comm, ierr ) comm: コミュニケータ ( 例えば,MPI_COMM_WORLD) ierr: 戻りコード ( 整数型 ) var = mpi_wtime() 2013/8/6 RIKEN AICS HPC Summer School 2013:MPI 初歩 13

復習 集団通信 - reduction mpi_reduce( sendbuff, recvbuff, count, datatype, op, root, comm, ierr ) comm で指定されたすべてのプロセスからデータを root が集め, 演算 (op) を適用する. sendbuff: 送信するデータの変数名 ( 先頭アドレス ) recvbuff: 受信するデータの変数名 ( 先頭アドレス ) count: データの個数 ( 整数型 ) datatype: 送信するデータの型 MPI_INTEGER, MPI_DOUBLE_PRECISION, MPI_CHARACTER など op: 集まってきたデータに適用する演算の種類 MPI_SUM( 総和 ),MPI_PROD( 掛け算 ),MPI_MAX( 最大値 ) など root: comm: データを集める MPI プロセス番号 コミュニケータ ( 例えば,MPI_COMM_WORLD) ierr: 戻りコード ( 整数型 ) 2013/8/6 RIKEN AICS HPC Summer School 2013:MPI 初歩 14

復習 集団通信 - broadcast mpi_bcast( buff, count, datatype, root, comm, ierr ) root が持つ buff の値を,comm で指定された他のプロセスの buff に配布する. buff: 送り主 (root) が送信するデータの変数名 ( 先頭アドレス ) 他のMPIプロセスは, 同じ変数名でデータを受け取る. count: データの個数 ( 整数型 ) datatype: 送信するデータの型 MPI_INTEGER, MPI_DOUBLE_PRECISION, MPI_CHARACTER など root: 送り主のMPIプロセス番号 comm: コミュニケータ ( 例えば,MPI_COMM_WORLD) ierr: 戻りコード ( 整数型 ) 2013/8/6 RIKEN AICS HPC Summer School 2013:MPI 初歩 15

復習 集団通信 - reduction mpi_allreduce( sendbuff, recvbuff, count, datatype, op, comm, ierr ) mpi_reduce と mpi_bcast を同時に行える関数. すべてのプロセスで同じ結果 ( 総和など ) が得られる. sendbuff: 送信するデータの変数名 ( 先頭アドレス ) recvbuff: 受信するデータの変数名 ( 先頭アドレス ) count: データの個数 ( 整数型 ) datatype: 送信するデータの型 MPI_INTEGER, MPI_DOUBLE_PRECISION, MPI_CHARACTER など op: 集まってきたデータに適用する演算の種類 MPI_SUM( 総和 ),MPI_PROD( 掛け算 ),MPI_MAX( 最大値 ) など comm: コミュニケータ ( 例えば,MPI_COMM_WORLD) ierr: 戻りコード ( 整数型 ) 2013/8/6 RIKEN AICS HPC Summer School 2013:MPI 初歩 16

課題 4 結果を配布する 課題 4 1 課題 3 で作成した並列プログラムについて, 1 mpi_reduce を使って書き換えなさい. ただし, 計算結果の総和は, プロセス 0 で求めることにすること. 2 mpi_bcast を用いてプロセス 0 で求めた総和を, すべてのプロセスに配布しなさい. 3 各プロセスで総和を出力し, 正しく計算が出来ていることを確認しなさい. 課題 4 2 課題 4 1 と同様のことを,mpi_allreduce を使って書き換え, 結果が正しいこ とを確認しなさい. 2013/8/6 RIKEN AICS HPC Summer School 2013:MPI 初歩 17

課題 5 並列数を変えてみよう. 並列計算の目的は, 計算時間を短縮することである. 課題 4 1 で作成したプログラムを用い, 並列数を変えて計算時間を計測しなさい. また, 以下の表を完成させ, どのくらい計算時間が短縮されるか確かめなさい. 並列数 n 計算時間 T(n) ( 秒 ) 速度向上率 T(n)/T(1) (n=1の計算時間 T(1) との比 ) 1 1.0 2 4 8 16 2013/8/6 RIKEN AICS HPC Summer School 2013:MPI 初歩 18

課題 6 π(=3.141592 ) を計算しよう. 次の π を求めるプログラムを並列化しなさい. また, 並列数を変えて時間を計測し, 課題 5 で作成した表と同様の表を作成しなさい. program pi implicit none integer, parameter :: n=1000000 integer :: i real(kind=8) :: x, dx, p dx = 1.0d0/dble(n) p = 0.0d0 do i = 1, n x = dble(i)*dx p = p + 4.0d0/(1.0d0 + x*x)*dx enddo π 4 1 print *, p end program pi 総和部分を部分和に分けて, 最終的に総和を求めるプログラムにする. ( このファイルは,/tmp/school/ex2/fortran/pi.f90 にあります ) 2013/8/6 RIKEN AICS HPC Summer School 2013:MPI 初歩 19

C 言語編 2013/8/6 RIKEN AICS HPC Summer School 2013:MPI 初歩 20

復習 MPI プログラムの基本構成 #include mpi.h int main( int argc, char **argv ) { int nprocs, myrank; MPI_init( &argc, &argv ); MPI_Comm_size( MPI_COMM_WORLD, &nprocs ); MPI_Comm_rank( MPI_COMM_WORLD, &myrank ); MPI を使うおまじない MPI で使う変数の宣言 MPI の初期化 ( おまじない 2) MPI で使うプロセス数を nprocs に取得自分のプロセス番号を myrank に取得 ( この部分に並列実行するプログラムを書く ) } MPI_Finalize() ; return 0 ; MPI の終了処理 ( おまじない 3) それぞれのプロセスが何の計算をするかは,myrank の値で場合分けし, うまく仕事が割り振られるようにする. ( このファイルは,/tmp/school/ex2/c/skelton.c にあります ) 2013/8/6 RIKEN AICS HPC Summer School 2013:MPI 初歩 21

復習 MPI プログラムの基本構成 ( 説明 ) int MPI_Init(int *argc, char ***argv ) MPI の初期化を行う.MPI プログラムの最初に必ず書く. int MPI_Comm_size( MPI_Comm comm, int *nprocs ) MPI の全プロセス数を取得し,2 番目の引数 nprocs( 整数型 ) に取得する. MPI_COMM_WORLD はコミュニケータと呼ばれ, 最初に割り当てられるすべてのプロセスの集合 int MPI_Comm_rank( MPI_Comm comm, int *myrank ) 自分のプロセス番号 (0 から nprocs 1 のどれか ) を,2 番目の引数 myrank ( 整数型 ) に取得する. int MPI_Finalize(void) MPI の終了処理をする.MPI プログラムの最後に必ず書く. 2013/8/6 RIKEN AICS HPC Summer School 2013:MPI 初歩 22

課題 1 Hello, world を並列に出力する. プログラム hello.c を利用し, Hello, world from ( プロセス番号 ) を表示する並列プログラムを作成しなさい. 1 hello.c に,21 ページ MPI プログラムの基本構成 を参考にし, 並列化する. 2 printf 文に, 自分のプロセス番号 (myrank) を出力するよう修正する. 3 プログラムを作成したら, コンパイルし,4 プロセスで実行せよ. 実行結果の例 必ずしも, プロセスの順番に出力されるとは限らない. Hello, world from 2 Hello, world from 3 Hello, world from 0 Hello, world from 1 ( このファイルは,/tmp/school/ex2/c/hello.c にあります ) 2013/8/6 RIKEN AICS HPC Summer School 2013:MPI 初歩 23

π- コンピュータでのプログラムの実行手順 1 プログラム作成 : エディタを用いてプログラム (xxx.c) を作成 ( 修正 ) 2 プログラムのコンパイル :# mpifccpx xxx.c lmpi ( lm) 入力コマンドです. a.out が作られる. 3 ジョブスクリプトを作成 : エディタを用いて,job.sh を作成 4 ジョブを投入 : # pjsub ( ジョブスクリプトファイル名 ) [INFO] PJM xxxx pjsub JOB nnnnn submitted. 注意 nnnnn がジョブ番号 ( ジョブに与えられたシステム内で唯一の番号 ) 5 ジョブ状態の確認 : # pjstat 6 結果の確認 : job.sh.onnnnn を確認する. 2013/8/6 RIKEN AICS HPC Summer School 2013:MPI 初歩 24

ジョブスクリプトファイル例 (job.sh) #!/bin/bash #PJM L rscgrp=school #PJM L node=8 #PJM L elapse=00:03:00 mpiexec n 4./a.out おまじない 1 おまじない 2: 実行キューの指定 利用する計算ノード数 (24 まで可能 ) 計算時間の予測値 ( 実際の計算時間よりも少し大きく ) MPI プログラムの実行. この例では,MPI プロセス数が 4 であることに注意 他の課題においても, このジョブスクリプトを適宜, 修正のこと. ( このファイルは,/tmp/school/ex2/c/job.sh にあります ) 2013/8/6 RIKEN AICS HPC Summer School 2013:MPI 初歩 25

復習 1 対 1 通信 送信関数 ( 送り出し側 ) int MPI_Send(void *buff, int count, MPI_Datatype datatype, int dest, int tag, MPI_Comm comm) buff: 送信するデータの変数名 ( 先頭アドレス ) count: 送信するデータの個数 datatype: 送信するデータの型 MPI_CHAR, MPI_INT, MPI_DOUBLE など dest: 送信先のMPIプロセス番号 tag: comm: メッセージ識別番号. 送るデータを区別するための番号 コミュニケータ ( 例えば,MPI_COMM_WORLD) 関数の戻りコードは, エラーコード 2013/8/6 RIKEN AICS HPC Summer School 2013:MPI 初歩 26

復習 1 対 1 通信 受信関数 ( 受け取り側 ) int MPI_Recv(void *buff, int count, MPI_Datatype datatype, int source, int tag, MPI_Comm comm, MPI_Status *status) buff: 送信するデータの変数名 ( 先頭アドレス ) count: 送信するデータの個数 datatype: 送信するデータの型 MPI_CHAR, MPI_INT, MPI_DOUBLE など source: 送信先のMPIプロセス番号 tag: comm: メッセージ識別番号. 送るデータを区別するための番号 コミュニケータ ( 例えば,MPI_COMM_WORLD) status: 状況オブジェクト.MPI_Send にはないので注意. 関数の戻りコードは, エラーコード 2013/8/6 RIKEN AICS HPC Summer School 2013:MPI 初歩 27

課題 2 プロセス 0 からのメッセージを受け取る (1 対 1 通信 ) プロセス番号 0 から受け取ったメッセージに自分のプロセス番号を追加して表示するプログラムを作成せよ. プロセス 0 の処理と他のプロセスの処理は,myrank の値による場合分けを行う. プロセス 0 の処理 1 送るメッセージを作る. メッセージの長さはきめておく. - 例えば, Hello, world from (17 文字 ) 2 MPI_Send 関数で他のプロセスにメッセージを送る. 他のプロセスの処理 1 プロセス 0 から送られてくるメッセージを,MPI_Recv 関数で受け取る. 2 送られたメッセージに自分のプロセス番号を追加して出力する. 実行結果の例 Hello, world from 1 Hello, world from 3 Hello, world from 2 参考 文字列の扱い #include string.h char str[18]; strcpy( str, Hello, world from ) ; 2013/8/6 RIKEN AICS HPC Summer School 2013:MPI 初歩 28

課題 3 2 個のベクトルの内積を求める. 次のプログラムは,2 個のベクトルの内積を計算するプログラムである. 並列化せよ. また, 並列化したプログラムにおいて, 赤で示した部分に相当する部分の計算時間を計測せよ. #include stdio.h #inlucde math.h int main( int argc, char **argv ) { int i; const int n=10000; double v[n], w[n]; double ipr; for( i=0; i<n; i++ ){ v[i] = sin( 0.1*(i+1) ); w[i] = cos( 0.1*(i+1) ); } for( ipr=0.0, i=0; i<n; i++ ){ ipr += v[i]*v[i] } printf( Inner product = %20.15lf n, ipr); return 0; ベクトルの長さ ( 定数 ) 2 個のベクトルを格納する配列の宣言 2 個のベクトルを設定倍精度の sin 関数倍精度の cos 関数 2 個のベクトルの内積を計算 計算結果の出力 } ( このファイルは,/tmp/school/ex2/c/ipr.c にあります ) 2013/8/6 RIKEN AICS HPC Summer School 2013:MPI 初歩 29

課題 3 のヒント 1 各プロセスで部分和を計算する. n 個のデータを p 個のプロセスで分割した時の第 i プロセス (i は 0 から p 1) の部分和の区間は,[(i*n)/p+1, ((i+1)*n)/p] になる. ただし, この演習では, n は p で割り切れるものとする. 第 i プロセスは,myrank と同じ値であることに注意. 例えば,n=10000 のベクトルを4 個のプロセスで計算する場合 プロセス0: 1 2500の部分和を計算 プロセス1: 2501 5000の部分和を計算 プロセス2: 5001 7500の部分和を計算 プロセス3: 7501 10000の部分和を計算 2 プロセス 1,2,3 は,MPI_Send 関数で, 部分和をプロセス 0 に送る. 3 プロセス 0 は, 他のプロセスから送られた部分和を MPI_Recv 関数で受け取り, 自分の部分和と足し合わせ, 最終的な総和を計算し, 出力する. プロセス 0 の処理と他のプロセスの処理は,myrank の値による場合分けを行う. 2013/8/6 RIKEN AICS HPC Summer School 2013:MPI 初歩 30

課題 3 のヒント 計算時間の計測をする方法 double time0, time2 ; MPI_Barrier( MPI_COMM_WORLD ); time0 = MPI_Wtime(); 計測のための変数を倍精度実数で宣言する. MPI_Barrier 関数で, 開始の足並みを揃える. MPI_Wtime 関数で開始時刻を time0 に設定 ( 計測する部分 ) MPI_Barrier( MPI_COMM_WORLD ); time1 = MPI_Wtime(); (time1 time0 を出力する ) 全プロセスで終了の足並みを揃える. MPI_Wtime 関数で終了時刻を time1 に設定 time1 time0 が計測した部分の計算時間となる. int MPI_Barrier(MPI_Comm comm) : コミュニケータ間で同期を取る. comm: コミュニケータ ( 例えば,MPI_COMM_WORLD) double MPI_Wtime(void) : time の現行値 ( 秒数 ) を倍精度浮動小数点で返す 2013/8/6 RIKEN AICS HPC Summer School 2013:MPI 初歩 31

復習 集団通信 - reduction int MPI_Reduce(void *sendbuff, void *recvbuff, int count, MPI_Datatype datatype, MPI_Op op, int root, MPI_Comm comm) comm で指定されたすべてのプロセスからデータを root が集め, 演算 (op) を適用する. sendbuff: 送信するデータの変数名 ( 先頭アドレス ) recvbuff: 受信するデータの変数名 ( 先頭アドレス ) count: データの個数 datatype: 送信するデータの型 MPI_INT, MPI_DOUBLE, MPI_CHAR など op: 集まってきたデータに適用する演算の種類 MPI_SUM( 総和 ),MPI_PROD( 掛け算 ),MPI_MAX( 最大値 ) など root: データを集めるMPIプロセス番号 comm: コミュニケータ ( 例えば,MPI_COMM_WORLD) 関数の戻りコードは, エラーコードを表す. 2013/8/6 RIKEN AICS HPC Summer School 2013:MPI 初歩 32

復習 集団通信 - broadcast int MPI_Bcast(void *buff, int count, MPI_Datatype datatype, int root, MPI_Comm comm) root が持つ buff の値を,comm で指定された他のプロセスの buff に配布する. buff: 送り主 (root) が送信するデータの変数名 ( 先頭アドレス ) 他の MPI プロセスは, 同じ変数名でデータを受け取る. count: データの個数 datatype: 送信するデータの型 MPI_INT, MPI_DOUBLE, MPI_CHAR など root: 送り主のMPIプロセス番号 comm: コミュニケータ ( 例えば,MPI_COMM_WORLD) 関数の戻りコードは, エラーコードを表す. 2013/8/6 RIKEN AICS HPC Summer School 2013:MPI 初歩 33

復習 集団通信 - reduction int MPI_Allreduce( void *sendbuff, void *recvbuff, int count, MPI_Datatype datatype, MPI_Op op, MPI_Comm comm ) MPI_Reduce と MPI_Bcast を同時に行える関数. すべてのプロセスで同じ結果 ( 総和など ) が得られる. sendbuff: 送信するデータの変数名 ( 先頭アドレス ) recvbuff: 受信するデータの変数名 ( 先頭アドレス ) count: データの個数 datatype: 送信するデータの型 MPI_INT, MPI_DOUBLE, MPI_CHAR など op: 集まってきたデータに適用する演算の種類 MPI_SUM( 総和 ),MPI_PROD( 掛け算 ),MPI_MAX( 最大値 ) など comm: コミュニケータ ( 例えば,MPI_COMM_WORLD) 関数の戻りコードは, エラーコードを表す. 2013/8/6 RIKEN AICS HPC Summer School 2013:MPI 初歩 34

課題 4 結果を配布する 課題 4 1 課題 3 で作成した並列プログラムについて, 1 MPI_Reduce を使って書き換えなさい. ただし, 計算結果の総和は, プロセス 0 で求めることにすること. 2 MPI_Bcast を用いてプロセス 0 で求めた総和を, すべてのプロセスに配布しなさい. 3 各プロセスで総和を出力し, 正しく計算が出来ていることを確認しなさい. 課題 4 2 課題 4 1 と同様のことを,MPI_Allreduce を使って書き換え, 結果が正しいこ とを確認しなさい. 2013/8/6 RIKEN AICS HPC Summer School 2013:MPI 初歩 35

課題 5 並列数を変えてみよう. 並列計算の目的は, 計算時間を短縮することである. 課題 4 1 で作成したプログラムを用い, 並列数を変えて計算時間を計測しなさい. また, 以下の表を完成させ, どのくらい計算時間が短縮されるか確かめなさい. 並列数 n 計算時間 T(n) ( 秒 ) 速度向上率 T(n)/T(1) (n=1の計算時間 T(1) との比 ) 1 1.0 2 4 8 16 2013/8/6 RIKEN AICS HPC Summer School 2013:MPI 初歩 36

課題 6 π(=3.141592 ) を計算しよう. 次の π を求めるプログラムを並列化しなさい. また, 並列数を変えて時間を計測し, 課題 5 で作成した表と同様の表を作成しなさい. #include stdio.h int main( int argc, char **argv ) { int i; const int n=1000000; double dx, x, pi; dx = 1.0/n; for( pi=0.0, i=1; i<=n; i++ ){ x = i*dx; pi += 4.0*dx/(1.0+x*x); } π 4 1 } printf( pi = %20.14lf^n, pi ); return 0; 総和部分を部分和に分けて, 最終的に総和を求めるプログラムにする. ( このファイルは,/tmp/school/ex2/c/pi.c にあります ) 2013/8/6 RIKEN AICS HPC Summer School 2013:MPI 初歩 37