演習準備 2014 年 3 月 5 日神戸大学大学院システム情報学研究科森下浩二 1 RIKEN AICS HPC Spring School /3/5

Similar documents
演習準備

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

Microsoft PowerPoint - KHPCSS pptx

演習1: 演習準備

Microsoft PowerPoint _MPI-01.pptx

NUMAの構成

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

Microsoft PowerPoint - 講義:コミュニケータ.pptx

PowerPoint プレゼンテーション

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

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

コードのチューニング

Microsoft PowerPoint _MPI-03.pptx

スライド 1

untitled

演習 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

FX10利用準備

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

openmp1_Yaguchi_version_170530

講義の流れ 並列プログラムの概要 通常のプログラムと並列プログラムの違い 並列プログラム作成手段と並列計算機の構造 OpenMP による並列プログラム作成 処理を複数コアに分割して並列実行する方法 MPI による並列プログラム作成 ( 午後 ) プロセス間通信による並列処理 処理の分割 + データの

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

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

スライド 1

課題 S1 解説 Fortran 編 中島研吾 東京大学情報基盤センター

86


課題 S1 解説 C 言語編 中島研吾 東京大学情報基盤センター

Microsoft PowerPoint MPI.v...O...~...O.e.L.X.g(...Q..)

WinHPC ppt

untitled

並列計算導入.pptx

目 目 用方 用 用 方

コードのチューニング

第8回講義(2016年12月6日)

about MPI

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

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

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

MPI コミュニケータ操作

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

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

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

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

120802_MPI.ppt

情報処理演習 II

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

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

MPI usage

スライド 1

Microsoft PowerPoint - 計算機言語 第7回.ppt

para02-2.dvi

スライド 1

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

Microsoft PowerPoint - scls_biogrid_lecture_v2.pptx

chap2.ppt

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

かし, 異なったプロセス間でデータを共有するためには, プロセス間通信や特殊な共有メモリ領域を 利用する必要がある. このためマルチプロセッサマシンの利点を最大に引き出すことができない. こ の問題はマルチスレッドを用いることで解決できる. マルチスレッドとは,1 つのプロセスの中に複 数のスレッド


MPI 超 入門 (FORTRAN 編 ) 東京大学情報基盤センター C 言語編は以下 /ohshima/seminars/t2k201111/ (MPI による並列アプリケーション開発入門 2)

Microsoft PowerPoint - 阪大CMSI pptx

nakao

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

演習1

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

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

I I / 47

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

Microsoft Word - 計算科学演習第1回3.doc

Microsoft PowerPoint - MPIprog-C [互換モード]

Microsoft PowerPoint - MPIprog-F [互換モード]

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

スライド 1

Microsoft PowerPoint - 第10回講義(2015年12月22日)-1 .pptx

< F2D837C E95CF CF68A4A94C5816A2E6A>

