3.3 OpenMPによる高速化

3.3.1 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.2 OpenMPの計算時間

表3-3-1と図3-3-1にスレッド数と計算時間の関係を示します。
スレッド数が少ないときはmatrixモードの方が速いですが、 スレッド数が20を超えるとnomatrixモードの方が速くなります。
これはnomatrixモードは使用メモリーが小さいためにキャッシュが有効利用されるためと思われます。

表3-3-1 OpenMPの計算時間(()内は1スレッドとの速度比)
スレッド数benchmark100benchmark200benchmark300
nomatrixmatrixnomatrixmatrixnomatrixmatrix
1192秒 (1.0)143秒 (1.0)1907秒 (1.0)1223秒 (1.0)6138秒 (1.0)3935秒 (1.0)
2101秒 (1.9) 86秒 (1.7)1060秒 (1.8) 750秒 (1.6)3311秒 (1.9)2333秒 (1.7)
4 54秒 (3.6) 46秒 (3.1) 564秒 (3.4) 413秒 (3.0)1748秒 (3.5)1279秒 (3.1)
10 29秒 (6.5) 28秒 (5.0) 321秒 (5.9) 288秒 (4.2) 928秒 (6.6) 831秒 (4.7)
20 22秒 (8.6) 29秒 (4.8) 258秒 (7.4) 276秒 (4.4) 699秒 (8.8) 818秒 (4.8)
40 19秒 (10.0) 30秒 (4.8) 210秒 (9.1) 293秒 (4.2) 556秒 (11.0) 846秒 (4.7)


図3-3-1 OpenMPの計算時間