CommonMP 利用におけるによる実行上利用における C#によるによる実行上の実行上の課題と課題と DLL の活用

東京建設コンサルタント

正会員

○渡辺明英

東京建設コンサルタント

曽田康秀

１．はじめにCommonMP は C#から要素モデル DLL を呼び出すため，要素モデルは C#がベースとなる．一般に，C#は C++よりも遅く，C++はプログラムによっては C や Fortran より遅いとされる．特に C#の 2 次元以上の非定常問題で実行速度に問題が生じる様である．本文では，C#や C, Fortran による native な実行 code，C#から Fortran-DLL 呼び出しについて実行速度テストを行い，効率的かつ高速に計算するためには，要素モデルの計算部分のプログラムがどうあるべきかについて検討する．

２．実行速度テスト
実行速度テストのテストの条件と条件と方法
C#での実行速度を評価するために，表-1 に示す様々な CPU, OS, コンパイラ（version）の組合せで計測されているが，傾向は同様であったので，主要な 2,4,5,6 についてのみ結果を示す．テストには，流体解析に多く見られる時間発展型の 2 次元偏微分方程式の代表として，式(1)に示される拡散方程式が用いられた．演算スキームは図-1 に示される通りであり，浮動少数点演算回数は(loop 長 x16FP)/time-step とした．境界条件は図-2 に示される通りであり，K は等方性だが不透過壁が内在する．計算は倍精度(8byte)で行っており，速度は通常，単精度に比べ CPU で 1/2, GPU で 1/8 に低下する．DLL 化にあたって，Fortran 引数は全て参照渡し，2 次元以上の配列で C や C#とは low と column が逆になることに注意が必要である．
実際の計算速度 FPreal は，[計算量/経過時間]で算出される．経過時間には計算時間の他，データ転送，over head, 通信等の時間や loss-time が含まれ，式(2)で表される．式(2)からわかるように，実速度は計算速度とデータ転送速度の遅い方で決まる．時間発展型偏微分方程式に対して，現行機の多くではメモリ帯域依存の律速状態（計算時間より，メモリから CPU への data 転送時間が長い状態）になり易いことが知られている．計算速度は使用するデータ量（配列の大きさ）に依存するので，配列要素数を変えて計算時間を計測し，計算速度を求めた．試行錯誤の結果，計測誤差は概ね 10%程度である．

３．実行速度テスト
実行速度テスト結果
テスト結果
図-3 は，テスト環境 2,4,5,6 における実行速度を配列要素の Memory Size に対して示したものである．ここで，gnu 系 1)のcompile option2)はそれぞれ，-O0:最適化なし，-O2:主に cache 関係の最適化, -O3, -Ofast:その他 loop の最適化に加えてvector(SIMD:SSE,AVX)化である．Intel compiler による openmp 並列(Linux)と PGI acc による GPGPU 並列(Linux, windows)の結果も比較して表している．図-3 より,環境 2(1 core で実行)で速度は明らかに，C# << 最適化及び AVX が有効状態の[ C,C#&DLL, Fortran ]である．C と Fortran 及び DLL の速度は code や compiler に依存するが，この環境下でほぼ差はない．しかし，C#と Fortran 他では 7 倍-10 倍程度速度が異なる．最適化なしの Fortran と C#での速度がほぼ同一であり，C#上でunroll や block 化を直接 coding しても速度に変化はなかったことから，C#の低速度は cache 関連の最適化無効に起因していると推定される．Visual Studio の最適化 check-box では速度改善は見られない．一方，command line から [/optimize+]を指定する 3)と，C#でもわずかに改善はあったが，gnu 系-O1 にもかなり劣る程度であった．適切な option で compile された
Fortran-DLL を用いた場合に速度改善が見られたため，計算速度に問題がある場合には C#にこだわる必要はなかろう．
Linux 上での並列計算[最適化+ベクトル化+openmp](環境 4)や GPGPU(環境 5,6)計算と比べれば，C#とそれらとの速度には 50 倍-100 倍近い開きがある．分布型 model の様な大規模計算で，GPGPU は選択肢の１つとなろう．データ量が少ない範囲で並列計算に十分な速度が出てないのは，並列化のための over-head によるものとされている．20Mbyte を越えた辺りでCPU の並列計算速度が急減するのは，計算データ量が cache 容量を大きく上回り，CPU レジスタへの実質のデータ転送速度が落ちたためである．この解消には，[CPU 数/node]を増やし[cache/node]を上げるか(MPP 等)，node 間 MPI 通信を活用して[計算量及びデータ量/node]を減らすか(クラスター化)，帯域を上げる必要がある．簡単に帯域を上げる手段の一つがGPGPU(GDDR5)の利用である． 高速計算機，いわゆるスーパーコンピュータではこれらの方法が併せて採られている．
キーワード Common MP, C#, C/C++, Fortran , DLL, 実行速度, メモリ帯域
連絡先〒170-0004 東京都豊島区北大塚 1-15-6 (株) 東京建設コンサルタント環境防災研究所 TEL: 03-5980-2633

