偏微分方程式の差分計算 長岡技術科学大学電気電子情報工学専攻出川智啓

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

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

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

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

OpenFOAM(R) ソースコード入門 pt1 熱伝導方程式の解法から有限体積法の実装について考える 前編 : 有限体積法の基礎確認 2013/11/17 オープンCAE 富山富山県立大学中川慎二

パソコンシミュレータの現状

Microsoft Word - NumericalComputation.docx

計算機シミュレーション

2014 年 10 月 2 日 本日の講義及び演習 数値シミュレーション 2014 年度第 2 回 偏微分方程式の偏微分項をコンピュータで扱えるようにする 離散化 ( 差分化 ) テイラー展開の利用 1 階微分項に対する差分式 2 階微分項に対する差分式 1 次元熱伝導方程式に適用して差分式を導出

0 21 カラー反射率 slope aspect 図 2.9: 復元結果例 2.4 画像生成技術としての計算フォトグラフィ 3 次元情報を復元することにより, 画像生成 ( レンダリング ) に応用することが可能である. 近年, コンピュータにより, カメラで直接得られない画像を生成する技術分野が生

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

Slide 1

今後の予定 6/29 パターン形成第 11 回 7/6 データ解析第 12 回 7/13 群れ行動 ( 久保先生 ) 第 13 回 7/17 ( 金 ) 休講 7/20 まとめ第 14 回 7/27 休講?

FEM原理講座 (サンプルテキスト)

Microsoft PowerPoint - OS07.pptx

差分スキーム 物理 化学 生物現象には微分方程式でモデル化される例が多い モデルを使って現実の現象をコンピュータ上で再現することをシミュレーション ( 数値シミュレーション コンピュータシミュレーション ) と呼ぶ そのためには 微分方程式をコンピュータ上で計算できる数値スキームで近似することが必要

微分方程式 モデリングとシミュレーション

CUDA を用いた画像処理 画像処理を CUDA で並列化 基本的な並列化の考え方 目標 : 妥当な Naïve コードが書ける 最適化の初歩がわかる ブロックサイズ メモリアクセスパターン

数値計算で学ぶ物理学 4 放物運動と惑星運動 地上のように下向きに重力がはたらいているような場においては 物体を投げると放物運動をする 一方 中心星のまわりの重力場中では 惑星は 円 だ円 放物線または双曲線を描きながら運動する ここでは 放物運動と惑星運動を 運動方程式を導出したうえで 数値シミュ

スライド 1

微分方程式による現象記述と解きかた