Sae x Sae x 1: 1. {x (i) 0 0 }N i=1 (x (i) 0 0 p(x 0) ) 2. = 1,, T a d (a) i (i = 1,, N) I, II I. v (i) II. x (i) 1 = f (x (i) 1 1, v(i) (b) i (i = 1,

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

Microsoft PowerPoint - OpenMP入門.pptx

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

02: 変数と標準入出力

1.ppt

Microsoft PowerPoint - 高速化WS富山.pptx

PowerPoint プレゼンテーション

PowerPoint Presentation

CS

Reedbush-Uアカウントの発行

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

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

< 中略 > 24 0 NNE 次に 指定した日時の時間降水量と気温を 観測地点の一覧表に載っているすべての地点について出力するプログラムを作成してみます 観測地点の一覧表は index.txt というファイルで与えられています このファイルを読みこむためのサブルーチンが AMD

Microsoft Word - Training10_プリプロセッサ.docx

memo

Microsoft PowerPoint - kougi7.ppt

Microsoft PowerPoint ppt

Fujitsu Standard Tool

MPI

Prog1_10th

PowerPoint プレゼンテーション

ÊÂÎó·×»»¤È¤Ï/OpenMP¤Î½éÊâ¡Ê£±¡Ë

< 中略 > 24 0 NNE 次に 指定した日時の時間降水量と気温を 観測地点の一覧表に載っているすべての地点について出力するプログラムを作成してみます 観測地点の一覧表は index.txt というファイルで与えられています このファイルを読みこむためのサブルーチンが AMD

並列計算プログラミング超入門

Transcription:

演習準備 2014 年 3 月 5 日神戸大学大学院システム情報学研究科森下浩二 1

演習準備の内容 神戸大 FX10(π-Computer) 利用準備 システム概要 ログイン方法 コンパイルとジョブ実行方法 MPI 復習 1. MPIプログラムの基本構成 2. 並列実行 3. 1 対 1 通信 集団通信 4. データ 処理分割 5. 計算時間計測 2

神戸大 FX10(π-Computer) 利用準備 3

神戸大 FX10(π-Computer) 富士通 PRIMEHPC FX10:1 ラック SPARC64 TM IXfx プロセッサ x 96 ノード 総理論演算性能 :20.2TFLOPS 総主記憶容量 :3TByte 1 ノード諸元表 ( 京との比較 ) FX10 (SPARC64 TM IXfx ) 京 (SPARC64 TM VIIIfx ) コア数 16 8 L1 キャッシュ ( コア ) 32KB(D)/32KB(I) 共有 L2 キャッシュ 12MB 6MB 動作周波数 1.65GHz 2.0GHz 理論演算性能 211.2GFlops 128GFlops メモリ容量 32GB 16GB 4

FX10 へのログイン方法 公開鍵認証によりログイン 手順の詳細は別紙を参照 1. 鍵ペア ( 公開鍵 秘密鍵 ) の作成 2. 仮の鍵ペアでログイン 3. 自身の公開鍵を登録 4. 自身の鍵ペアでログイン出来ることを確認 5. 仮の公開鍵を削除 5

コンパイル方法 逐次プログラム $ frtpx sample.f90 F :Fortran F C :C 言語 $ fccpx sample.c OpenMP( ノード内スレッド並列 ) $ frtpx Kopenmp sample.f90 C F $ fccpx Kopenmp sample.c MPI( ノード間プロセス並列 ) $ mpifrtpx sample.f90 C F $ mpifccpx sample.c C 6

ジョブ実行方法 ジョブスクリプトの作成 single.sh: 逐次ジョブ #!/bin/sh #PJM -L "rscgrp=school" #PJM -L "node=1" #PJM -L "elapse=10:00" #PJM -j #./a.out シェルを指定 利用リソースグループ名 利用ノード数 最大経過時間 (hh:mm:ss) 標準エラー出力をマージして出力 プログラムの実行 7 ジョブの投入 $ pjsub single.sh

ジョブ実行方法 (OpenMP) ジョブスクリプトの作成 parallel_omp.sh: スレッド並列 (OpenMP) ジョブ #!/bin/sh #PJM -L "rscgrp=school" #PJM -L "node=1" #PJM -L "elapse=10:00" #PJM -j # export OMP_NUM_THREADS=16./a.out シェルを指定 利用リソースグループ名 利用ノード数 最大経過時間 (hh:mm:ss) 標準エラー出力をマージして出力 OpenMP 並列数を指定 プログラムの実行 環境変数 OMP_NUM_THREADS に OpenMP 並列数を設定 8

ジョブ実行方法 (MPI) ジョブスクリプトの作成 parallel_mpi.sh: プロセス並列 (MPI) ジョブ #!/bin/sh #PJM -L "rscgrp=school" #PJM -L "node=4" #PJM -L "elapse=10:00" #PJM -j # mpiexec./a.out シェルを指定 利用リソースグループ名 利用ノード数 最大経過時間 (hh:mm:ss) 標準エラー出力をマージして出力 MPI プログラムの実行 利用ノード数に MPI によるプロセス並列数を設定 9

ジョブの管理 ジョブの状態表示 $ pjstat [option] -v オプション : 詳細なジョブ情報を表示 -H オプション : 終了したジョブ情報を表示 -A オプション : 全ユーザのジョブ情報を表示 ジョブのキャンセル $ pjdel [JOB_ID] [JOB_ID] はジョブ投入時に表示 ( pjstat でも確認可 ) 例 ) [JOB_ID] が 12345 のジョブをキャンセル $ pjdel 12345 10

ジョブ結果の確認 バッチジョブの実行が終了すると 標準出力ファイルと標準エラー出力ファイルがジョブ投入ディレクトリに出力される 標準出力ファイル : ジョブ名.oXXXXX 標準エラー出力ファイル : ジョブ名.eXXXXX デフォルトのジョブ名はジョブスクリプトのファイル名 XXXXX には [JOB_ID] が入る ジョブスクリプト内で #PJM -j を指定した場合には 標準エラー出力はマージされ標準出力ファイルのみ出力される 例 )p.7 の single.sh を投入し [JOB_ID] に 12345 が割り当てられた場合 : single.sh.o12345 が出力 11

ジョブ実行手順の例 1 2 プログラムの作成 プログラムのコンパイル $ vi sample.f90 $ frtpx sample.f90 3 コンパイルし実行ファイル (a.out) を作成 ジョブスクリプトの作成 $ vi single.sh 4 ジョブの投入 $ pjsub single.sh ジョブ投入時の出力例 : [INFO] PJM 0000 pjsub Job XXXXX submitted. XXXXX が割り当てられたジョブ番号 5 ジョブ状態の確認 $ pjstat 6 結果の確認 $ cat single.sh.oxxxxx 12

MPI 復習 (Fortran 編 ) 13

1. MPI プログラムの基本構成 program main use mpi MPIモジュールを読み込み implicit none integer :: nprocs, myrank, ierr F call mpi_init( ierr ) MPIの初期化処理 call mpi_comm_size( MPI_COMM_WORLD, nprocs, ierr ) MPIプロセス数を nprocs に取得 call mpi_comm_rank( MPI_COMM_WORLD, myrank, ierr ) 自身のプロセス番号を myrank に取得 ( この部分に並列実行したい処理を記述 ) call mpi_finalize( ierr ) end program main MPI の終了処理 それぞれのプロセスが何の計算をするかは nprocs や myrank の値で場合分けし うまく仕事が割り振られるようにする 14

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

2. 並列処理 Hello, world from ( プロセス番号 ) を並列に出力する Process 0 Process 1 Process 2 Process 3 Hello, world from 0 Hello, world from 1 Hello, world from 2 Hello, world from 3 16

プログラム 1 ソースファイル :mpi1.f90 program mpi1 use mpi implicit none integer :: nprocs, myrank, ierr F call mpi_init( ierr ) call mpi_comm_size( MPI_COMM_WORLD, nprocs, ierr ) call mpi_comm_rank( MPI_COMM_WORLD, myrank, ierr ) write(*, *) "Hello, world from", myrank call mpi_finalize( ierr ) end program mpi1 17

並列処理 : 実習 実習 1 プログラム 1: mpi1.f90 を作成し コンパイルした後 4 プロセスで実行し 結果を確認してください 実行結果の例 必ずしもプロセスの順番に出力されるとは限らない Hello, world from 1 Hello, world from 0 Hello, world from 3 Hello, world from 2 18

3. 通信 MPI プロセス番号 0 から受け取ったメッセージ Hello, world from に自分のプロセス番号を追加して出力する Process 0 Process 1 Process 2 Process 3 Hello, world from 通信 Hello, world from 通信 Hello, world from 通信 Hello, world from 1 Hello, world from 2 Hello, world from 3 19

通信関数 1 対 1 通信 mpi_send ( 送信 ) mpi_recv ( 受信 ) etc 集団通信 mpi_bcast ( ブロードキャスト ) mpi_reduce ( リダクション ) mpi_allreduce ( リダクション + ブロードキャスト ) etc 20

1 対 1 通信 : 送信関数 mpi_send( buff, count, datatype, dest, tag, comm, ierr ) buff: 送信するデータの変数名 ( 先頭アドレス ) count: 送信するデータの個数 ( 整数型 ) datatype: dest: tag: comm: 送信するデータの型 (MPI_INTEGER, MPI_REAL8, MPI_CHARACTER など ) 送信先のプロセス番号 メッセージ識別番号 コミュニケータ ( 例えば MPI_COMM_WORLD) ierr: 戻りコード ( 整数型 ) 21

1 対 1 通信 : 受信関数 mpi_recv( buff, count, datatype, source, tag, comm, status, ierr ) buff: 受信するデータのための変数名 ( 先頭アドレス ) count: 受信するデータの個数 ( 整数型 ) datatype: source: tag: comm: status: 受信するデータの型 (MPI_INTEGER, MPI_REAL8, MPI_CHARACTER など ) 送信元のプロセス番号 メッセージ識別番号 コミュニケータ ( 例えば MPI_COMM_WORLD) 受信状態を格納するサイズ MPI_STATUS_SIZE の配列 ( 整数型 ) ierr: 戻りコード ( 整数型 ) 22

プログラム 2 ソースファイル :mpi2.f90 program mpi2 use mpi implicit none integer :: nprocs, myrank, ierr, i, mst(mpi_status_size) character (len=17) :: msg F call mpi_init( ierr ) call mpi_comm_size( MPI_COMM_WORLD, nprocs, ierr ) call mpi_comm_rank( MPI_COMM_WORLD, myrank, ierr ) if( myrank == 0 ) then msg = "Hello, world from" do i = 1, 3 call mpi_send( msg, len(msg), MPI_CHARACTER, i, 0, MPI_COMM_WORLD, ierr ) end do else call mpi_recv( msg, len(msg), MPI_CHARACTER, 0, 0, MPI_COMM_WORLD, mst, ierr ) write(*, '(a,i5)') msg, myrank end if call mpi_finalize( ierr ) end program mpi2 23

集団通信 : ブロードキャスト root に指定したプロセスが持つ buff の値を,comm 内の他のプロセスの buff に配布する mpi_bcast( buff, count, datatype, root, comm, ierr ) buff: root が送信するデータの変数名 ( 先頭アドレス ) 他のプロセスは 同じ変数名でデータを受け取る count: 送受信するデータの個数 ( 整数型 ) datatype: root: comm: 送受信するデータの型 :MPI_INTEGER, MPI_REAL8, MPI_CHARACTER など 送信元のプロセス番号 コミュニケータ ( 例えば MPI_COMM_WORLD) ierr: 戻りコード ( 整数型 ) 24

プログラム 3 ソースファイル :mpi3.f90 program mpi3 use mpi implicit none integer :: nprocs, myrank, ierr character (len=17) :: msg F call mpi_init( ierr ) call mpi_comm_size( MPI_COMM_WORLD, nprocs, ierr ) call mpi_comm_rank( MPI_COMM_WORLD, myrank, ierr ) if( myrank == 0 ) then msg = "Hello, world from" end if call mpi_bcast( msg, len(msg), MPI_CHARACTER, 0, MPI_COMM_WORLD, ierr ) if( myrank /= 0 ) then write(*, '(a,i5)') msg, myrank end if call mpi_finalize( ierr ) end program mpi3 25

通信 : 実習 実習 2 プログラム 2: mpi2.f90, プログラム 3: mpi3.f90 を作成し コンパイルした後 4 プロセスで実行し 結果を確認してください 実行結果の例 必ずしもプロセスの順番に出力されるとは限らない Hello, world from 1 Hello, world from 3 Hello, world from 2 26

4. データ 処理分割 大きさ n の 2 個のベクトルの内積を計算するプログラムを並列化 program main implicit none integer :: i integer, parameter :: n=10000 real(8) :: v(n), w(n) real(8) :: ipr do i = 1, n v(i) = dsin(i*0.1d0) w(i) = dcos(i*0.1d0) end do ipr = 0.0d0 do i = 1, n ipr = ipr + v(i)*w(i) end do write(*, '(a,f20.15)') "answer:", ipr end program main F 各プロセスにデータ 処理を分散 例えば,n=10000 のベクトルを 4 個のプロセスで計算する場合 プロセス 0: 1-2500 のループ部分を処理 プロセス 1: 2501-5000 のループ部分を処理 プロセス 2: 5001-7500 のループ部分を処理 プロセス 3: 7501-10000 のループ部分を処理 各プロセスの部分和のリダクションが必要 mpi_reduce または mpi_allreduce 27

集団通信 : リダクション comm 内のすべてのプロセスからデータを root へ集め, 演算 (op) を適用する mpi_reduce( sendbuff, recvbuff, count, datatype, op, root, comm, ierr ) sendbuff: 送信するデータの変数名 ( 先頭アドレス ) recvbuff: 受信するデータの変数名 ( 先頭アドレス ) count: 送受信するデータの個数 ( 整数型 ) datatype: 送受信するデータの型 op: データに適用する演算の種類 :MPI_SUM( 総和 ) MPI_PROD( 掛け算 ) MPI_MAX( 最大値 ) など root: comm: 送信先のプロセス番号 コミュニケータ ( 例えば MPI_COMM_WORLD) ierr: 戻りコード ( 整数型 ) 28

集団通信 : リダクション comm 内のすべてのプロセスのデータに対して演算 (op) を適用し その結果をすべてのプロセスへ配布する mpi_allreduce( sendbuff, recvbuff, count, datatype, op, comm, ierr ) sendbuff: 送信するデータの変数名 ( 先頭アドレス ) recvbuff: 受信するデータの変数名 ( 先頭アドレス ) count: 送受信するデータの個数 ( 整数型 ) datatype: 送受信するデータの型 op: データに適用する演算の種類 :MPI_SUM( 総和 ) MPI_PROD( 掛け算 ) MPI_MAX( 最大値 ) など comm: コミュニケータ ( 例えば MPI_COMM_WORLD) ierr: 戻りコード ( 整数型 ) 29

プログラム 4 ソースファイル :mpi4.f90 program mpi4 use mpi F implicit none integer :: i, ista, iend integer, parameter :: n=10000 real(8) :: v(n), w(n) real(8) :: ipr, ans 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 ) ista = myrank*n/nprocs + 1 iend = (myrank+1)*n/nprocs do i = ista, iend v(i) = sin(i*0.1d0) w(i) = cos(i*0.1d0) end do ipr = 0.0d0 do i = ista, iend ipr = ipr + v(i)*w(i) end do call mpi_allreduce( ipr, ans, 1, MPI_REAL8, & & MPI_SUM, MPI_COMM_WORLD, ierr ) write(*, '(a,i5,a,f20.15)') "rank:", myrank, & & ", answer:", ans 30 call mpi_finalize( ierr ) end program mpi4

