NEC SX-Aurora TSUBASA [5](以下、SX)を用いた高速化について述べます。
SXは1台にベクトル長256のベクトル演算器を8コア持っています。
内側のループをコンパイラーの自動ベクトル化によってベクトル計算し、
外側のループをOpenMPによって並列計算します。
さらに複数のノードで計算するには領域分割を行いMPIを用いて並列計算します。
本プログラムは前節まででOpenMPとMPIによって並列化されていますので、SXに対応することは比較的容易です。
ただしベクトル化するために余分な配列が必要になり必要メモリーは12/5=2.4倍になります。
表4-6-1にVシステム(A100-1)の1〜2ノードの計算時間を示します。
表より2ノードでは1ノードの2倍近く速くなることがわかります。
また2ノードでは使用可能なメモリーが2倍になり、より大きな問題が計算できるようになります。
ノード数 | ベンチマーク300 | ベンチマーク400 | ベンチマーク500 | ベンチマーク600 |
---|---|---|---|---|
1 | 16.2秒 (1.0) | 28.9秒 (1.0) | 50.5秒 (1.0) | 89.7秒 (1.0) |
2 | 10.2秒 (1.58) | 15.6秒 (1.85) | 26.7秒 (1.89) | 46.8秒 (1.92) |
表4-6-2にWシステム(A300-8)の1VEと8VEの計算時間を示します。
実行コマンドは以下の通りです。
$ ofd_ncc -n 8 data/benchmark/benchmark300.ofd (1VEのとき) $ mpiexec -ve 0-7 -n 8 ofd_ncc_mpi -n 8 data/benchmark/benchmark300.ofd (8VEのとき)表より8VEは1VEと比べて最大6.3倍速くなることがわかります。 また8VE数では使用可能なメモリーが8倍になり、より大きな問題が計算できるようになります。
VE数 | ベンチマーク300 | ベンチマーク400 | ベンチマーク500 | ベンチマーク600 |
---|---|---|---|---|
1 | 15.0秒 (1.0) | 28.1秒 (1.0) | 48.9秒 (1.0) | 89.8秒 (1.0) |
8 | 2.8秒 (5.4) | 5.5秒 (5.1) | 7.9秒 (6.2) | 14.2秒 (6.3) |
リスト4-6-1に計算の主要部のコンパイルメッセージを示します。
コンパイルオプションに"-D_VECTOR"が必要です。
これから、一番外側のループがOpenMPで並列計算され、
一番内側のループがベクトル計算されることがわかります。
$ cat -n updateEx.c 1 #include "ofd.h" 2 3 void updateEx_f(void) 4 { 5 const int64_t kmin = kMin; 6 const int64_t kmax = kMax; 7 8 int64_t i; 9 #ifdef _OPENMP 10 #pragma omp parallel for 11 #endif 12 for ( i = iMin; i < iMax; i++) { 13 for (int64_t j = jMin; j <= jMax; j++) { 14 int64_t n = NA(i, j, kMin); 15 int64_t n1 = n - Nj; 16 int64_t n2 = n - Nk; 17 float *ptr_ex = &Ex[n]; 18 float *ptr_hy = &Hy[n]; 19 float *ptr_hz = &Hz[n]; 20 float *ptr_hym = &Hy[n2]; 21 float *ptr_hzm = &Hz[n1]; 22 float *ptr_k1ex = &K1Ex[n]; 23 float *ptr_k2ex = &K2Ex[n]; 24 float ryn = RYn[j]; 25 float *ptr_rzn = &RZn[kMin]; 26 for (int64_t k = kmin; k <= kmax; k++) { 27 *ptr_ex = *ptr_k1ex * (*ptr_ex) 28 + *ptr_k2ex * ( ryn * (*ptr_hz - *ptr_hzm) 29 - *ptr_rzn * (*ptr_hy - *ptr_hym)); 30 ptr_ex++; 31 ptr_hy++; 32 ptr_hz++; 33 ptr_hym++; 34 ptr_hzm++; 35 ptr_k1ex++; 36 ptr_k2ex++; 37 ptr_rzn++; 38 } 39 } 40 } 41 } $ ncc -c -O2 -fopenmp -D_VECTOR -I../include -Wall -fdiag-vector=2 -fdiag-parallel=2 updateEx.c ncc: par(1801): updateEx.c, line 10: Parallel routine generated.: updateEx_f$1 ncc: par(1803): updateEx.c, line 12: Parallelized by "for". ncc: vec( 103): updateEx.c, line 13: Unvectorized loop. ncc: vec( 113): updateEx.c, line 13: Overhead of loop division is too large. ncc: opt(1097): updateEx.c, line 14: This statement prevents loop optimization. ncc: vec( 101): updateEx.c, line 26: Vectorized loop. ncc: vec( 128): updateEx.c, line 27: Fused multiply-add operation applied.