4 月 東京都立蔵前工業高等学校平成 30 年度教科 ( 工業 ) 科目 ( プログラミング技術 ) 年間授業計画 教科 :( 工業 ) 科目 :( プログラミング技術 ) 単位数 : 2 単位 対象学年組 :( 第 3 学年電気科 ) 教科担当者 :( 高橋寛 三枝明夫 ) 使用教科書 :( プロ

偏微分方程式、連立1次方程式、乱数

Microsoft PowerPoint - 夏の学校(CFD).pptx

PowerPoint Presentation

3 数値解の特性 3.1 CFL 条件 を 前の章では 波動方程式 f x= x0 = f x= x0 t f c x f =0 [1] c f 0 x= x 0 x 0 f x= x0 x 2 x 2 t [2] のように差分化して数値解を求めた ここでは このようにして得られた数値解の性質を 考

Chap2.key

モデリングとは

vecrot

슬라이드 1

Microsoft PowerPoint - シミュレーション工学-2010-第1回.ppt

1/12 平成 29 年 3 月 24 日午後 1 時 1 分第 3 章測地線 第 3 章測地線 Ⅰ. 変分法と運動方程式最小作用の原理に基づくラグランジュの方法により 重力場中の粒子の運動方程式が求められる これは 力が未知の時に有効な方法であり 今のような 一般相対性理論における力を求めるのに使

シミュレーション物理4

数学 Ⅲ 微分法の応用 大学入試問題 ( 教科書程度 ) 1 問 1 (1) 次の各問に答えよ (ⅰ) 極限 を求めよ 年会津大学 ( 前期 ) (ⅱ) 極限値 を求めよ 年愛媛大学 ( 前期 ) (ⅲ) 無限等比級数 が収束するような実数 の範囲と そのときの和を求めよ 年広島市立大学 ( 前期

Laplace2.rtf

enshu5_6.key

スライド 1

板バネの元は固定にします x[0] は常に0です : > x[0]:=t->0; (1.2) 初期値の設定をします 以降 for 文処理のため 空集合を生成しておきます : > init:={}: 30 番目 ( 端 ) 以外については 初期高さおよび初速は全て 0 にします 初期高さを x[j]

2018年度 2次数学セレクション(微分と積分)

線積分.indd

解析力学B - 第11回: 正準変換

Microsoft Word - 1B2011.doc

相対性理論入門 1 Lorentz 変換 光がどのような座標系に対しても同一の速さ c で進むことから導かれる座標の一次変換である. (x, y, z, t ) の座標系が (x, y, z, t) の座標系に対して x 軸方向に w の速度で進んでいる場合, 座標系が一次変換で関係づけられるとする

DVIOUT-SS_Ma

耳桁の剛性の考慮分配係数の計算条件は 主桁本数 n 格子剛度 zです 通常の並列鋼桁橋では 主桁はすべて同じ断面を使います しかし 分配の効率を上げる場合 耳桁 ( 幅員端側の桁 ) の断面を大きくすることがあります 最近の桁橋では 上下線を別橋梁とすることがあり また 防音壁などの敷設が片側に有る

Microsoft PowerPoint - H22制御工学I-2回.ppt

Microsoft Word - 中村工大連携教材(最終 ).doc

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

Autodesk Inventor Skill Builders Autodesk Inventor 2010 構造解析の精度改良 メッシュリファインメントによる収束計算 予想作業時間:15 分 対象のバージョン:Inventor 2010 もしくはそれ以降のバージョン シミュレーションを設定する際

コンピュータグラフィックス第8回

Microsoft PowerPoint - mp11-02.pptx

Microsoft PowerPoint - Lec17 [互換モード]

Microsoft PowerPoint - H21生物計算化学2.ppt

最小二乗フィット、カイ二乗フィット、gnuplot

C言語による数値計算プログラミング演習

テンソル ( その ) テンソル ( その ) スカラー ( 階のテンソル ) スカラー ( 階のテンソル ) 階数 ベクトル ( 階のテンソル ) ベクトル ( 階のテンソル ) 行列表現 シンボリック表現 [ ]

PowerPoint Presentation

ストリームを用いたコンカレントカーネルプログラミングと最適化 エヌビディアジャパン CUDAエンジニア森野慎也 GTC Japan 2014

第2回シミュレーションスクール - 第2日: 熱拡散方程式のプログラムをつくろう

Phys1_03.key

PowerPoint プレゼンテーション

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

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

平成 年 月 7 日 ( 土 第 75 回数学教育実践研究会アスティ 45 ビル F セミナールーム A 札幌医科大学 年 P ab, を正の定数とする 平面上において ( a, を中心とする円 Q 4 C と (, b を中心とする円 C が 原点 O で外接している また P を円 C 上の点と

応用数学Ⅱ 偏微分方程式(2) 波動方程式(12/13)

数 IB( 植松 ) 2006 年夏学期解答 ( 兼ノート ) (2007 年のは課題プリでやってしまったので ) 1 (a) 補完公式を使う問題です 補完公式とは n+1 個の点を通る n 次の多項式を求める公式のことです 例 n=3 x y y0 y1 y2 y3 このデータを補

2014計算機実験1_1

Microsoft PowerPoint - CSA_B3_EX2.pptx

2008 年度下期未踏 IT 人材発掘 育成事業採択案件評価書 1. 担当 PM 田中二郎 PM ( 筑波大学大学院システム情報工学研究科教授 ) 2. 採択者氏名チーフクリエータ : 矢口裕明 ( 東京大学大学院情報理工学系研究科創造情報学専攻博士課程三年次学生 ) コクリエータ : なし 3.

データ解析

Microsoft PowerPoint - NA03-09black.ppt

GPU 画像 動画処理用ハードウェア 低性能なプロセッサがたくさん詰まっている ピーク性能が非常に高い GPUを数値計算に用いるのがGPGPU Graphics Processing Unit General Purpose GPU TSUBAME2.0: GPUスパコン 本演習ではNVIDIA社の

PowerPoint プレゼンテーション

ボルツマンマシンの高速化

2016年度 京都大・文系数学

cp-7. 配列

行列、ベクトル

合金の凝固

以下 変数の上のドットは時間に関する微分を表わしている (ex. 2 dx d x x, x 2 dt dt ) 付録 E 非線形微分方程式の平衡点の安定性解析 E-1) 非線形方程式の線形近似特に言及してこなかったが これまでは線形微分方程式 ( x や x, x などがすべて 1 次で なおかつ

Problem P5

Microsoft PowerPoint - H22制御工学I-10回.ppt

Microsoft PowerPoint - 測量学.ppt [互換モード]

Taro-数値計算の基礎Ⅱ(公開版)

計算機アーキテクチャ

memo

Microsoft PowerPoint - 第3回2.ppt

2018年度 神戸大・理系数学

Microsoft PowerPoint SIGAL.ppt

Microsoft PowerPoint - 発表II-3原稿r02.ppt [互換モード]

DVIOUT

熊本大学学術リポジトリ Kumamoto University Repositor Title GPGPU による高速演算について Author(s) 榎本, 昌一 Citation Issue date Type URL Presentation

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

ଗȨɍɫȮĘർǻ 図 : a)3 次元自由粒子の波数空間におけるエネルギー固有値の分布の様子 b) マクロなサイズの系 L ) における W E) と ΩE) の対応 として与えられる 周期境界条件を満たす波数 kn は kn = πn, L n = 0, ±, ±, 7) となる 長さ L の有限

2014年度 名古屋大・理系数学

(Microsoft PowerPoint - \221\34613\211\361)

<4D F736F F F696E74202D20906C8D488AC28BAB90DD8C7689F090CD8D488A D91E F1>

適応フィルタのSIMD最適化

スライド 1

2011年度 筑波大・理系数学

<4D F736F F D2097CD8A7793FC96E582BD82ED82DD8A E6318FCD2E646F63>

Transcription:

偏微分方程式の差分計算 長岡技術科学大学電気電子情報工学専攻出川智啓

今回の内容 差分法 階微分 階微分に対する差分法 次元拡散方程式 guplot による結果の表示 分岐の書き方による実行時間の変化 高速化に利用できるいくつかのテクニック 7

前回授業 ビットマップを使った画像処理 配列の 要素が物理的な配置に対応 配列の 要素に物理的なデータが定義 B G R 7

数値計算 ( 差分法 ) 計算機を利用して数学 物理学的問題の解を計算 微積分を計算機で扱える形に変換 差分法では微分を差分に置き換え 処理自体は単純 精度を上げるために計算量が増加 73

シミュレーションの歴史と進歩 このスライドは諸事情により空白です 74

数値計算 ( 差分法 ) 物理空間に観測点を設置 観測点での物理量の変化を計算 観測点群を配列として確保し その点で物理量を定義 75

