OpenMPでは並列化可能なループの直前に指示文を記入します。
図2-9-2の行列・ベクトル積はデータ依存関係がないので、
一番外側のループをOpenMPを用いてそのまま並列化することができます。
ベクトル同士の演算(BLAS Level-1)も以下のように簡単に並列化することができます。
リスト3-3-1 OpenMPによるコピー(Zcopy)の並列化
void Zcopy(int64_t n, const d_complex_t *x, d_complex_t *y) { int64_t i; #ifdef _OPENMP #pragma omp parallel for #endif for (i = 0; i < n; i++) { y[i].r = x[i].r; y[i].i = x[i].i; } }
リスト3-3-2 OpenMPによる内積(Zdotu)の並列化
d_complex_t Zdotu(int64_t n, const d_complex_t *x, const d_complex_t *y) { d_complex_t ret; double sum_r = 0, sum_i = 0; int64_t i; #ifdef _OPENMP #pragma omp parallel for reduction (+:sum_r, sum_i) #endif for (i = 0; i < n; i++) { sum_r += (x[i].r * y[i].r) - (x[i].i * y[i].i); sum_i += (x[i].r * y[i].i) + (x[i].i * y[i].r); } ret.r = sum_r; ret.i = sum_i; return ret; }
表3-3-1と図3-3-1にスレッド数と計算時間の関係を示します。
スレッド数が少ないときはmatrixモードの方が速いですが、
スレッド数が多いときはnomatrixモードの方が速くなります。
ただし、両者の差は小さいので使用メモリーの少ないnomatrixモードを推奨します。
またスレッド数は物理コア数(=8)と論理コア数(=16)の差は小さいのでどちらでもかまいません。
スレッド数 | benchmark100 | benchmark200 | ||
---|---|---|---|---|
nomatrix | matrix | nomatrix | matrix | |
1 | 136秒 (1.0) | 113秒 (1.0) | 1066秒 (1.0) | 859秒 (1.0) |
2 | 77秒 (1.77) | 79秒 (1.43) | 592秒 (1.80) | 523秒 (1.64) |
4 | 71秒 (1.92) | 55秒 (2.05) | 535秒 (1.99) | 460秒 (1.87) |
8 | 47秒 (2.89) | 49秒 (2.31) | 377秒 (2.83) | 385秒 (2.23) |
16 | 46秒 (2.96) | 52秒 (2.17) | 296秒 (3.60) | 402秒 (2.14) |
図3-3-1 OpenMPの計算時間(CPU)