データ 処理分割 : 実習 実習 3 プログラム 4: mpi4.f90 を作成し コンパイルした後 4 プロセスで実行し 結果を確認してください 実行結果の例 rank: 0, answer: 3.639755648373931 rank: 1, answer: 3.639755648373931 rank: 3, answer: 3.639755648373931 rank: 2, answer: 3.639755648373931 31

5. 計算時間計測 real(8) :: time1, time2 call mpi_barrier( MPI_COMM_WORLD, ierr ) time1 = mpi_wtime() ( 計測する部分 ) call mpi_barrier( MPI_COMM_WORLD, ierr ) time2 = mpi_wtime() (time2-time1 を出力 ) 計測のための変数を倍精度実数で宣言する 開始の足並みを揃える 開始時刻を time1 に設定 終了の足並みを揃える 終了時刻を time2 に設定 time2 - time1 が計測した部分の計算時間となる F mpi_barrier( comm, ierr ) comm 内の最も遅いプロセスが到達するまで 全プロセスが待つ mpi_wtime() ある時点を基準とした経過秒数を倍精度実数で返す関数 32

計算時間計測 : 実習 実習 4 1. プログラム 4: mpi4.f90 を 並列処理部分の計算時間を計測して出力するよう修正してください 2. 並列数を変えて実行し計算時間がどう変わるか測定し 以下の表を完成させてください 並列数 n 計算時間 T(n) ( 秒 ) 速度向上率 T(n)/T(1) (n=1 の計算時間 T(1) との比 ) 33 1 1.0 2 4 8 16