４．C# における高速化
における高速化と高速化と DLL の活用
演算部を Fortran/C で DLL 化 4)5)すれば，C#の要素 model はある程度の高速化は可能であると思われる．ただし，十分な性能を引き出すためには，プログラムが構造化されている必要があり，行番号で制御されている既存の F77 プログラムをそのまままるごと DLL 化するよりは fortran90 以降の文法形式で書き換えた方が良い．手間がかかることになるが，一度 C#に書き換えてから，遅い演算メソッドを改めて C か Fortran で DLL を作成し直して，どちらででも実行可能にする方が望ましい．
Win32API 仕様で作成された DLL は，Windows 上であれば CommonMP 要素 model や C#だけでなく言語に依らずに利用できる．このため，今後の発展を望むのであれば DLL の活用が望ましいが，CPU/OS/compiler & option(特に SIMD 関係部分)によっては，動作が確実ではないのでバイナリ配布する場合には注意が必要である．計算の高速化を目指すのであれば，DLL を介した GPGPU(アクセラレータ)の利用や通信による外部演算サーバの活用なども視野に入れる必要があろう．
表-1 ベンチマークテスト環境（ [ *1:倍精度では 1/8 相当], コンパイラの数字は version を示す．）

12
3
456

corename
Core2 DuoCore i5
Xeon X5482
Xeon X5680
GTX570
GTX670code name(発売年)
Penryn (2008)
Ivy Bridge (2012)
Harpertown (2007)
Westmere-EP (2010)
Fermi (2010)
Kepler (2012)∂C∂∂C=(K i)+ f∂x i∂t ∂x iclock
GHz
2.4
2.4TB
3.20
3.33
1.46
0.98

cpu
数
1122-

core数
224(x2)6(x2)-register
数 32bit
4 (x2)
8 (x2)
4 (x8)
4 (x12)1480c *
11344c*FPreal =L (1)C : 濃度等の変数 , K i : 拡散 or 透過係数 ,f : sink − source項,
x i : 座標軸(i = 1,2), t : 時間

cache
MB
3
36(x2)
12(x2)
-

帯域
GB/s
8.3
25.6
21.3
64.0
152
192.

Interconnect
FSB
QPI
FSB
QPI

OSXP
W-7
LinuxLinuxLinux
W-7

gnu
3.4.5
4.7.1

Compiler
g95
intel pgi
0.93
13C#2010
2010

9111213

Flop
Flop / Byte
=Fpeak L(2)Flop / Fpeak + Byte / Bpeak + ε Flop / Byte + Fpeak / Bpeak + ε '[計算時間] [転送時間]
 Fpeak / B peak << 1 ⇒ FPreal = Fpeak : CPU律速状態
 Flop / Byte >> Fpeak / B peak ⇒ FPreal = FpeakF / Bpeak >> Flop / Byte ⇒ FPreal = ( Flop / Byte) B peak : メモリ律速状態
 peakFlop (計算量 )= ( I max × J max ) × 浮動少数点演算回数 / Loop

Byte(データ量 ) = ( I max × J max ) × 変数の数 × Byte数 / Loop
Fpeak (最大計算速度 ) = [CPU数 / node ][core数 / CPU ][register数 / core]× [ FP回数 / clock ][clock周波数 (GHz )]data 量＞Cache 量 :B peak (最大転送速度 ) =  data 量 ≤ Cache 量 :

図-1 Fortran 演算スキーム

2 C#
2 gfortran -O0
4 ifort/1core
4 icc/1core
5 pgiacc

Memory帯域依存
Cache速度依存

2 C#&fortdll
2 gfortran -O2
4 ifort/6core
4 icc/6core
6 pgiacc (win)

2 gcc -O3
2 gfortran -O3
4 ifort/12core
4 icc/12core

100.0GPGPU

K=1

C = 0 (境界)f : source 項

openmp10.0
GFlops

内部領域

Fortran, DLL,C

帯域に依存した速度

非透過壁 K=0

1.0
C#,
非最適化 Fortran図-2 計算領域と境界条件（境界４辺単純支持）

Cache が有効

Memory 帯域律速
帯域律速

(参考資料等)
0.1
1) Windows 用 GNU コンパイラ http://tdm-gcc.tdragon.net/
0.1
1.0
10.0
100.0
1000.02) http://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html#Optimize-Options
Used memory of array (MByte)
3) C# コンパイルhttp://msdn.microsoft.com/ja-jp/library/t0hfscdc.aspx
図-3 各計算環境下における計算速度の比較結果
4) DLL 関係 http://fortranwiki.org/fortran/show/C%23+Interoperability+5) DLL 関係 http://software.intel.com/en-us/articles/calling-fortran-function-or-subroutine-in-dll-from-c-code/