目次

4.2 OpenMPによる並列化

4.2.1 OpenMPプログラム

OpenMPにより、計算時間の大部分を占める電磁界の更新を高速化することができます。
リスト4-2-1はEx成分を更新する関数です。
リスト3-2-1との違いは5行目の指示文だけです。
このようにFDTD法は並列化向きのアルゴリズムであるためにOpenMPを用いると簡単に並列化することができます。
OpenMPを有効にするには、VC++ではコンパイルオプションに"/openmp"、 gccではコンパイルオプションとリンクオプションに"-fopenmp"が必要です。

リスト4-2-1 OpenMPプログラム(updateEx.c)


     1	void updateEx(void)
     2	{
     3		int i;
     4	#ifdef _OPENMP
     5	#pragma omp parallel for
     6	#endif
     7		for (    i = iMin; i <  iMax; i++) {
     8		for (int j = jMin; j <= jMax; j++) {
     9			int64_t n = NA(i, j, kMin);
    10			for (int k = kMin; k <= kMax; k++) {
    11				const int64_t m = iEx[n];
    12				Ex[n] = C1[m] * Ex[n]
    13				      + C2[m] * (RYn[j] * (Hz[n] - Hz[n - Nj])
    14				               - RZn[k] * (Hy[n] - Hy[n - Nk]));
    15				n++;
    16			}
    17		}
    18		}
    19	}

4.2.2 領域分割について

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

4.2.3 OpenMPの計算時間

表4-2-1にOpenMPのスレッド数を変えたときの計算時間を示します。
4~8スレッドで約3倍速くなります。
novectorモードとvectorモードの計算時間はほぼ同じです。 これからCPUでは使用メモリーの少ないnovectorモードを推奨します。
16スレッドは8スレッドより遅く、ハイパースレッディングの効果はないので、 スレッド数は物理コア数を推奨します。

表4-2-1 OpenMPの計算時間
(ベンチマーク100、単精度、()内は1プロセスとの速度比)
スレッド数novectorvector
138.0秒 (1.0)37.1秒 (1.0)
219.9秒 (1.9)19.1秒 (1.9)
411.5秒 (3.3)13.9秒 (2.7)
811.2秒 (3.4)14.3秒 (2.6)
1613.9秒 (2.7)14.8秒 (2.5)

表4-2-2にベンチマーク問題を変えたときの計算時間を示します。

表4-2-2 OpenMPの計算時間
(8スレッド、単精度)
ベンチマークnovectorvector
100 11.2秒 14.3秒
200 98.6秒113.6秒
300326.5秒385.2秒
400779.0秒827.8秒