MPI 復習 (C 言語編 ) 34

1. MPI プログラムの基本構成 #include "stdio.h" #include "mpi.h" MPIライブラリを読み込み int main( int argc, char **argv ){ int nprocs, myrank; C } MPI_Init( &argc, &argv ); MPIの初期化処理 MPI_Comm_size( MPI_COMM_WORLD, &nprocs ); MPIプロセス数を nprocs に取得 MPI_Comm_rank( MPI_COMM_WORLD, &myrank ); 自身のプロセス番号を myrank に取得 ( この部分に並列実行したい処理を記述 ) MPI_Finalize(); return 0; MPI の終了処理 それぞれのプロセスが何の計算をするかは nprocs や myrank の値で場合分けし うまく仕事が割り振られるようにする 35

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 プログラムの最後に必ず書く ) 36

2. 並列処理 Hello, world from ( プロセス番号 ) を並列に出力する Process 0 Process 1 Process 2 Process 3 Hello, world from 0 Hello, world from 1 Hello, world from 2 Hello, world from 3 37

プログラム 1 ソースファイル :mpi1.c #include "stdio.h" #include "mpi.h" C 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 ); printf( "Hello, world from %3d n", myrank ); } MPI_Finalize(); return 0; 38

並列処理 : 実習 実習 1 プログラム 1: mpi1.c を作成し コンパイルした後 4 プロセスで実行し 結果を確認してください 実行結果の例 必ずしもプロセスの順番に出力されるとは限らない Hello, world from 1 Hello, world from 0 Hello, world from 3 Hello, world from 2 39

