21
OpenFOAMスレッド並列化のための基礎検討 富岡 稔*(株式会社フィックスターズ) 伊藤 優希(株式会社フィックスターズ) 丸石 崇史(株式会社フィックスターズ) 藤 尚生(株式会社フィックスターズ) © 2017 Fixstars Corporation, All rights reserved.

OpenFOAMスレッド並列化のための基礎検討 · invD[upperAddr[face]]*lower[face]*z[lowerAddr[face]];} face 0 1 2 lower 5 6 7 lowerAddr 0 0 2 upperAddr 2 3 3

Embed Size (px)

Citation preview

Page 1: OpenFOAMスレッド並列化のための基礎検討 · invD[upperAddr[face]]*lower[face]*z[lowerAddr[face]];} face 0 1 2 lower 5 6 7 lowerAddr 0 0 2 upperAddr 2 3 3

OpenFOAMスレッド並列化のための基礎検討

富岡稔*(株式会社フィックスターズ)伊藤優希(株式会社フィックスターズ)丸石崇史(株式会社フィックスターズ)𠮷藤尚生(株式会社フィックスターズ)

© 2017 Fixstars Corporation, All rights reserved.

Page 2: OpenFOAMスレッド並列化のための基礎検討 · invD[upperAddr[face]]*lower[face]*z[lowerAddr[face]];} face 0 1 2 lower 5 6 7 lowerAddr 0 0 2 upperAddr 2 3 3

概要

OpenFOAMのスレッド並列化を行ってIntel

Xeon PhiなどのメニーコアCPU上での高速化を目指す

今回はそのための基礎検討として、pimpleFoamなどで使用されるlduMatrixクラスの線形ソルバPCGのスレッド並列化を検討した

1

© 2017 Fixstars Corporation, All rights reserved.

Page 3: OpenFOAMスレッド並列化のための基礎検討 · invD[upperAddr[face]]*lower[face]*z[lowerAddr[face]];} face 0 1 2 lower 5 6 7 lowerAddr 0 0 2 upperAddr 2 3 3

OpenFOAMの並列計算

MPIによるプロセス並列のみ

メニーコアCPUで効率よく計算するにはスレッド並列も用いるべき

2

© 2017 Fixstars Corporation, All rights reserved.

Page 4: OpenFOAMスレッド並列化のための基礎検討 · invD[upperAddr[face]]*lower[face]*z[lowerAddr[face]];} face 0 1 2 lower 5 6 7 lowerAddr 0 0 2 upperAddr 2 3 3

なぜ今基礎検討なのか?

過去にはMPIとスレッド並列を組み合わせたHybrid並列を実装し、「京」コンピュータにて評価しているものが存在する[1]

→ MPIのみのものと同等の性能

同様にスレッド並列化を行っている例は複数存在しているがコードはOpenFOAMに取り込まれていない

ゼロベースで作ることで知見を得る それによって高速化したい

3

© 2017 Fixstars Corporation, All rights reserved.

(1) 内山学,ファムバンフック,千葉修一,井上義昭,浅見暁,OpenFOAMによる流体コードのHybrid並列化の評価,情報処理学会研究報告,Vol.2015-HPC-151,No.20,pp.1-6, (2015)

Page 5: OpenFOAMスレッド並列化のための基礎検討 · invD[upperAddr[face]]*lower[face]*z[lowerAddr[face]];} face 0 1 2 lower 5 6 7 lowerAddr 0 0 2 upperAddr 2 3 3

概要

OpenFOAMのスレッド並列化を行ってIntel

Xeon PhiなどのメニーコアCPU上での高速化を目指す

今回はそのための基礎検討として、pimpleFoamなどで使用されるlduMatrixクラスの線形ソルバPCGのスレッド並列化を検討した

4

© 2017 Fixstars Corporation, All rights reserved.

Page 6: OpenFOAMスレッド並列化のための基礎検討 · invD[upperAddr[face]]*lower[face]*z[lowerAddr[face]];} face 0 1 2 lower 5 6 7 lowerAddr 0 0 2 upperAddr 2 3 3

