4.3 OpenMPによる高速化

4.3.1 OpenMPプログラム

OpenMPにより、計算時間の大部分を占める電磁界の更新を高速化することができます。
リスト4-3-1はEx成分を更新する関数です。
リスト3-2-1との違いは4行目の指示文だけです。
このようにFDTD法は並列化向きのアルゴリズムであるためにOpenMPを用いると簡単に並列化することができます。


リスト4-3-1 OpenMPプログラム(updateEx.c)
     1	void updateEx()
     2	{
     3		int    i;
     4	#pragma omp parallel for
     5		for (    i = iMin; i <  iMax; i++) {
     6		for (int j = jMin; j <= jMax; j++) {
     7			int64_t n = NA(i, j, 0);
     8			int64_t n1 = n - Nj;
     9			int64_t n2 = n - Nk;
    10			for (int k = kMin; k <= kMax; k++) {
    11				int m = iEx[n];
    12				Ex[n] = C1[m] * Ex[n]
    13				      + C2[m] * (RYn[j] * (Hz[n] - Hz[n1])
    14				               - RZn[k] * (Hy[n] - Hy[n2]));
    15				n++;
    16				n1++;
    17				n2++;
    18			}
    19		}
    20		}
    21	}

4.3.2 領域分割について

リスト4-3-1においてX,Y,Z方向のインデックスの範囲はそれぞれ(0-Nx),(0-Ny),(0-Nz)ではなく、 (iMin-iMax),(jMin-jMax),(kMin-kMax)としています。
このようにするとMPIにおいて領域分割したときとコードを共通化することができます。 iMin,iMax,jMin,jMax,kMin,kMaxを適当に設定することにより任意の部分領域に対応することができます。

4.3.3 OpenMPの計算時間

表4-3-1にWindows環境でスレッド数を1〜8と変えたときの計算時間の測定結果を示します。
2スレッドである程度速くなりますが、スレッド数をそれ以上増やしても速くなりません。
また2スレッド以上ではSIMDの有無で計算時間が変わりません。

表4-3-1 OpenMPの計算時間(Windows環境、i7-4770K、()内は1スレッドとの速度比)
スレッド数ベンチマークNo.1ベンチマークNo.2
SIMDなしSSESIMDなしSSE
129.1秒(1.0)20.7秒(1.0)233.5秒(1.0)159.1秒(1.0)
217.7秒(1.64)16.9秒(1.22)143.0秒(1.63)129.7秒(1.22)
417.6秒(1.65)17.2秒(1.20)134.6秒(1.73)128.6秒(1.24)
817.4秒(1.67)17.9秒(1.16)134.8秒(1.73)131.2秒(1.21)

表4-3-2と図4-3-1にLinux環境でスレッド数を1〜40と変えたときの計算時間の測定結果を示します。
10スレッドまで速くなりますが、それ以上スレッド数を増やすと逆に遅くなることがわかります。
またスレッド数が多いときはSIMDを使用した方が遅くなることがあります。

表4-3-2 OpenMPの計算時間(FOCUSスパコンDシステム、Xeon E5-2670v2 x2、icc17.0、()内は1スレッドとの速度比)
スレッド数ベンチマークNo.1ベンチマークNo.2
SIMDなしSSESIMDなしSSE
130.6秒(1.0)17.9秒(1.0)230.8秒(1.0)154.2秒(1.0)
214.6秒(2.10)10.2秒(1.75)119.9秒(1.92)81.7秒(1.89)
48.4秒(3.64)7.0秒(2.56)64.7秒(3.57)53.5秒(2.88)
103.9秒(7.85)5.9秒(3.03)46.9秒(4.92)46.3秒(3.33)
204.0秒(7.65)6.1秒(2.93)48.6秒(4.75)48.4秒(3.19)
404.4秒(6.95)9.7秒(1.85)72.9秒(3.17)55.3秒(2.79)


図4-3-1 OpenMPの計算時間(FOCUSスパコンDシステム、Xeon E5-2670v2 x2、icc17.0)