3. 通信 MPI プロセス番号 0 から受け取ったメッセージ Hello, world from に自分のプロセス番号を追加して出力する Process 0 Process 1 Process 2 Process 3 Hello, world from 通信 Hello, world from 通信 Hello, world from 通信 Hello, world from 1 Hello, world from 2 Hello, world from 3 40

通信関数 1 対 1 通信 MPI_Send ( 送信 ) MPI_Recv ( 受信 ) etc 集団通信 MPI_Bcast ( ブロードキャスト ) MPI_Reduce ( リダクション ) MPI_Allreduce ( リダクション + ブロードキャスト ) etc 41

1 対 1 通信 : 送信関数 int MPI_Send( void *buff, int count, MPI_Datatype datatype, int dest, int tag, MPI_Comm comm ) buff: 送信するデータの変数名 ( 先頭アドレス ) count: 送信するデータの個数 ( 整数型 ) datatype: dest: tag: comm: 送信するデータの型 (MPI_INT, MPI_DOUBLE, MPI_CHAR など ) 送信先のプロセス番号 メッセージ識別番号 コミュニケータ ( 例えば MPI_COMM_WORLD) 戻り値 : 戻りコード ( 整数型 ) 42

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: source: tag: comm: status: 受信するデータの型 (MPI_INT, MPI_DOUBLE, MPI_CHAR など ) 送信元のプロセス番号 メッセージ識別番号 コミュニケータ ( 例えば MPI_COMM_WORLD) 受信状態を格納するオブジェクト 戻り値 : 戻りコード ( 整数型 ) 43

