Microsoft PowerPoint - GPGPU実践基礎工学(web).pptx

Similar documents
Microsoft PowerPoint - 先端GPGPUシミュレーション工学特論(web).pptx

NUMAの構成

Slides: TimeGraph: GPU Scheduling for Real-Time Multi-Tasking Environments

Microsoft PowerPoint - OpenMP入門.pptx

スライド 1

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

1.overview

Microsoft PowerPoint - KHPCSS pptx

スライド 1

研究背景 大規模な演算を行うためには 分散メモリ型システムの利用が必須 Message Passing Interface MPI 並列プログラムの大半はMPIを利用 様々な実装 OpenMPI, MPICH, MVAPICH, MPI.NET プログラミングコストが高いため 生産性が悪い 新しい並

about MPI

並列計算導入.pptx

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

memo

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

NUMAの構成

(Microsoft PowerPoint \215u\213`4\201i\221\272\210\344\201j.pptx)

memo

Microsoft PowerPoint _MPI-01.pptx

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

Microsoft Word - openmp-txt.doc

Microsoft PowerPoint - OS07.pptx

Microsoft PowerPoint - compsys2-06.ppt

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

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

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

演習準備

目 目 用方 用 用 方

演習1: 演習準備

Microsoft PowerPoint ppt

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

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

XcalableMP入門

スライド 1

program7app.ppt

N08

AICS 村井均 RIKEN AICS HPC Summer School /6/2013 1

コードのチューニング

PowerPoint プレゼンテーション

enshu5_4.key

WinHPC ppt

memo

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

XACC講習会

Insert your Title here

Slide 1

1. GPU コンピューティング GPU コンピューティング GPUによる 汎用コンピューティング GPU = Graphics Processing Unit CUDA Compute Unified Device Architecture NVIDIA の GPU コンピューティング環境 Lin

TopSE並行システム はじめに

本文ALL.indd

情報処理演習 II

スライド 1

Microsoft PowerPoint - sales2.ppt

N 体問題 長岡技術科学大学電気電子情報工学専攻出川智啓

PowerPoint プレゼンテーション

openmp1_Yaguchi_version_170530

PowerPoint プレゼンテーション

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

第1回 プログラミング演習3 センサーアプリケーション

ビッグデータ分析を高速化する 分散処理技術を開発 日本電気株式会社

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

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

PowerPoint プレゼンテーション

コードのチューニング

chap2.ppt

OpenMPプログラミング

Taro-ポインタ変数Ⅰ(公開版).j

Microsoft PowerPoint - sps14_kogi6.pptx

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

PowerPoint プレゼンテーション

プログラミング実習I

untitled

kiso2-09.key

スライド 1

CUDA 連携とライブラリの活用 2

Microsoft PowerPoint - 高速化WS富山.pptx

Microsoft Word ●IntelクアッドコアCPUでのベンチマーク_吉岡_ _更新__ doc

VXPRO R1400® ご提案資料

Class Overview

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

02: 変数と標準入出力

PowerPoint プレゼンテーション

para02-2.dvi

01-introduction.ppt

Microsoft PowerPoint - 6.PID制御.pptx

RX ファミリ用 C/C++ コンパイラ V.1.00 Release 02 ご使用上のお願い RX ファミリ用 C/C++ コンパイラの使用上の注意事項 4 件を連絡します #pragma option 使用時の 1 または 2 バイトの整数型の関数戻り値に関する注意事項 (RXC#012) 共用

cp-7. 配列

Microsoft PowerPoint - 11Web.pptx

Microsoft PowerPoint - 03_What is OpenMP 4.0 other_Jan18

計算機アーキテクチャ

Microsoft PowerPoint - GPGPU実践基礎工学(web).pptx

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

次に示す数値の並びを昇順にソートするものとする このソートでは配列の末尾側から操作を行っていく まず 末尾の数値 9 と 8 に着目する 昇順にソートするので この値を交換すると以下の数値の並びになる 次に末尾側から 2 番目と 3 番目の 1

インテル アーキテクチャプラットフォーム リーダーシップ 2000 年 12 月 21 日 第 14 回数値流体力学シンポジウム インテル株式会社 ia 技術本部本部長坂野勝美

enshu5_6.key

概要 プログラミング論 変数のスコープ, 記憶クラス. メモリ動的確保. 変数のスコープ 重要. おそらく簡単. 記憶クラス 自動変数 (auto) と静的変数 (static). スコープほどではないが重要.

HPC143

この方法では, 複数のアドレスが同じインデックスに対応づけられる可能性があるため, キャッシュラインのコピーと書き戻しが交互に起きる性のミスが発生する可能性がある. これを回避するために考案されたのが, 連想メモリアクセスができる形キャッシュである. この方式は, キャッシュに余裕がある限り主記憶の

プログラミング及び演習 第1回 講義概容・実行制御

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

プログラミング実習I

Transcription:

並列計算の概念 ( プロセスとスレッド ) 長岡技術科学大学電気電子情報工学専攻出川智啓

今回の内容 並列計算の分類 並列アーキテクチャ 並列計算機システム 並列処理 プロセスとスレッド スレッド並列化 OpenMP プロセス並列化 MPI 249

CPU の性能の変化 動作クロックを向上させることで性能を向上 http://pc.watch.impress.co.jp/docs/2003/0227/kaigai01.htm より引用 250

CPU の性能の変化 増加し続けるトランジスタ数をコアの増加に充てる クロックを遅くすることで発熱を抑制 251 http://www.gdep.jp/page/view/248 より引用

CPU の性能の変化 FLOPS = 1 コアの演算性能 コア数 CPU の動作周波数 1 コアの演算性能の向上 演算器 ( トランジスタ ) の増加 コア数の増加 トランジスタ数の増加 CPU の動作周波数 回路の効率化や印可電圧の向上 コンパイラの最適化を利用 複数のコアを使うようにプログラムを書かないと速くならない 劇的な性能向上は期待できない 252

CPU の性能の変化 シングルコア 動作クロックを向上させることで性能を向上 CPUの動作は指数関数的に高速化 遅いプログラムでもCPUを新しくすれば高速化 マルチコア 効率的な利用には並列計算を意識したプログラミングが必要 待っていればCPUが勝手に速くなっていった時代はもう終わり Free Lunch is Over ( タダ飯食いは終わり ) 253

並列処理による高速化 処理を N 個に分割して各コアが処理を分担 実行時間が 1/N に高速化されると期待 資源 1 資源 2 資源 3 資源 4 シングルコア CPU 資源 1 資源 2 資源 3 資源 4 資源 1 資源 2 資源 3 資源 4 マルチコア CPU 処理時間 254

並列処理による高速化 Hyper Threading Technology 一つの物理 CPUを複数のCPUに見せる技術 CPU 内のレジスタやパイプラインの空きを利用 10~20% 程度の高速化 資源 1 資源 2 資源 3 資源 4 シングルコア CPU Hyper Threading Technology 資源 1 資源 2 資源 3 資源 4 処理時間 255

並列計算の分類 並列アーキテクチャ プロセッサレベルでの処理の並列化 データの処理と命令の並列性に着目 並列計算機システム 計算機レベルでの処理の並列化 計算機のメモリ構成に着目 並列処理 プログラムレベルでの処理の並列化 処理の並列化の方法に着目 256

並列アーキテクチャの分類 プロセッサの分類 Flynn の分類 並列アーキテクチャのグループ分け データの処理と命令の並列性に着目 1.SISD 単一命令単一データ 2.SIMD 単一命令複数データ 3.MISD 複数命令単一データ 4.MIMD 複数命令複数データ 257

Single Instruction Single Data stream 単一命令単一データ 一つのデータに対して一つの処理を実行 逐次アーキテクチャ, 単一アーキテクチャ 一度に一つの命令を実行 パイプライン処理することで並列処理が可能 命令 データ A + B 258

Single Instruction Multiple Data streams 単一命令複数データ 複数のまとまったデータに対して同じ演算を同時に実行 命令は一つ, その命令が同時に多くのデータに対して適用されるアーキテクチャ 数値シミュレーションに最適 数学のベクトルや配列計算の概念に一致 ベクトルプロセッサとも呼ばれる GPU も ( 一応 ) ここに分類 データ 命令 A 0 B 0 A 1 B 1 + A 2 B 2 A 3 B 3 259

CPU の SIMD 拡張命令セット SSE(Streaming SIMD Extensions) 1 命令で 4 個の単精度浮動小数点データを一括処理 インラインアセンブラで命令を記述 コンパイラの最適化で利用されることを期待 AVX(Advanced Vector Extensions) 1 命令で 8 個の単精度浮動小数点データを一括処理 1 命令で 4 個の倍精度浮動小数点データを一括処理 260

Multiple Instructions Single Data stream 複数命令単一データ 複数のプロセッサが単一のデータに対して異なる処理を同時に実行 形式上分類されているだけ 実際にはほとんど見かけない 対故障冗長計算 命令 誤り訂正機能 (ECC) を持たない GPU (Tesla 以外 ) を 2 個同時に利用 A + B 計算して結果を比較, 異なっていればやり直し データ A B 261

Multiple Instructions Multiple Data streams 複数命令複数データ 複数のデータに対して複数の処理を同時に実行 一般的な並列コンピュータ 複数のプロセッサがプログラマから見え, プロセッサごとに異なる命令を実行 対称マルチプロセッサ 複数の同一種類のプロセッサを持つどのプロセッサでも同じようにプログラムを実行できる 非対称マルチプロセッサ 複数のプロセッサを持つが, 各プロセッサは同一種類ではないプロセッサごとに処理の最適化ができる データ 命令 A 0 + B 0 A 1 / B 1 A 2 B 2 A 3 * B 3 262

その他の分類 Single Program Multiple Data Streams 単一プログラム複数データ MIMD システムのプログラミング手法 現在のスーパーコンピュータや PC クラスタでプログラムを作る際の標準的な手法 各 PC 用にプログラムを作らず, 一つのプログラムの中で役割を認識 263

その他の分類 Single Instruction Multiple Threads 単一命令複数スレッド GPU のアーキテクチャ 一つの命令に対して, レジスタと演算器のペアがそれぞれデータを処理 CPU では逐次処理が基本で,SIMD 用の演算器を使って並列処理 SIMT では並列処理が基本 264

並列計算の分類 並列アーキテクチャ プロセッサレベルでの処理の並列化 データの処理と命令の並列性に着目 並列計算機システム 計算機レベルでの処理の並列化 計算機のメモリ構成に着目 並列処理 プログラムレベルでの処理の並列化 処理の並列化の方法に着目 265

並列計算機システム 並列処理の基本 処理を何らかの方法で分割 分割した処理をプロセッサ ( やコア ) に割り当て同時に処理 並列計算機システム 複数のプロセッサをもつ 主にメモリに違いがある 1. 共有メモリシステム 2. 分散メモリシステム 3. ハイブリッドシステム 266

共有メモリシステム 複数のプロセッサがメモリ空間を共有 分割した処理は各プロセッサ上で並列的に処理 共有されたメモリ空間上の変数は全ての CPU( やコア ) からアクセス ( 読み書き ) 可能 他からアクセスされない変数を持つことも可能 CPU CPU CPU CPU メモリ 267

共有メモリシステム 各プロセッサが同等な条件でメモリにアクセス SMP : Symmetric Multi Processor 物理的に共有されていないが SMP に見えるシステム NUMA : Non Uniform Memory Access SMP NUMA CPU CPU メモリ CPU CPU メモリ メモリ CPU CPU メモリ CPU CPU メモリ 268

分散メモリシステム 複数のプロセッサが独立なメモリ空間を持つ 分割した処理は各 PC 上で並列的に処理 共有されたメモリ空間上の変数は全て共有されない データの共有には通信を行う CPU CPU CPU CPU メモリ メモリ メモリ メモリ 269 高速ネットワーク,LAN

ハイブリッドシステム 大規模な分散メモリシステム MPP : Massively Parallel Processor 1 ノードが共有メモリシステムからなる MPP SMP/MPP ハイブリッドシステム ~16CPUs ~16CPUs ~16CPUs CPU CPU CPU CPU CPU CPU キャッシュ キャッシュ キャッシュ キャッシュ キャッシュ キャッシュ メモリ メモリ メモリ 270 高速ネットワーク

並列計算の分類 並列アーキテクチャ プロセッサレベルでの処理の並列化 データの処理と命令の並列性に着目 並列計算機システム 計算機レベルでの処理の並列化 計算機のメモリ構成に着目 並列処理 プログラムレベルでの処理の並列化 処理の並列化の方法に着目 271

並列処理の分類 タスク並列 独立なタスクを異なる CPU, コアで同時に実行 データ並列 独立なタスクが処理するデータを分割し, 異なる CPU, コアが参照し, 処理を実行 Embarrassingly parallel (perfectly parallel) 各 CPU, コアが同じタスクを異なるパラメータで実行 GPUが各ピクセルの色を決定し, ディスプレイに描画する処理 あるタスクに対してパラメータの影響を調査するような問題 天気予報等での活用が期待されている 272

タスク並列 独立な処理 A, B, C を各 CPU, コアが実行 逐次処理 コア 処理 A 処理 B 処理 C 並列処理 コア 1 処理 A 処理 C コア 2 処理 B 高速化 273

データ並列 独立な処理 A, B, C が取り扱うデータを分割して実行 逐次処理 コア 処理 A 処理 B 処理 C 並列処理 コア 1 処理 A 処理 B 処理 C コア 2 処理 A 処理 B 処理 C 高速化 274

Embarrassingly Parallel ある処理 A を複数の異なるパラメータで実行 逐次処理 コア 処理 A パラメータ 1 処理 A パラメータ 2 並列処理 コア 1 処理 A パラメータ 1 コア 2 処理 A パラメータ 2 高速化 275

プロセスとスレッド プログラムの実行を抽象化した概念 プロセス OS から資源を割り付けられたプログラムの状態 命令実行を行うスレッドとメモリ空間を含む スレッド プロセスの中における命令実行を抽象化した概念 276

プロセス OS から資源を割り付けられ, 実行状態 ( または待機状態 ) にあるプログラム プログラムで定められた命令実行 割り当てられたメモリの管理 システムプロセス OS の実行に関係するプログラム ユーザプロセス ユーザ権限で実行されているプログラム 277

マルチプロセス 複数のプロセスが存在し, 並列に実行 プロセスが一つのみ シングルプロセス プロセスが二つ以上 マルチプロセス マルチプロセスに対応した OS が必要 現在の OS はマルチプロセスに対応 シングルコア CPU 一つでもマルチプロセスが可能 OS が複数のプロセスを切替 複数のプロセスが並列に実行されているように見せる 278

マルチプロセス 各プロセスに専用のメモリ領域を割り当て CPUやメモリは複数のプログラムに割り当てられる プログラムはCPUやメモリを独占しているように振る舞う プロセス A スレッド CPU メモリ OS メモリ プロセス B スレッド メモリ 279

スレッド プログラムの処理の最小実行単位 プロセス内で複数のスレッドが存在 1プロセスに一つ シングルスレッド 1プロセスに二つ以上 マルチスレッド シングルプロセス シングルスレッド マルチスレッド マルチプロセス シングルスレッド マルチスレッド 280

マルチスレッド 一つのプロセスに二つ以上のスレッドが存在 一つのプロセスには専用のメモリ領域が割り当てられる プロセス内の複数のスレッドはメモリ領域を共有 プロセス A スレッド スレッド CPU メモリ OS メモリプロセスB スレッドスレッド メモリ 281

並列処理と並行処理 並列処理 Parallel Processing 一つの処理を複数の処理に分割 複数の処理が協調しながら処理を実行 真の並列処理複数のプロセッサにそれぞれ一つのプロセス 疑似並列処理一つのプロセッサに複数のプロセス 並行処理 Concurrent Processing 複数の処理を実行 複数の処理は必ずしも協調していない 282

並列計算 Parallel Computing 計算を複数に分割 各処理を計算機, プロセッサ, プロセス, スレッドが担当 複数の計算機 スーパーコンピュータ,PCクラスタ 複数のプロセッサ ワークステーション 複数のコア マルチコアCPU, GPU 283

並列計算の方法 マルチスレッド 計算を複数に分割し, 一つの処理を一つのスレッドが担当 複数のスレッドはメモリ領域を共有 複数スレッドの協調処理は容易 OpenMP (Open Multi Processing) プログラムに指示句 ( ディレクティブ ) を挿入 ディレクティブで指定した箇所が自動で並列化 非常にお手軽な並列化方法 284

並列計算の方法 マルチプロセス 計算を複数に分割し, 一つの処理を一つのプロセスが担当 異なるプロセス同士はメモリの共有が不可能 協調して処理を行うにはデータを共有する手段が必要 MPI (Message Passing Interface) 異なるプロセス間でデータを交換する仕組みを提供 細かい命令を記述 並列化に手間はかかるが高い性能を達成 285

マルチスレッド

対象 並列アーキテクチャ (SIMD) CPUレベルでの処理の並列化 データの処理と命令の並列性に着目 並列計算機システム ( 共有メモリ計算機 ) 計算機レベルでの処理の並列化 計算機のメモリ構成に着目 並列処理 ( データ並列 ) プログラムレベルでの処理の並列化 処理の並列化の方法に着目 287

OpenMP 共有メモリシステムの並列処理に利用 標準化されたオープンな規格 OpenMP をサポートしているコンパイラであれば同じ書き方が可能 並列化したい箇所をコンパイラに指示 ディレクティブを挿入 コンパイラが対応していなければコメントとして扱われる 修正が最小限で済み, 共通のソースコードで管理 288

OpenMP による並列化 処理を並列実行したい箇所に指示句 ( ディレクティブ ) を挿入 for 文の並列化 ディレクティブを一行追加 (#pragma omp ~) #pragma omp parallel for for(int i=0; i<n; i++) C[i] = A[i] + B[i] 289

ベクトル和 C=A+B の計算 配列要素に対して計算順序の依存性がなく, 最も単純に並列化可能 a[i] + + + + + + b[i] c[i] 290

逐次 ( 並列化前 ) プログラム #include<stdio.h> #define N (1024*1024) int main(){ float a[n],b[n],c[n]; int i; for(i=0; i<n; i++) c[i] = a[i] + b[i]; for(i=0; i<n; i++) printf("%f+%f=%f n", a[i],b[i],c[i]); } return 0; for(i=0; i<n; i++){ a[i] = 1.0; b[i] = 2.0; c[i] = 0.0; } vectoradd.c 291

逐次 ( 並列化前 ) プログラム #include<stdio.h> #include<stdlib.h> #define N (1024*1024) #define Nbytes (N*sizeof(float)) int main(){ float *a,*b,*c; int i; a = (float *)malloc(nbytes); b = (float *)malloc(nbytes); c = (float *)malloc(nbytes); for(i=0; i<n; i++){ a[i] = 1.0; b[i] = 2.0; c[i] = 0.0; } } for(i=0; i<n; i++) c[i] = a[i] + b[i]; for(i=0; i<n; i++) printf("%f+%f=%f n", a[i],b[i],c[i]); free(a); free(b); free(c); return 0; vectoradd_malloc.c 292

逐次 ( 並列化前 ) プログラム malloc/free 指定したバイト数分のメモリを確保 / 解放 stdlib.h をインクルードする必要がある sizeof #include<stdlib.h> main(){ int *a; a = (int *)malloc( sizeof(int)*100 ); free(a); } データ型 1 個のサイズ ( バイト数 ) を求める printf("%d, %d n", sizeof(float), sizeof(double)); 実行すると 4,8 と表示される 293

並列化プログラム ( スレッド並列 ) #include<stdio.h> #include<stdlib.h> #define N (1024*1024) #define Nbytes (N*sizeof(float)) #include<omp.h> int main(){ float *a,*b,*c; int i; a = (float *)malloc(nbytes); b = (float *)malloc(nbytes); c = (float *)malloc(nbytes); } a[i] = 1.0; b[i] = 2.0; c[i] = 0.0; } #pragma omp for//for 文を分担して実行 for(i=0; i<n; i++) c[i] = a[i] + b[i]; for(i=0; i<n; i++) printf("%f+%f=%f n", a[i],b[i],c[i]); // 複数スレッドで処理する領域を指定 // この指定だけだと全スレッドが同じ処理を行う #pragma omp parallel { #pragma omp for//for 文を分担して実行 for(i=0; i<n; i++){ } free(a); free(b); free(c); return 0; vectoradd.cpp 294

処理の並列化 データ並列 for ループをスレッドの数だけ分割 分割された for ループを各スレッドが実行 実行時間は 1/ スレッド数になると期待 スレッド 0 スレッド 1 a[i] スレッド 0 for(i=0; i<n/2 1; i++) c[i] = a[i] + b[i]; + + + + b[i] スレッド 1 for(i=n/2; i<n; i++) c[i] = a[i] + b[i]; c[i] 295

プログラムのコンパイルと実行 コンパイル時にコンパイルオプションを付与 fopenmp fopenmp を付けるとディレクティブを処理 fopenmp を付けないとディレクティブは処理されない grouse では ソースファイルの拡張子は.cではなく.cpp コンパイラはccではなくg++ g++ fopenmp vectoradd.cpp 296

速度向上率 N 個の CPU コア PC で並列処理 理想的には 1 個で処理した時の N 倍高速化 処理時間に着目して評価 速度向上率 S T (1) T ( N) T(1) : 1 個の CPU コア PC で処理した時間 T(N) : N 個の CPU コア PC で処理した時間 並列化効率 E S( N) N 297

速度向上率 よい計算機, 計算アルゴリズム, プログラム 悪い計算機, 計算アルゴリズム, プログラム N 1 N 1 理想 理想 速度向上率 並列化効率 速度向上率 並列化効率 1 1 並列度 N 0 1 1 並列度 N 0 298

計算時間の変化 6 5 Processing time [ms] 4 3 2 1 0 1 2 3 4 5 6 7 8 9 10 11 12 Number of Threads 299

速度向上率 12 11 10 Speedup ratio 9 8 7 6 5 4 3 ideal 2 1 1 2 3 4 5 6 7 8 9 10 11 12 Number of Threads 300

マルチプロセス

対象 並列アーキテクチャ (MIMD, SPMD) CPUレベルでの処理の並列化 データの処理と命令の並列性に着目 並列計算機システム ( 分散メモリ計算機 ) 計算機レベルでの処理の並列化 計算機のメモリ構成に着目 並列処理 ( データ並列 ) プログラムレベルでの処理の並列化 処理の並列化の方法に着目 302

Single Program Multiple Data streams 単一プログラム複数データ MIMD システムのプログラミング手法 現在のスーパーコンピュータや PC クラスタでプログラムを作る際の標準的な手法 各 PC 用にプログラムを作らず, 一つのプログラムの中で役割を認識 303

MPI (Message Passing Interface) メッセージ通信用ライブラリの標準規格の一つ 分散メモリシステムの並列処理に利用 共有メモリシステムでも動作 共有できないメモリ内のデータを, ネットワークを介して送受信 送受信されるデータをメッセージと呼ぶ 304

MPI の処理の概要 通信を行うノード ( 計算機,CPU, コアなど ) の集合を定義 各ノードに 0 から n 1(n はノード総数 ) の番号を付与 各ノードでどのような処理を行うかを記述 通常の四則演算や関数呼出 メッセージ通信 どのノードへデータを送るか, どのノードからデータを受け取るか 各ノード用にプログラムを書くのではなく, 一つのプログラム内で各ノードが行う処理を書く 305

ベクトル和 C=A+B の計算 配列要素に対して計算順序の依存性がなく, 最も単純に並列化可能 a[i] + + + + + + b[i] c[i] 306

逐次 ( 並列化前 ) プログラム #include<stdio.h> #include<stdlib.h> #define N (1024*1024) #define Nbytes (N*sizeof(float)) int main(){ float *a,*b,*c; int i; a = (float *)malloc(nbytes); b = (float *)malloc(nbytes); c = (float *)malloc(nbytes); for(i=0; i<n; i++){ a[i] = 1.0; b[i] = 2.0; c[i] = 0.0; } } for(i=0; i<n; i++) c[i] = a[i] + b[i]; for(i=0; i<n; i++) printf("%f+%f=%f n", a[i],b[i],c[i]); free(a); free(b); free(c); return 0; vectoradd_malloc.c 307

並列化プログラム ( プロセス並列 ) #include<stdlib.h> #include<mpi.h> #define N (1024*1024) int main(int argc, char* argv[]){ float *a, *b, *c; int i, nsize, rank, nproc, bytes; //MPI のライブラリを初期化して実行準備 MPI_Init(&argc, &argv); // 全ノード数を取得 MPI_Comm_size(MPI_COMM_WORLD, &nproc); // 各ノードに割り振られた固有の番号を取得 MPI_Comm_rank(MPI_COMM_WORLD, &rank); // 各ノードで処理するデータサイズを設定 nsize = N/nproc; if(rank==nproc 1)nsize+=N%nproc; bytes = sizeof(float)*nsize; a=(float *)malloc(bytes);// 各ノード b=(float *)malloc(bytes);// でメモリを c=(float *)malloc(bytes);// 確保 // 各ノードで配列の初期化と加算を実行 for(i=0;i<nsize;i++){ a[i]=1.0; b[i]=2.0; c[i]=0.0; } for(int i=0;i<nsize;i++) c[i] = a[i]+b[i]; // 全ノードの同期を取る MPI_Barrier(MPI_COMM_WORLD); free(a); free(b); free(c); MPI_Finalize();//MPI のライブラリを終了 return 0; } vectoradd_mpi.cpp 308

MPI ライブラリの内容 MPI_Init MPI のライブラリを初期化 MPI_COMM_WORLD という名前のノードの集合を用意 MPI_Comm_rank(MPI_COMM_WORLD, &rank) 各ノードに割り振られた固有の番号を取得 MPI_Comm_size(MPI_COMM_WORLD, &nproc) 全ノード数を取得 MPI_Barrier(MPI_COMM_WORLD) 各ノード間の同期をとる MPI_Finalize MPI のライブラリを終了 309

処理の並列化 データ並列 for ループをスレッドの数だけ分割 分割された for ループを各ノードが実行 実行時間は 1/ スレッド数になると期待 ノード 0 ノード 1 a[i] ノード 0 for(i=0; i<n/2 1; i++) c[i] = a[i] + b[i]; + + + + b[i] ノード 1 for(i=0; i<n/2 1; i++) c[i] = a[i] + b[i]; c[i] 310

プログラムのコンパイルと実行 コンパイル, 実行には MPI 用のコンパイラや実行プログラムを利用 コンパイル mpic++ mpic++ vectoradd_mpi.cpp 標準で a.out という実行ファイルを作成 ( これまでと同じ ) 実行 mpiexec mpiexec n 4./a.out n 4 プロセスの数を4で実行 grouseでは mca btl ^openib というオプションも必要 311

計算時間の変化 9 Processing time [ms] 8 7 6 5 4 3 2 MPI OpenMP 1 0 1 2 3 4 5 6 7 8 9 10 11 12 Number of Threads 312

高速化率 12 11 10 Speedup ratio 9 8 7 6 5 4 3 ideal 2 1 1 2 3 4 5 6 7 8 9 10 11 12 Number of Threads 313

OpenMP との比較 OpenMP よりも若干実行に時間がかかる MPI を利用するための準備が必要 OpenMP の並列化の上限は 1 ノード内の CPU のコア数 MPI の並列化の上限は計算機システム上の CPU の全コア数 大規模な計算をするには MPI しか選択肢がない 314

ハイブリッドシステム 大規模な分散メモリシステム MPP : Massively Parallel Processor 1 ノードが共有メモリシステムからなる MPP SMP/MPP ハイブリッドシステム ~16CPUs ~16CPUs ~16CPUs CPU CPU CPU CPU CPU CPU キャッシュ キャッシュ キャッシュ キャッシュ キャッシュ キャッシュ メモリ メモリ メモリ 315 高速ネットワーク

ハイブリッドシステムでのプログラミング 大規模な計算では MPI しか選択肢がない 全て MPI でプログラムを作成 (Flat MPI) メモリが共有できないノード間では MPI メモリが共有できるノード内も MPI MPI と OpenMP でプログラムを作成 (Hybrid MPI) メモリが共有できないノード間では MPI メモリが共有できるノード内は OpenMP 316

並列処理の性能評価 速度向上率 アムダールの法則 (Amdahl s law) スケーリング 強いスケーリング (strong scaling) 弱いスケーリング (weak scaling) 317

速度向上率 N 個の CPU コア PC で並列処理 理想的には1 個で処理した時のN 倍高速化 N 倍の基準は? 処理時間?FLOPS? 速度向上率 処理時間に着目して評価 S T (1) T ( N) T(1) : 1 個の CPU コア PC で処理した時間 T(N) : N 個の CPU コア PC で処理した時間 並列化効率 E S( N) N 318

アムダールの法則 並列度を大きくした際の性能向上の予測 問題のサイズは固定 並列化が不可能な箇所の割合によって性能向上の上限が決定 S T (1) T ( N) T(1) : 1 個の CPU コア PC で処理した時間 T(N) : N 個の CPU コア PC で処理した時間 T ( N) T N 1 (1) : プログラム中で並列化可能な箇所の割合 時間 並列化不可能 並列化可能 並列度 319

スケーリング (scaling) いくつかの条件を固定したとき, 速度向上率が並列度に比例すること スケーラビリティ (scalability) スケーリングの度合い ストロング ( 強い ) スケーリング (strong scaling) 問題の大きさを固定したときのスケーラビリティ ウィーク ( 弱い ) スケーリング (weak scaling) 各 CPU, コア,PC の負荷を固定したときのスケーラビリティ 問題の大きさは並列度に比例して大規模化 320

ストロング ( 強い ) スケーリング 問題の大きさを固定して並列度を増加 並列度の増加に伴って一つの CPU, コア,PC の負荷が減少 並列度 0 並列度 8 並列度 64 321

ウィーク ( 弱い ) スケーリング 各 CPU, コア,PC の負荷を固定したときのスケーラビリティ 並列度の増加に伴って問題が大規模化 並列度 0 並列度 8 322

付録

OpenMP による総和計算の並列化 計算順序に依存性はないが, 出力結果に依存性がある a[i] + + + + + + sum 324

逐次 ( 並列化前 ) プログラム #include<stdio.h> #include<stdlib.h> #define N 100 #define Nbytes (N*sizeof(float)) int main(){ float *a,sum=0.0f; int i; a = (float *)malloc(nbytes); for(i=0; i<n; i++) a[i] = (float)(i+1); } for(i=0; i<n; i++) sum += a[i]; printf("%f n",sum); return 0; sum_serial.c 325

並列化プログラム ( スレッド並列 ) #include<stdio.h> #include<stdlib.h> #include<omp.h> #define N 100 #define Nbytes (N*sizeof(float)) int main(){ float *a, sum=0.0f; int i; a = (float *)malloc(nbytes); #pragma omp parallel for for(i=0; i<n; i++) a[i] = (float)(i+1); } printf("%f n",sum); return 0; #pragma omp parallel for num_threads(4) reduction(+:sum) for(i=0; i<n; i++) sum += a[i]; //num_threads() でスレッド数を設定 //reduction(+:sum) で sum に値の合計を集約 sum.cpp 326

データ競合 reduction() を付けないとどうなるか 実行結果が毎回変わる データ競合 ( データレース ) が発生 sum の値 (0) を参照 sum スレッド 1 a[i] 1 2 3 4 5 6 0 sum の値 (0) を参照 スレッド 2 a[i] 51 52 53 54 55 56 327

データ競合 reduction() を付けないとどうなるか 実行結果が毎回変わる データ競合 ( データレース ) が発生 スレッド 1 a[i] sum 1 2 3 4 5 6 51 0+51 を sum に書き込み スレッド 2 a[i] 51 52 53 54 55 56 328

データ競合 reduction() を付けないとどうなるか 実行結果が毎回変わる データ競合 ( データレース ) が発生 0+1 を sum に書き込み sum スレッド 1 a[i] 1 2 3 4 5 6 1 スレッド 2 a[i] 51 52 53 54 55 56 329

MPI による総和計算の並列化 計算順序に依存性はないが, 出力結果に依存性がある OpenMPの時は計算順序が問題 MPIの時はノード間通信が必要 a[i] + + + + + + sum 330

並列化プログラム ( プロセス並列 ) #include<stdio.h> #include<stdlib.h> #include<mpi.h> #define ROOT 0 //rank 0 のノードは特別扱い #define N 100 int main(int argc, char* argv[]){ float *a,sum; int i, nsize, rank, nproc,bytes; int src, dst,tag; float sum_rcv; MPI_Status stat; //MPI のライブラリを初期化して実行準備 MPI_Init(&argc, &argv); // 全ノード数を取得 MPI_Comm_size(MPI_COMM_WORLD, &nproc); // 各ノードに割り振られた固有の番号を取得 MPI_Comm_rank(MPI_COMM_WORLD, &rank); // 各ノードで処理するデータサイズを設定 nsize = N/nproc; if(rank==nproc 1) nsize+=n%nproc; // 各ノードでメモリを確保 bytes = sizeof(float)*nsize; a=(float *)malloc(bytes); // 値の設定 for(i=0;i<nsize;i++) a[i]=(float)(i+rank*n/nproc+1); MPI_Barrier(MPI_COMM_WORLD); sum_mpi.cpp 331

並列化プログラム ( プロセス並列 ) // 各ノードで配列の総和を求める sum=0.0; for(i=0;i<nsize;i++) sum += a[i]; // 全ノードの同期を取る MPI_Barrier(MPI_COMM_WORLD); // 各ノードの総和の値を rank0 に送る if(rank!= ROOT){ //rank0 以外のノードは rank0 に //sum の値を送信 dst=root; tag=0; MPI_Send(&sum, 1, MPI_FLOAT, dst, tag, MPI_COMM_WORLD); }else{ //rank0 はそれ以外の全ノードから // 送られてくる値を受信し, 総和を計算 } } for(src=root+1; src < nproc; src++){ tag=0; MPI_Recv(&sum_rcv, 1, MPI_FLOAT, src, tag, MPI_COMM_WORLD, &stat); sum +=sum_rcv; } if(rank == ROOT) printf("%f n",sum); free(a); MPI_Finalize();//MPI のライブラリを終了 return 0; sum_mpi.cpp 332

MPI ライブラリの内容 MPI_Send 指定したノードへメッセージを送信 送信したメッセージが正常に受信されるまで停止 ( 同期実行 ) MPI_Recv 指定したノードからメッセージを受信 送信された ( されてくるはずの ) メッセージを正常に受信するまで停止 ( 同期実行 ) 333

実行イメージ (1 から 100 までの総和 ) PC1(rank0) PC2(rank1) PC3(rank2) nsize=33 nsize=33 nsize=34 1 2 3 32 33 34 35 36 65 66 67 68 69 99 100 334 sum sum sum MPI_Send sum_rcv sum + MPI_Recv sum_rcv sum + MPI_Recv MPI_Send

デッドロック ノード間のデータ交換 処理の順序を間違えるとプログラムが停止 正常 デッドロック PC1(rank0) PC2(rank1) PC1(rank0) PC2(rank1) MPI_Send MPI_Recv MPI_Send MPI_Send MPI_Recv MPI_Send MPI_Recv MPI_Recv の順に実行 の順に実行 335

デッドロック ノード間のデータ交換 処理の順序を間違えるとプログラムが停止 PC1(rank0) 正常 PC2(rank1) PC1(rank0) デッドロック PC2(rank1) MPI_Send MPI_Recv MPI_Send MPI_Send MPI_Recv MPI_Send 相手が受信するまで停止し続け, プログラムが正常に動作しない MPI_Recv MPI_Recv の順に実行 の順に実行 336