前処理付き共役勾配法(PCG)

線形方程式を解く反復法の一種

反復内の主な処理

➢前処理 (𝑀−1𝒓)

➢内積 (𝒓1 ∙ 𝒓2)

➢ベクトル和 (𝒓1 + 𝒓2)

➢ベクトルのスカラー倍 (𝛼𝒓)

➢疎行列ベクトル積 (𝐴𝒓)

5

© 2017 Fixstars Corporation, All rights reserved.

Page 7: OpenFOAMスレッド並列化のための基礎検討 · invD[upperAddr[face]]*lower[face]*z[lowerAddr[face]];} face 0 1 2 lower 5 6 7 lowerAddr 0 0 2 upperAddr 2 3 3

PCGのボトルネック

前処理を対角ベース不完全コレスキー分解(DIC)

の場合の実行時間を計測

計測にはオープンCAE学会がベンチマークとして作成したチャネル流問題[2]を使用

ボトルネックはDIC前処理と疎行列ベクトル積

どちらも行列演算でlduMatrixクラスを使用

→ 並列性はlduMatrixクラスに依存

6

© 2017 Fixstars Corporation, All rights reserved.

(2) OpenFOAM Benchmark Test for Channel Flow (Re_tau=110),

https://github.com/opencae/OpenFOAM-BenchmarkTest/tree/master/channelReTau110, (accessed 2017-11-17)

Page 8: OpenFOAMスレッド並列化のための基礎検討 · invD[upperAddr[face]]*lower[face]*z[lowerAddr[face]];} face 0 1 2 lower 5 6 7 lowerAddr 0 0 2 upperAddr 2 3 3

lduMatrixクラスの疎行列格納形式

lduMatrixクラスは疎行列を対角部分D, 上三角部分U, 下三角部分Lに分けてそれぞれの非ゼロ要素を保持

Uは行優先、Lは列優先で格納

非ゼロ要素に対応する行と列の情報も保持

→ COO形式と等価

7

© 2017 Fixstars Corporation, All rights reserved.

𝑈

𝐿

𝐷

Page 9: OpenFOAMスレッド並列化のための基礎検討 · invD[upperAddr[face]]*lower[face]*z[lowerAddr[face]];} face 0 1 2 lower 5 6 7 lowerAddr 0 0 2 upperAddr 2 3 3

lduMatrixクラス(具体例)8

© 2017 Fixstars Corporation, All rights reserved.

1 5 62

8 3 79 10 4

diag = 1, 2, 3, 4upper = 5, 6 7lower = 8, 9, 10lowerAddr = 0, 0, 2upperAddr = 2, 3, 3

𝑈

𝐿

𝐷

対角部分の値上三角部分の値下三角部分の値上三角部分の行番号・下三角部分の列番号上三角部分の列番号・下三角部分の行番号

Page 10: OpenFOAMスレッド並列化のための基礎検討 · invD[upperAddr[face]]*lower[face]*z[lowerAddr[face]];} face 0 1 2 lower 5 6 7 lowerAddr 0 0 2 upperAddr 2 3 3

lduMatrixクラスの問題点

下三角部分Lを列優先で保持している

→ 非ゼロ要素の行番号が連続していない

疎行列ベクトル積やDIC前処理をスレッド並列化するとアクセス競合が発生する

lduMatrixクラスを用いている部分は

スレッド並列化が困難

9

© 2017 Fixstars Corporation, All rights reserved.

Page 11: OpenFOAMスレッド並列化のための基礎検討 · invD[upperAddr[face]]*lower[face]*z[lowerAddr[face]];} face 0 1 2 lower 5 6 7 lowerAddr 0 0 2 upperAddr 2 3 3

疎行列ベクトル積(lduMatrix)

𝒚 = 𝐴𝒙⇔各非ゼロ要素𝑎𝑖𝑗に対して 𝑦𝑖 += 𝑎𝑖𝑗 𝑥𝑗 を計算

10

© 2017 Fixstars Corporation, All rights reserved.