プログラム 2 ソースファイル :mpi2.c #include "stdio.h" #include "string.h" #include "mpi.h" int main( int argc, char **argv ){ int nprocs, myrank, i; char msg[18]; MPI_Status mst; C MPI_Init( &argc, &argv ); MPI_Comm_size( MPI_COMM_WORLD, &nprocs ); MPI_Comm_rank( MPI_COMM_WORLD, &myrank ); if( myrank == 0 ) { strcpy( msg, "Hello, world from" ); for( i = 1; i <= 3 ; i++ ){ MPI_Send( &msg, 17, MPI_CHAR, i, 0, MPI_COMM_WORLD ); } } else { MPI_Recv( &msg, 17, MPI_CHAR, 0, 0, MPI_COMM_WORLD, &mst ); printf( "%s %3d n", msg, myrank ); } } MPI_Finalize(); return 0; 44

集団通信 : ブロードキャスト 45 root に指定したプロセスが持つ buff の値を,comm 内の他のプロセスの buff に配布する int MPI_Bcast( void *buff, int count, MPI_Datatype datatype, int root, MPI_Comm comm ) buff: root が送信するデータの変数名 ( 先頭アドレス ) 他のプロセスは 同じ変数名でデータを受け取る count: 送受信するデータの個数 ( 整数型 ) datatype: root: comm: 送受信するデータの型 送信元のプロセス番号 コミュニケータ ( 例えば MPI_COMM_WORLD) 戻り値 : 戻りコード ( 整数型 )