偏微分方程式 ( 拡散方程式 ) 物質の拡散を表す方程式 水の中に落ちたインクの拡散 金属中の熱伝導等 時刻 t=0 における の分布 ( 初期値 ) が既知 時間進行に伴い がどのように変化するかを計算 時間積分しながら の分布を求める ) ( ) ( x t x t t x 76 ) ( ) ( ) ( y t y x x t y x t t y x

差分法 計算機で微分を計算する方法の一つ 微分の定義 x の関数 について x だけ離れた 点間の傾きを計算し 点の間隔を無限小に近づけたときの極限 差分近似 d dx lm 0 Δx 関数をある間隔でサンプリング ( x Δx) Δx ( x) その間隔 x が の変化に対して十分小さいと仮定 d ( x Δx) ( x) dx Δx 77

差分法 ( 理論的なお話 ) 差分の誤差 lm を排除したことでどの程度の誤差が入るのか d dx lm Δx0 ( x Δx) Δx ( x) ( x Δx) Δx ( x) 関数 のテイラー展開を利用 ( x 3 3 d Δx d Δx d Δx) ( x) Δx 3 dx! dx 3! dx d dx ( x Δx) Δx ( x) Δx Δx! d dx Δx 3! 3 d 3 dx 3 78

差分法 ( 理論的なお話 ) 空間打ち切り誤差 定義とテイラー展開の比較 d dx ( x Δx) ( x) ( x Δx) ( x) lm Δx 0 Δx Δx 誤差 d dx ( x Δx) Δx ( x) Δx Δx! d dx Δx 3! 3 d 3 dx 3 テイラー展開を有限項で打ち切ったことによる誤差 3 Δx d Δx d 3! dx 3! dx 79

階微分の離散化 テイラー展開を応用 x 方向に x 離れた 点で展開 ( x 3 3 Δx Δx Δx) ( x) Δx 3 x! x 3! x ( x 3 3 Δx Δx Δx) ( x) Δx 3 x! x 3! x 式を足すと 階微分が消滅 ( x Δx Δx) ( x Δx) ( x)! x 730

階微分の離散化 階微分の式に整理 x ( x Δx) ( x) Δx ( x Δx) (x) (x+x) (x) (x x) x x=0 x x x x+x x 73

階微分の離散化 階微分の式に整理 x ( x Δx) ( x) Δx ( x Δx) [] 階の中心差分 [+] ([+] *[]+[ ]) /(dx*dx) [ ] [] 73 dx =0 + サンプリングされた関数値を配列 [] で保持

階微分の離散化 サンプリングされた関数値 の保持 x 方向長さ ( 計算領域の長さ ) を等間隔 xに分割 間隔 xの両端に離散点 ( 観測点 ) を置き そこでの値を定義 原点から順に離散点に番号を付与し で表現 離散点 におけるの値を配列 [] に保存 [] 配列 ( メモリ ) 配列 [] 離散点 =0 + 733

差分法の実装 計算領域内部 ddx[]=([ ] *[]+[+])/dxdx; 境界条件 ( 関数値が無いため処理を変更 ) ddx[0 ]=(*[0 ] 5*[ ]+4*[ ] [3 ])/dxdx; ddx[n ]=(*[N ] 5*[N ]+4*[N 3] [N 4])/dxdx; [] + + + + + + Δx ddx[] 734

差分法の実装 計算領域内部 ddx[]=([ ] *[]+[+])/dxdx; 境界条件 ( 関数値が無いため処理を変更 ) ddx[0 ]=(*[0 ] 5*[ ]+4*[ ] [3 ])/dxdx; ddx[n ]=(*[N ] 5*[N ]+4*[N 3] [N 4])/dxdx; [] + Δx ddx[] 735

差分法の実装 計算領域内部 ddx[]=([ ] *[]+[+])/dxdx; 境界条件 ( 関数値が無いため処理を変更 ) ddx[0 ]=(*[0 ] 5*[ ]+4*[ ] [3 ])/dxdx; ddx[n ]=(*[N ] 5*[N ]+4*[N 3] [N 4])/dxdx; [] + Δx ddx[] 736

CPU プログラム #clude<stdlb.h> #clude<math.h>/* lmオプションが必要*/ #dee Lx (.0*M_PI) #dee Nx (56) #dee dx (Lx/(Nx )) #dee Nbytes (Nx*szeo(double)) #dee dxdx (dx*dx) vod t(double *){ t ; or(=0; <Nx; ++){ [] = s(*dx); vod deretate(double * double *ddx){ t ; ddx[0] = (.0*[0] 5.0*[] +4.0*[] [3])/dxdx; or(=; <Nx ; ++) ddx[] = ( [+].0*[ ] + [ ])/dxdx; ddx[nx ]=( [Nx 4] +4.0*[Nx 3] 5.0*[Nx ] +.0*[Nx ])/dxdx; t ma(vod){ double **ddx; = (double *)malloc(nbytes); ddx = (double *)malloc(nbytes); t(); deretate(ddx); retur 0; deretate.c 737

関数の離散化 計算領域の長さと離散点の数 離散点の間隔の関係 (x) L x x 0 x 0 から L x の間に設けられた点の数 N x =L x /x + 738

実行結果 d/dx 739 x

GPU への移植 計算領域内部を計算するスレッド ddx[]=([ ] *[]+[+])/dxdx; 境界を計算するスレッド ddx[0 ]=(*[0 ] 5*[ ]+4*[ ] [3 ])/dxdx; ddx[n ]=(*[N ] 5*[N ]+4*[N 3] [N 4])/dxdx; [] + + + + + + + + Δx ddx[] 740

GPU プログラム #clude<stdo.h> #clude<stdlb.h> #clude<math.h>/* lmオプションが必要*/ #dee Lx (.0*M_PI) #dee Nx (56) #dee dx (Lx/(Nx )) #dee Nbytes (Nx*szeo(double)) #dee dxdx (dx*dx) #dee NT (8) #dee NB (Nx/NT) vod t(double *){ t ; or(=0; <Nx; ++){ [] = s(*dx); global vod deretate (double * double *ddx){ t = blockidx.x*blockdm.x + threadidx.x; (==0) ddx[] = (.0*[ ] 5.0*[+] +4.0*[+] [+3])/dxdx; (0< && <Nx ) ddx[] = ( [+].0*[ ] + [ ])/dxdx; (==Nx ) ddx[]=( [ 3] +4.0*[ ] 5.0*[ ] +.0*[ ])/dxdx; deretate.cu 74

GPU プログラム t ma(vod){ double *host_*host_ddx; double **ddx; host_ =(double *)malloc(nbytes); cudamalloc((vod **)&Nbytes); cudamalloc((vod **)&ddxnbytes); t(host_); cudamemcpy( host_ Nbytes cudamemcpyhosttodevce); deretate<<<nb NT>>>( ddx); //host_ddx=(double *)malloc(nbytes); //cudamemcpy(host_ddx ddx Nbytes cudamemcpydevcetohost); //or(t =0; <Nx; ++)prt("%%% "*dxhost_[]host_ddx[]); ree(host_); ree(host_ddx); cudafree(); cudafree(ddx); retur 0; deretate.cu 74

次元への拡張 743 拡散方程式 次元 次元 ) ( ) ( x t x t t x ) ( ) ( ) ( y t y x x t y x t t y x deretate.cu で計算どのように 次元に拡張するかどのように離散化するか

次元への拡張 x 方向 階偏微分 y 方向を固定して x 方向に偏微分 y 方向 階偏微分 x 方向を固定して y 方向に偏微分 ) ( ) ( ) ( Δx y Δx x y x y Δx x x ) ( ) ( ) ( Δy Δy y x y x Δy y x y 744

時間積分 時間微分項の離散化 時間微分項を前進差分で離散化 ( x y t Δt) ( x y t) t Δt 右辺のt+tの項を移行 ( x y t Δt) ( x y t) Δt t t 拡散方程式を代入 ( x y t Δt) ( x y t) Δt ( x y t) (x y t) の 階微分を計算できれば (x y t+t) が求められる 745

離散化された方程式の記述 簡略化した表現 配列との対応をとるため下付き添字 を利用 ( x y) ( x Δx y) ( x y Δy) 時間は 上付き添字 を利用 ( x y t) ( x y t Δt) 746

離散化された拡散方程式 連続系 離散系 t 秒後の値 ) ( ) ( ) ( y t y x x t y x t t y x Δy Δx Δt Δy Δx Δt 747

離散化された関数値の保持 各方向を等間隔 x yに分割し 離散点を配置 離散点で関数値を定義し 配列に保存 配列 [][] =0 + =0 + 離散点 配列 ( メモリ ) 748

拡散方程式 ( 熱伝導方程式 ) x y + + x y x y x y t t+t 749 Δy Δx Δt + +

拡散方程式の安定性 プログラムを正しく作成しても正常な計算結果が得られない場合がある 安定条件 拡散の強さを表す係数 ( 拡散係数 ) を使った形 Δt 二つの条件を満たすことが必要条件 ( 結果が正しいかは別 ) Δt 0.5 Δt v v 5 Δx Δy 0. Δx Δy 750

計算手順. 計算条件の決定 計算領域の大きさ L x L y 計算領域の分割数 ( 離散点の個数 )N x N y 離散点同士の間隔 ( 格子間隔 )x y 計算時間間隔 t. 初期値の決定 の初期分布の決定 3. 差分値の計算 の分布からx y 方向の 階微分値を計算 境界条件に基づいて境界の値を決定 t 秒後のを計算 75

CPU プログラム 計算条件の決定 計算領域の大きさ L x L y 計算領域の分割数 ( 離散点の個数 )N x N y 離散点同士の間隔 ( 格子間隔 )x y #clude<stdo.h> #clude<stdlb.h> #clude<math.h> #dee Lx (.0) #dee Ly (.0) #dee Nx 8 #dee Ny 8 #dee dx (Lx/(Nx )) #dee dy (Ly/(Ny )) #dee dt 0.000 計算時間間隔 t 75

CPU プログラム 初期条件 境界条件 753 0.) ( 0.) ( 0 r r x y r 0 : 外向き法線ベクトル Δx 0 0 Δy y x r

CPU プログラム #clude<stdlb.h> #clude<math.h> #dee Lx (.0) #dee Ly (.0) #dee Nx 8 #dee Ny 8 #dee dx (Lx/(Nx )) #dee dy (Ly/(Ny )) #dee dt 0.000 #dee edt (.0) #dee Nt (t)(edt/dt) #dee DIFF (0.0) #dee dxdx (dx*dx) #dee dydy (dy*dy) #dee Nbytes (Nx*Ny*szeo(double)) vod t(double * double * double *); vod laplaca(double * double *); vod tegrate(double * double * double *); vod update(double * double *); t ma(vod){ double **_ew*_lapxy; t ; = (double *)malloc(nx*ny*szeo(double)); _ew = (double *)malloc(nx*ny*szeo(double)); _lap = (double *)malloc(nx*ny*szeo(double)); t( _lap _ew); or(=0;<nt;++){ laplaca(_lap); tegrate(_lap_ew); update(_ew); retur 0; duso.c 754

CPU プログラム vod t(double * double *_lap double *_ew){ t ; double xy; or(=0;<ny;++){ or(=0;<nx;++){ [+Nx*] = 0.0; _lap[+nx*] = 0.0; _ew[+nx*] = 0.0; x=*dx Lx/.0; y=*dy Ly/.0; (sqrt(x*x+y*y)<=0.) [+Nx*] =.0; vod laplaca(double * double *_lap){ t pmpm; or(=0;<ny;++){ or(=0;<nx;++){ = +Nx*; m= +Nx* ; ( < 0 )m=++nx*; p=++nx* ; (+>=Nx)p= +Nx*; m= +Nx*( );( < 0 )m=+nx*(+); p= +Nx*(+);(+>=Ny)p=+Nx*( ); _lap[] = ([p].0*[]+[m])/dxdx +([p].0*[]+[m])/dydy; vod tegrate (double * double *_lap double *_ew){ t ; or(=0;<ny;++){ or(=0;<nx;++){ = +Nx*; _ew[] = [] + dt*diff*_lap[]; vod update(double * double *_ew){ t ; or(=0;<ny;++){ or(=0;<nx;++){ = +Nx*; [] = _ew[]; duso.c 755

CPU プログラム 差分計算 x 方向 y 方向偏微分を個別に計算して加算 vod laplaca(double * double *_lap){ t pmpm; or(=0;<ny;++){ or(=0;<nx;++){ = +Nx* ; m= +Nx* ; ( < 0 )m=++nx*; p=++nx* ; (+>=Nx)p= +Nx*; m= +Nx*( );( < 0 )m=+nx*(+); p= +Nx*(+);(+>=Ny)p=+Nx*( ); _lap[] = ([p].0*[]+[m])/dxdx +([p].0*[]+[m])/dydy; 756

ラプラシアン計算のメモリ参照 ある 点 のラプラシアンを計算するために 周囲 5 点の を参照 [] _lap[] + + 757

ラプラシアン計算のメモリ参照 ある 点 のラプラシアンを計算するために 周囲 5 点の を参照 [] _lap[] + + 758

ラプラシアン計算のメモリ参照 ある 点 のラプラシアンを計算するために 周囲 5 点の を参照 [] _lap[] + + 759

ラプラシアン計算のメモリ参照 ある 点 のラプラシアンを計算するために 周囲 5 点の を参照 [] _lap[] + + 760

ラプラシアン計算のメモリ参照 ある 点 のラプラシアンを計算するために 周囲 5 点の を参照 全ての を参照し 領域内部の _lap を計算 [] _lap[] 76

CPU プログラム 境界条件 法線方向の 階微分が 0 境界での 階の差分式 76 _lap[] 0 : 外向き法線ベクトル Δx 0 0 Δy or Δx Δx Δx or Δy Δy Δy

CPU プログラム 境界条件 参照する点が境界からはみ出している場合は添字を修正 階微分を計算する式は変更なし _lap[] ( < 0 )m=++nx*; (+>=Nx)p= +Nx*; ( < 0 )m= +Nx*(+); (+>=Ny)p= +Nx*( ); 右端では+を に修正 左端では を+に修正 上端では+を に修正 下端では を+に修正 763

CPU プログラム の積分 vod tegrate(double * double *_lap double *_ew){ t ; or(=0;<ny;++){ or(=0;<nx;++){ = +Nx*; _ew[] = [] + dt*diff*_lap[]; 764 Δy Δx Δt

CPU プログラム の更新 から + を計算 + から + を計算 同じアルゴリズム 今の時刻から次の時刻を求める 求められた次の時刻を今の時刻と見なし 次の時刻を求める vod update(double * double *_ew){ t ; or(=0;<ny;++){ or(=0;<nx;++){ = +Nx*; [] = _ew[]; 765

GPU プログラム (CPU 処理用共通部分 ) #clude<stdo.h> #clude<stdlb.h> #clude<math.h> #dee Lx (.0) #dee Ly (.0) #dee Nx 048 #dee Ny Nx #dee dx (Lx/(Nx )) #dee dy (Ly/(Ny )) #dee dt 0.00000 #dee edt (.0) #dee Nt (t)(edt/dt) #dee DIFF (0.0) #dee dxdx (dx*dx) #dee dydy (dy*dy) #dee Nbytes (Nx*Ny*szeo(double)) #clude "d.cu" //#clude "d.cu" t ma(vod){ t ; double *dev_*dev ew*dev lap; dm3 Thread Block; (DIFF*dt/dxdx > 0.5){ prt("cogurato error "); ext(); cudamalloc( (vod**)&dev_ Nbytes ); cudamalloc( (vod**)&dev ew Nbytes ); cudamalloc( (vod**)&dev lap Nbytes ); Thread = dm3(threadxthready); Block = dm3(blockx BLOCKY ); t<<<block Thread>>> (dev_ dev lap dev ew); or(=;<=nt;++){ laplaca<<<block Thread>>>(dev_dev lap); tegrate<<<block Thread>>> (dev_dev lapdev ew); update<<<block Thread>>>(dev_dev ew); retur 0; duso.cu 766

GPU プログラム ( スレッドが 点を計算 ) #dee THREADX 6 #dee THREADY 6 #dee BLOCKX (Nx/THREADX) #dee BLOCKY (Ny/THREADY) global vod laplaca(double * double *_lap){ t mpmp; = blockidx.x*blockdm.x + threadidx.x; = blockidx.y*blockdm.y + threadidx.y; = +Nx* ; m= +Nx* ; ( < 0 )m=++nx*; p=++nx* ; (+>=Nx)p= +Nx*; m= +Nx*( );( < 0 )m=+nx*(+); p= +Nx*(+);(+>=Ny)p=+Nx*( ); _lap[] = ([p].0*[]+[m])/dxdx +([p].0*[]+[m])/dydy; global vod tegrate (double * double *_lap double *_ew){ t ; = blockidx.x*blockdm.x + threadidx.x; = blockidx.y*blockdm.y + threadidx.y; = +Nx*; _ew[] = [] + dt*diff*_lap[]; global vod update(double * double *_ew){ t ; = blockidx.x*blockdm.x + threadidx.x; = blockidx.y*blockdm.y + threadidx.y; = +Nx*; [] = _ew[]; global vod t (double * double *_lap double *_ew){ t ; double xy; = blockidx.x*blockdm.x + threadidx.x; = blockidx.y*blockdm.y + threadidx.y; = +Nx*; [] = 0.0; _lap[] = 0.0; _ew[] = 0.0; x=*dx Lx/.0; y=*dy Ly/.0; (sqrt(x*x+y*y)<=0.) [] =.0; d.cu 767

guplot による結果の表示 次元 3 次元データをプロットするアプリケーション コマンドラインで命令を実行してグラフを描画 関数の描画 ファイルから読み込んだデータの表示が可能 tesla?? では正しく動作しないため grouse で実行すること 768

guplot による結果の表示 表示可能なファイルフォーマット データはスペース区切り 3 次元表示では列 ( または行 ) の区切りとして空白行が必要 0.500000 0.500000 0.000000e+00 0.4990 0.500000 0.000000e+00... 0.4990 0.500000 0.000000e+00 0.500000 0.500000 0.000000e+00 0.500000 0.4990 0.000000e+00 0.4990 0.4990 0.000000e+00... 0.4990 0.4990 0.000000e+00 0.500000 0.4990 0.000000e+00 0.500000 0.498045 0.000000e+00 0.4990 0.498045 0.000000e+00 < 改行 < 改行 769

guplot による結果の表示 スクリプトの実行 guplotのコマンドを記述したファイルを実行 load ' スクリプトファイル名 ' am.gpl 結果を単色の等値面で 3 次元表示 am_color.gpl 結果をカラーの等値面で 3 次元表示 am_d.gpl 結果をカラーの等高線で 次元表示 770

guplot による結果の表示 スクリプト am.gpl の内容 set xrage [ 0.5:0.5] x 軸の表示範囲を 0.5~0.5に固定 set yrage [ 0.5:0.5] y 軸の表示範囲を 0.5~0.5に固定 set zrage [0:] z 軸の表示範囲を0~に固定 set tcslevel 0 xy 平面とz 軸の最小値表示位置の差 set hdde3d 隠線消去をする set vew 4530 視点をx 方向 45 y 方向 30 に設定 set sze 0.75 グラフの縦横比を:0.75 uset cotour 次元等高線は表示しない set surace 3 次元で等値面を表示 uset pm3d カラー表示はしない 以下でファイルを読み込み 3 次元表示 splot '0.00.txt' usg ::3 wth le ttle "t=0.00s"... splot '.00.txt' usg ::3 wth le ttle "t=.00s" 77

guplot による結果の表示 スクリプト am.gpl による表示結果 77

guplot による結果の表示 スクリプト am_color.gpl の内容 set xrage [ 0.5:0.5] x 軸の表示範囲を 0.5~0.5に固定 set yrage [ 0.5:0.5] y 軸の表示範囲を 0.5~0.5に固定 set zrage [0:] z 軸の表示範囲を0~に固定 set tcslevel 0 xy 平面とz 軸の最小値表示位置の差 set hdde3d 隠線消去をする set vew 4530 視点をx 方向 45 y 方向 30 に設定 set sze 0.75 グラフの縦横比を:0.75 uset cotour 次元等高線は表示しない set surace 3 次元で等値面を表示 set pm3d カラー表示する set cbrage[0:] カラーバーの表示範囲を0~に固定 以下でファイルを読み込み 3 次元表示 splot '0.00.txt' usg ::3 wth le ttle "t=0.00s"... splot '.00.txt' usg ::3 wth le ttle "t=.00s" 773

guplot による結果の表示 スクリプト am_color.gpl による表示結果 774

guplot による結果の表示 スクリプト am_d.gpl の内容 set xrage [ 0.5:0.5] x 軸の表示範囲を 0.5~0.5に固定 set yrage [ 0.5:0.5] y 軸の表示範囲を 0.5~0.5に固定 set zrage [0:] z 軸の表示範囲を0~に固定 set vew 00 真上から見下ろす set sze グラフの縦横比を: set cotour 次元等高線を表示 uset surace 3 次元で等値面を表示しない uset pm3d カラー表示しない set ctrparam levels cremetal 00. 等高線を0からまで0. 刻みに設定以下でファイルを読み込み 3 次元表示 splot '0.00.txt' usg ::3 wth le ttle "t=0.00s"... splot '.00.txt' usg ::3 wth le ttle "t=.00s" 775

guplot による結果の表示 スクリプト am_d.gpl による表示結果 776

様々な境界条件の計算 共有メモリを利用してキャッシュを模擬 共有メモリに付加的な領域を追加 袖領域 [] _lap[] 777

様々な境界条件の計算 共有メモリを利用してキャッシュを模擬 共有メモリに付加的な領域を追加 [] _lap[] 778

様々な境界条件の計算 共有メモリを利用してキャッシュを模擬 共有メモリに付加的な領域を追加 s[][] [] _lap[] 779

付加的な領域 ( 袖領域 ) の取り扱い データがグローバルメモリに存在する場合は グローバルメモリから読み込み s[][] [] _lap[] 780

付加的な領域 ( 袖領域 ) の取り扱い グローバルメモリに無い場合は境界条件から決定 s[][] [] _lap[] 78

境界条件 78 階微分が 0 0 Δy y 0 Δx x u

境界条件 783 階微分が 0 0 Δx x 0 Δy y

境界条件 784 階微分を片側差分で計算 3 4 6 4 3 4 5 Δy y 3 4 5 Δx x 3 4 6 4

GPU プログラム ( ラプラシアン kerel) #dee THREADX 6 #dee THREADY 6 #dee BLOCKX (Nx/THREADX) #dee BLOCKY (Ny/THREADY) global vod laplaca(double * double *_lap){ t ; t txty; shared loat s[+threadx+][+thready+]; = blockidx.x*blockdm.x + threadidx.x; = blockidx.y*blockdm.y + threadidx.y; tx = threadidx.x + ; ty = threadidx.y + ; = +Nx*; s[tx][ty] = []; sycthreads(); (blockidx.x == 0 && threadidx.x == 0) s[tx ][ty] = s[tx+][ty]; (blockidx.x!= 0 && threadidx.x == 0) s[tx ][ty] = [ +Nx*]; (blockidx.x == grddm.x && threadidx.x == blockdm.x ) s[tx+][ty] = s[tx ][ty]; (blockidx.x!= grddm.x && threadidx.x == blockdm.x ) s[tx+][ty] = [++Nx*]; (blockidx.y == 0 && threadidx.y == 0) s[tx][ty ] = s[tx][ty+]; (blockidx.y!= 0 && threadidx.y == 0) s[tx][ty ] = [+Nx*( )]; (blockidx.y == grddm.y && threadidx.y == blockdm.y ) s[tx][ty+] = s[tx][ty ]; (blockidx.y!= grddm.y && threadidx.y == blockdm.y ) s[tx][ty+] = [+Nx*(+)]; sycthreads(); _lap[] = (s[tx ][ty ].0*s[tx][ty]+s[tx+][ty ])/dxdx +(s[tx ][ty ].0*s[tx][ty]+s[tx ][ty+])/dydy; d.cu 785

GPU プログラム ( ラプラシアン kerel) shared loat s[+threadx+][+thready+]; = blockidx.x*blockdm.x + threadidx.x; = blockidx.y*blockdm.y + threadidx.y; tx = threadidx.x; ty = threadidx.y; [] = +Ny*; s[tx][ty] = []; sycthreads(); ブロック内のスレッド数 + 袖領域分の共有メモリを確保袖領域があるために添字の対応が変化 添字の対応を考えないと 必要なデータを袖領域に置いてしまう sycthreads() を呼んでスレッドを同期 共有メモリにデータが正しく書き込まれた事を保証 s[][] 786

GPU プログラム ( ラプラシアン kerel) shared loat s[+threadx+][+thready+]; = blockidx.x*blockdm.x + threadidx.x; = blockidx.y*blockdm.y + threadidx.y; tx = threadidx.x + ; ty = threadidx.y; [] = +Ny*; s[tx][ty] = []; sycthreads(); ブロック内のスレッド数 + 袖領域分の共有メモリを確保袖領域があるために添字の対応が変化 添字の対応を考えないと 必要なデータを袖領域に置いてしまう sycthreads() を呼んでスレッドを同期 787 共有メモリにデータが正しく書き込まれた事を保証 s[][] +

GPU プログラム ( ラプラシアン kerel) shared loat s[+threadx+][+thready+]; = blockidx.x*blockdm.x + threadidx.x; = blockidx.y*blockdm.y + threadidx.y; tx = threadidx.x + ; ty = threadidx.y + ; [] = +Ny*; s[tx][ty] = []; sycthreads(); ブロック内のスレッド数 + 袖領域分の共有メモリを確保袖領域があるために添字の対応が変化 添字の対応を考えないと 必要なデータを袖領域に置いてしまう sycthreads() を呼んでスレッドを同期 788 共有メモリにデータが正しく書き込まれた事を保証 s[][] + +

GPU プログラム ( ラプラシアン kerel) 袖領域の設定 (blockidx.x == 0 && threadidx.x == 0 ) s[tx ][ty] = s[tx+][ty]; (blockidx.x!= 0 && threadidx.x == 0 ) s[tx ][ty] = [ +Nx*]; (blockidx.x == grddm.x && threadidx.x == blockdm.x ) s[tx+][ty] = s[tx ][ty]; (blockidx.x!= grddm.x && threadidx.x == blockdm.x ) s[tx+][ty] = [++Nx*]; (blockidx.y == 0 && threadidx.y == 0 ) s[tx][ty ] = s[tx][ty+]; (blockidx.y!= 0 && threadidx.y == 0 ) s[tx][ty ] = [+Nx*( )]; (blockidx.y == grddm.y && threadidx.y == blockdm.y ) s[tx][ty+] = s[tx][ty ]; (blockidx.y!= grddm.y && threadidx.y == blockdm.y ) s[tx][ty+] = [+Nx*(+)]; sycthreads(); グローバルメモリにデータがある箇所はグローバルメモリから読み込みグローバルメモリにデータがない箇所は 階微分が0になるように袖領域の値を決定 ブロックが境界に接しているか否かで処理を切替 789

GPU プログラム ( ラプラシアン kerel) _lap[] = (s[tx ][ty ].0*s[tx][ty]+s[tx+][ty ])/dxdx +(s[tx ][ty ].0*s[tx][ty]+s[tx ][ty+])/dydy; 共有メモリのデータを利用してラプラシアンを計算 分岐を排除 _lap[] s[][] 790

GPU プログラムの評価 共有メモリを使用した d.cu d.cu( 共有メモリ不使用 ) と比較して遅い Ferm 世代以降の GPU はキャッシュを搭載 共有メモリを使っても速くならない 共有メモリへ明示的にデータを移動 余分な処理により負荷が増加 せっかくなので 文の書き方について評価 79

GPU プログラムの評価 分岐の書き方による実行速度の変化 ブロックとスレッドの条件を同時に記述 (blockidx.x == 0 && threadidx.x == 0 ) s[tx ][ty] = s[tx+][ty]; (blockidx.x!= 0 && threadidx.x == 0 ) s[tx ][ty] = [ +Nx*]; (blockidx.x == grddm.x && threadidx.x == blockdm.x ) s[tx+][ty] = s[tx ][ty]; (blockidx.x!= grddm.x && threadidx.x == blockdm.x ) s[tx+][ty] = [++Nx*]; (blockidx.y == 0 && threadidx.y == 0 ) s[tx][ty ] = s[tx][ty+]; (blockidx.y!= 0 && threadidx.y == 0 ) s[tx][ty ] = [+Nx*( )]; (blockidx.y == grddm.y && threadidx.y == blockdm.y ) s[tx][ty+] = s[tx][ty ]; (blockidx.y!= grddm.y && threadidx.y == blockdm.y ) s[tx][ty+] = [+Nx*(+)]; Warp 内のスレッドが分岐すると実行速度が著しく低下 GPU はブロック単位で分岐 Warp 単位で分岐しても実行速度の低下は抑えられる 上の書き方は最適ではない? ブロック単位の分岐とスレッド単位の分岐を同時に記述 79

GPU プログラムの評価 分岐の書き方による実行速度の変化 ブロックとスレッドの条件を分け を入れ子に (blockidx.x == 0 )(threadidx.x == 0 ) s[tx ][ty] = s[tx+][ty]; (blockidx.x!= 0 )(threadidx.x == 0 ) s[tx ][ty] = [ +Nx*]; (blockidx.x == grddm.x )(threadidx.x == blockdm.x ) s[tx+][ty] = s[tx ][ty]; (blockidx.x!= grddm.x )(threadidx.x == blockdm.x ) s[tx+][ty] = [++Nx*]; (blockidx.y == 0 )(threadidx.y == 0 ) s[tx][ty ] = s[tx][ty+]; (blockidx.y!= 0 )(threadidx.y == 0 ) s[tx][ty ] = [+Nx*( )]; (blockidx.y == grddm.y )(threadidx.y == blockdm.y ) s[tx][ty+] = s[tx][ty ]; (blockidx.y!= grddm.y )(threadidx.y == blockdm.y ) s[tx][ty+] = [+Nx*(+)]; ブロック単位で分岐した後 スレッド単位で分岐 ブロック単位での分岐による速度低下が抑えられそうな気がする ブロック単位の分岐を記述する 8 個の は 個一組 ( 同じ色の行 ) で排他的に分岐 blockidx.x==0 が成立すると blockidx!=0 は絶対に成立しない 793

GPU プログラムの評価 分岐の書き方による実行速度の変化 個一組の の片方を else に書き換え (blockidx.x == 0 ){(threadidx.x == 0 ) s[tx ][ty] = s[tx+][ty]; else {(threadidx.x == 0 ) s[tx ][ty] = [ +Nx*]; (blockidx.x == grddm.x ){(threadidx.x == blockdm.x ) s[tx+][ty] = s[tx ][ty]; else {(threadidx.x == blockdm.x ) s[tx+][ty] = [++Nx*]; (blockidx.y == 0 ){(threadidx.y == 0 ) s[tx][ty ] = s[tx][ty+]; else {(threadidx.y == 0 ) s[tx][ty ] = [+Nx*( )]; (blockidx.y == grddm.y ){(threadidx.y == blockdm.y ) s[tx][ty+] = s[tx][ty ]; else {(threadidx.y == blockdm.y ) s[tx][ty+] = [+Nx*(+)]; 個一組の における条件判断は 回限り 回 の条件判断を行うよりは速いような気がする 794

分岐の書き方の違いによる実行速度の変化 格子分割数 N x N y =048 048 ブロックあたりのスレッド数 6 6 文の書き方 ブロックとスレッドの条件を同時に記述ブロックとスレッドの条件を分け を入れ子に 個一組のの片方を elseに書き換えカーネル ( 共有メモリ不使用 ) 実行時間 [ms].9.49.33.00 795

その他の処理の高速化 laplaca カーネルと tegrate カーネルの融合 カーネルフュージョン (kerel uso) 異なる処理を行うカーネルをまとめることでデータを再利用 グローバルメモリへの書き込み 読み出しを回避 global vod tegrate(double * double *_ew){ t ; double _lap; // ある 点のラプラシアンを計算してレジスタに保存 = blockidx.x*blockdm.x + threadidx.x; = blockidx.y*blockdm.y + threadidx.y; = +Nx*; _lap =... _ew[] = [] + dt*diff*_lap; //[]=[]+... とすると 全ての点の _lap を計算する前に を更新する可能性がある 796

その他の処理の高速化 値の更新 _ewのデータをにコピーしているだけ cudamemcpyで代用可能 global vod update(double * double *_ew){ t ; = blockidx.x*blockdm.x + threadidx.x; = blockidx.y*blockdm.y + threadidx.y; = +Nx*; [] = _ew[]; 797

その他の処理の高速化 値の更新 _ewのデータをにコピーしているだけ cudamemcpyで代用可能 or(=;<=nt;++){ tegrate<<<block Thread>>>(dev_dev ew); //update<<<block Thread>>>(dev_dev ew); cudamemcpy(dev_ dev ew Nbytes cudamemcpydevcetodevce); retur 0; 798

その他の処理の高速化 値の更新 ダブルバッファリング ( 第 7 回授業参照 ) でコピーを回避することも可能 double *dev_[]; t =0;out= ; cudamalloc((vod **)&dev_[ ]Nbytes); cudamalloc((vod **)&dev_[out]nbytes); t<<<block Thread>>>(dev_[(=0)] dev_[out(=)]); or(=;<=nt;++){//= tegrate<<<block Thread>>>(dev_[(=0)]dev_[out(=)]); = out; out = ; //= out=0 799

その他の処理の高速化 値の更新 ダブルバッファリング ( 第 7 回授業参照 ) でコピーを回避することも可能 double *dev_[]; t =0;out= ; cudamalloc((vod **)&dev_[ ]Nbytes); cudamalloc((vod **)&dev_[out]nbytes); t<<<block Thread>>>(dev_[(=0)] dev_[out(=)]); or(=;<=nt;++){//= tegrate<<<block Thread>>>(dev_[(=)]dev_[out(=0)]); = out; out = ; //=0 out= 800

その他の処理の高速化 値の更新 ダブルバッファリング ( 第 7 回授業参照 ) でコピーを回避することも可能 tegrate<<<block Thread>>>(dev_[(=0)]dev_[out(=)]); dev_[0] 時刻 dev_[] 時刻 + 80

その他の処理の高速化 値の更新 ダブルバッファリング ( 第 7 回授業参照 ) でコピーを回避することも可能 tegrate<<<block Thread>>>(dev_[(=)]dev_[out(=0)]); dev_[0] 時刻 + dev_[] 時刻 80