const label nCells = diag().size();for (label cell = 0; cell < nCells; cell++) {

A[cell] = diag[cell]*x[cell];}

const label nFaces = upper().size();for (label face = 0; face < nFaces; face++) {

A[upperAddr[face]] += lower[face]*x[lowerAddr[face]];A[lowerAddr[face]] += upper[face]*x[upperAddr[face]];

}

Page 12: OpenFOAMスレッド並列化のための基礎検討 · invD[upperAddr[face]]*lower[face]*z[lowerAddr[face]];} face 0 1 2 lower 5 6 7 lowerAddr 0 0 2 upperAddr 2 3 3

具体例

異なるループ変数で同じ場所を書き換える

→ 並列化すると同時書き込みが発生

11

© 2017 Fixstars Corporation, All rights reserved.

1 5 62

8 3 79 10 4

const label nFaces = upper().size();for (label face = 0; face < nFaces; face++) {

A[upperAddr[face]] += lower[face]*x[lowerAddr[face]];A[lowerAddr[face]] += upper[face]*x[upperAddr[face]];

}

face 0 1 2

upper 5 6 7

lower 8 9 10

lowerAddr 0 0 2

upperAddr 2 3 3

Page 13: OpenFOAMスレッド並列化のための基礎検討 · invD[upperAddr[face]]*lower[face]*z[lowerAddr[face]];} face 0 1 2 lower 5 6 7 lowerAddr 0 0 2 upperAddr 2 3 3

DIC前処理(lduMatrix)

前処理は 𝒛 = 𝑀−1𝒓= 𝐼 + 𝐷∗−1𝑈 −1 𝐼 + 𝐷∗−1𝑈𝑇 −1𝐷∗−1𝒓で計算

→ 前進代入・後退代入

12

© 2017 Fixstars Corporation, All rights reserved.

←前進代入

←後退代入

for (label cell = 0; cell < nCells; cell++) { z[cell] = invD [cell]*r[cell];

}

for (label face=0; face < nFaces; face++) { z[upperAddr[face]] -=

invD[upperAddr[face]]*lower[face]*z[lowerAddr[face]];}

for (label face = nFaces-1; face >= 0; face--) {z[lowerAddr[face]] -=

invD[lowerAddr[face]]*upper[face]*z[upperAddr[face]];}

Page 14: OpenFOAMスレッド並列化のための基礎検討 · invD[upperAddr[face]]*lower[face]*z[lowerAddr[face]];} face 0 1 2 lower 5 6 7 lowerAddr 0 0 2 upperAddr 2 3 3

具体例

ループ内の異なるfaceで同じ場所を書き換える

→ 並列化すると同時書き込みが発生

13

© 2017 Fixstars Corporation, All rights reserved.

1 5 62

5 3 76 7 4

for (label face = 0; face < nFaces; face++) { z[upperAddr[face]] -=

invD[upperAddr[face]]*lower[face]*z[lowerAddr[face]];}

face 0 1 2

lower 5 6 7

lowerAddr 0 0 2

upperAddr 2 3 3

Page 15: OpenFOAMスレッド並列化のための基礎検討 · invD[upperAddr[face]]*lower[face]*z[lowerAddr[face]];} face 0 1 2 lower 5 6 7 lowerAddr 0 0 2 upperAddr 2 3 3

対策

lduMatrixクラスのままではスレッド並列化が困難

→ 別の形式に変換

今回はCSR形式で考える

14

© 2017 Fixstars Corporation, All rights reserved.

Page 16: OpenFOAMスレッド並列化のための基礎検討 · invD[upperAddr[face]]*lower[face]*z[lowerAddr[face]];} face 0 1 2 lower 5 6 7 lowerAddr 0 0 2 upperAddr 2 3 3

CSR形式

data[k]: k番目の非ゼロ要素の値

column[k]: k番目の非ゼロ要素の列番号

offset[i]: i行目のdataとcolumnの開始位置

15

© 2017 Fixstars Corporation, All rights reserved.

1 5 62