プログラム 3 ソースファイル :mpi3.c #include "stdio.h" #include "string.h" #include "mpi.h" int main( int argc, char **argv ){ int nprocs, myrank; char msg[18]; MPI_Init( &argc, &argv ); MPI_Comm_size( MPI_COMM_WORLD, &nprocs ); MPI_Comm_rank( MPI_COMM_WORLD, &myrank ); C if( myrank == 0 ) { strcpy( msg, "Hello, world from" ); } MPI_Bcast( &msg, 17, MPI_CHAR, 0, MPI_COMM_WORLD ); if( myrank!= 0) { printf( "%s %3d n", msg, myrank ); } } MPI_Finalize(); return 0; 46

通信 : 実習 実習 2 プログラム 2: mpi2.c, プログラム 3: mpi3.c を作成し コンパイルした後 4 プロセスで実行し 結果を確認してください 実行結果の例 必ずしもプロセスの順番に出力されるとは限らない Hello, world from 1 Hello, world from 3 Hello, world from 2 47

4. データ 処理分割 大きさ n の 2 個のベクトルの内積を計算するプログラムを並列化 48 #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) ); } C for( ipr = 0.0, i = 0; i < n; i++ ){ ipr += v[i]*v[i] } printf( "answer: %20.15lf n", ipr ); return 0; 各プロセスにデータ 処理を分散 例えば,n=10000 のベクトルを 4 個のプロセスで計算する場合 プロセス 0: 0-2499 のループ部分を処理 プロセス 1: 2500-4999 のループ部分を処理 プロセス 2: 5000-7499 のループ部分を処理 プロセス 3: 7500-9999 のループ部分を処理 各プロセスの部分和のリダクションが必要 MPI_Reduce または MPI_Allreduce

