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-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-1にOpenMPのスレッド数を変えたときの計算時間を示します。
4~8スレッドで約3倍速くなります。
novectorモードとvectorモードの計算時間はほぼ同じです。
これからCPUでは使用メモリーの少ないnovectorモードを推奨します。
16スレッドは8スレッドより遅く、ハイパースレッディングの効果はないので、
スレッド数は物理コア数を推奨します。
| スレッド数 | novector | vector |
|---|---|---|
| 1 | 38.0秒 (1.0) | 37.1秒 (1.0) |
| 2 | 19.9秒 (1.9) | 19.1秒 (1.9) |
| 4 | 11.5秒 (3.3) | 13.9秒 (2.7) |
| 8 | 11.2秒 (3.4) | 14.3秒 (2.6) |
| 16 | 13.9秒 (2.7) | 14.8秒 (2.5) |
表4-2-2にベンチマーク問題を変えたときの計算時間を示します。
| ベンチマーク | novector | vector |
|---|---|---|
| 100 | 11.2秒 | 14.3秒 |
| 200 | 98.6秒 | 113.6秒 |
| 300 | 326.5秒 | 385.2秒 |
| 400 | 779.0秒 | 827.8秒 |