8 3 79 10 4

data = [1, 5, 6, 2, 8, 3, 7, 9, 10, 4] column = [0, 2, 3, 1, 0, 2, 3, 0, 2, 3]offset = [0, 3, 4, 7, 10]

Page 17: OpenFOAMスレッド並列化のための基礎検討 · invD[upperAddr[face]]*lower[face]*z[lowerAddr[face]];} face 0 1 2 lower 5 6 7 lowerAddr 0 0 2 upperAddr 2 3 3

疎行列ベクトル積(CSR形式)

𝒚 = 𝐴𝒙⇔各非ゼロ要素𝑎𝑖𝑗に対して 𝑦𝑖 += 𝑎𝑖𝑗 𝑥𝑗 を計算

それぞれ違う場所を書き換える

→ 並列化が可能

16

© 2017 Fixstars Corporation, All rights reserved.

for (label i = 0; i < n; i++) {double work = 0.0;for (label index = offset[i]; index < offset[i + 1]; index++) {

work += data[index] * x[column[index]];}y[i] = work;

}

Page 18: OpenFOAMスレッド並列化のための基礎検討 · invD[upperAddr[face]]*lower[face]*z[lowerAddr[face]];} face 0 1 2 lower 5 6 7 lowerAddr 0 0 2 upperAddr 2 3 3

DIC前処理(CSR形式)

前処理は 𝒛 = 𝑀−1𝒓= 𝐼 + 𝐷∗−1𝑈 −1 𝐼 + 𝐷∗−1𝑈𝑇 −1𝐷∗−1𝒓で計算

→ 前進代入・後退代入

17

© 2017 Fixstars Corporation, All rights reserved.

for (label i = 0; i < n; i++) {z[i] = invD[i]*r[i];

}

for (label i = 0; i < n; i++) {double work = z[i];for (label index = offset[i]; index < offset[i+1]; index++) {

const auto j = column[index];if (j < i) {

work -= invD[i] * data[index] * z[j];}

}z[i] = work;

}

Page 19: OpenFOAMスレッド並列化のための基礎検討 · invD[upperAddr[face]]*lower[face]*z[lowerAddr[face]];} face 0 1 2 lower 5 6 7 lowerAddr 0 0 2 upperAddr 2 3 3

まだ並列化できない

データ依存性によりCSR形式でも単純にはスレッド並列化できない

→ Cuthill-Mckee法・Multicolor法

18

© 2017 Fixstars Corporation, All rights reserved.

for (label i=0; i<n; i++) {double work = z[i];for (label index = offset[i]; index < offset[i+1]; index++) {

const auto j = column[index];if (j < i) {

work -= invD[i] * data[index] * z[j];}

}z[i] = work;

}

Page 20: OpenFOAMスレッド並列化のための基礎検討 · invD[upperAddr[face]]*lower[face]*z[lowerAddr[face]];} face 0 1 2 lower 5 6 7 lowerAddr 0 0 2 upperAddr 2 3 3

まとめ

OpenFOAMのPCGのスレッド並列化のための基礎検討を行った

lduMatrixクラスの行列格納形式が原因でそのままでは並列化が困難である

CSRに変換することでPCGのスレッド並列化の可能性を示唆した

19

© 2017 Fixstars Corporation, All rights reserved.

Page 21: OpenFOAMスレッド並列化のための基礎検討 · invD[upperAddr[face]]*lower[face]*z[lowerAddr[face]];} face 0 1 2 lower 5 6 7 lowerAddr 0 0 2 upperAddr 2 3 3

今後の展望

DIC-PCGのスレッド並列を実装

メニーコアCPUの環境でスレッド並列化したDIC-PCGの実行時間を計測

フラットMPIによる並列計算と比較・評価し、コード公開

今回検討した部分以外もスレッド並列化を進める➢DIC以外の前処理

➢PCG以外の線形ソルバ

➢ lduMatrixクラス以外の処理

最終的にはOpenFOAM全体のスレッド並列化

20

© 2017 Fixstars Corporation, All rights reserved.