集団通信 : リダクション comm 内のすべてのプロセスからデータを root へ集め, 演算 (op) を適用する int MPI_Reduce( void *sendbuff, void *recvbuff, int count, MPI_Datatype datatype, MPI_Op op, int root, MPI_Comm comm ) sendbuff: 送信するデータの変数名 ( 先頭アドレス ) recvbuff: 受信するデータの変数名 ( 先頭アドレス ) count: 送受信するデータの個数 ( 整数型 ) datatype: 送受信するデータの型 op: データに適用する演算の種類 :MPI_SUM( 総和 ) MPI_PROD( 掛け算 ) MPI_MAX( 最大値 ) など root: comm: 送信先のプロセス番号 コミュニケータ ( 例えば MPI_COMM_WORLD) 戻り値 : 戻りコード ( 整数型 ) 49

集団通信 : リダクション comm 内のすべてのプロセスのデータに対して演算 (op) を適用し その結果をすべてのプロセスへ配布する int MPI_Allreduce( void *sendbuff, void *recvbuff, int count, MPI_Datatype datatype, MPI_Op op, MPI_Comm comm ) sendbuff: 送信するデータの変数名 ( 先頭アドレス ) recvbuff: 受信するデータの変数名 ( 先頭アドレス ) count: 送受信するデータの個数 ( 整数型 ) datatype: 送受信するデータの型 op: データに適用する演算の種類 :MPI_SUM( 総和 ) MPI_PROD( 掛け算 ) MPI_MAX( 最大値 ) など comm: コミュニケータ ( 例えば MPI_COMM_WORLD) 戻り値 : 戻りコード ( 整数型 ) 50

プログラム 4 ソースファイル :mpi4.c #include "stdio.h" #include "mpi.h" #include "math.h" int main( int argc, char **argv ){ int i, ista, iend; const int n=10000; double v[n], w[n]; double ipr, ans; int nprocs, myrank; MPI_Init( &argc, &argv ); MPI_Comm_size( MPI_COMM_WORLD, &nprocs ); MPI_Comm_rank( MPI_COMM_WORLD, &myrank ); ista = myrank*n/nprocs; iend = (myrank+1)*n/nprocs; for( i = ista; i < iend; i++ ){ v[i] = sin( 0.1*(i+1) ); w[i] = cos( 0.1*(i+1) ); } for( ipr = 0.0, i = ista; i < iend; i++ ){ ipr += v[i]*w[i]; } MPI_Allreduce( &ipr, &ans, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD ); C printf( "rank: %d, answer: %20.15lf n", myrank, ans ); 51 } MPI_Finalize(); return 0;

データ 処理分割 : 実習 実習 3 プログラム : mpi4.c を作成し コンパイルした後 4 プロセスで実行し 結果を確認してください 実行結果の例 rank: 0, answer: 3.639755648373932 rank: 1, answer: 3.639755648373932 rank: 3, answer: 3.639755648373932 rank: 2, answer: 3.639755648373932 52

5. 計算時間計測 double time1, time2; MPI_Barrier( MPI_COMM_WORLD ); time1 = MPI_Wtime(); ( 計測する部分 ) MPI_Barrier( MPI_COMM_WORLD ); time2 = MPI_Wtime(); (time2-time1 を出力 ) 計測のための変数を倍精度実数で宣言する 開始の足並みを揃える 開始時刻を time1 に設定 終了の足並みを揃える 終了時刻を time2 に設定 time2 - time1 が計測した部分の計算時間となる C int MPI_Barrier( MPI_Comm comm ) comm 内の最も遅いプロセスが到達するまで 全プロセスが待つ double MPI_Wtime( void ) ある時点を基準とした経過秒数を倍精度実数で返す関数 53

計算時間計測 : 実習 実習 4 1. プログラム 4: mpi4.c を 並列処理部分の計算時間を計測して出力するよう修正してください 2. 並列数を変えて実行し計算時間がどう変わるか測定し 以下の表を完成させてください 並列数 n 計算時間 T(n) ( 秒 ) 速度向上率 T(n)/T(1) (n=1 の計算時間 T(1) との比 ) 54 1 1.0 2 4 8 16