C++ OpenMP 在矩阵向量乘积上的工作速度非常慢
C++ OpenMP working really slow on matrix-vector product
所以,我正在使用 openMP 制作矩阵向量乘积,但我注意到它的运行速度非常慢。经过一段时间试图找出问题所在后,我刚刚删除了并行部分中的所有代码,但它仍然很慢。这里有什么问题? (n = 1000)
这是 1、2 和 4 核的时间结果。
seq_method time = 0.001047194215062
parrallel_method (1) time = 0.001050273191140 seq - par =
-0.000003078976079 seq/par = 0.997068404578433
parrallel_method (2) time = 0.001961992426004 seq - par =
-0.000914798210943 seq/par = 0.533740192460558
parrallel_method (4) time = 0.004448095121916 seq - par =
-0.003400900906854 seq/par = 0.235425319459132
即使我从并行部分删除代码 - 它也没有太大变化。
void parallel_method(float A[n][n], float B[n], float C[n], int thr_num)
{
double t1, t2;
float tmp = 0;
int i, j;
t1 = omp_get_wtime();
omp_set_dynamic(0);
omp_set_num_threads(thr_num);
#pragma omp parallel for private(tmp, j, i)
for (i = 0; i < n; i++) {
tmp = 0;
for (j = 0; j < n; j++) {
tmp += A[i][j] * B[j];
}
#pragma omp atomic
C[i] += tmp;
}
//////
t2 = omp_get_wtime();
if (show_c) print_vector(C);
par = t2 - t1;
printf("\nparrallel_method (%d) time = %.15f", thr_num, par);
printf("\nseq - par = %.15f", seq - par);
printf("\nseq/par = %.15f\n", seq / par);
}
我试图重现您的问题,但未能成功。
我有一个完全连贯的行为。
n=100
sequential_method (0) time = 0.000023339001928
parallel_method (1) time = 0.000023508997401
parallel_method (2) time = 0.000013864002540
parallel_method (4) time = 0.000008979986887
n=1000
sequential_method (0) time = 0.001439775005565
parallel_method (1) time = 0.001437967992388
parallel_method (2) time = 0.000701391996699
parallel_method (4) time = 0.000372130998080
n=10000
sequential_method (0) time = 0.140988592000213
parallel_method (1) time = 0.133375317003811
parallel_method (2) time = 0.077803490007180
parallel_method (4) time = 0.044142695999355
除了线程开销很大的小尺寸外,结果或多或少符合预期。
我做了什么:
所有措施都在同一个运行
我运行所有功能一次,没有定时预热缓存
在实际代码估计中,我也会
多次连续执行相同的函数,特别是如果时间很短以减少小的变化
运行多次实验,保留最小的一个来抑制异常值。 (我更喜欢最小值,但你也可以计算平均值)。
你应该把你所有的代码都贴出来了,我不知道你的方法是什么。但我认为您的估计是在不同的 运行 中完成的,并且没有预热缓存。对于此代码,缓存影响非常重要,核心必须存储相同的信息 (B)。而且问题还不够大,无法从更大的 L1/L2 缓存中获益。这些倍数负载可能解释了并行代码的较差性能。
关于您的代码的最后评论。每个线程都有自己的 i 值。因此 C[i] 只能由一个线程访问,原子 pragma 是无用的。
所以,我正在使用 openMP 制作矩阵向量乘积,但我注意到它的运行速度非常慢。经过一段时间试图找出问题所在后,我刚刚删除了并行部分中的所有代码,但它仍然很慢。这里有什么问题? (n = 1000)
这是 1、2 和 4 核的时间结果。
seq_method time = 0.001047194215062
parrallel_method (1) time = 0.001050273191140 seq - par = -0.000003078976079 seq/par = 0.997068404578433
parrallel_method (2) time = 0.001961992426004 seq - par = -0.000914798210943 seq/par = 0.533740192460558
parrallel_method (4) time = 0.004448095121916 seq - par = -0.003400900906854 seq/par = 0.235425319459132
即使我从并行部分删除代码 - 它也没有太大变化。
void parallel_method(float A[n][n], float B[n], float C[n], int thr_num)
{
double t1, t2;
float tmp = 0;
int i, j;
t1 = omp_get_wtime();
omp_set_dynamic(0);
omp_set_num_threads(thr_num);
#pragma omp parallel for private(tmp, j, i)
for (i = 0; i < n; i++) {
tmp = 0;
for (j = 0; j < n; j++) {
tmp += A[i][j] * B[j];
}
#pragma omp atomic
C[i] += tmp;
}
//////
t2 = omp_get_wtime();
if (show_c) print_vector(C);
par = t2 - t1;
printf("\nparrallel_method (%d) time = %.15f", thr_num, par);
printf("\nseq - par = %.15f", seq - par);
printf("\nseq/par = %.15f\n", seq / par);
}
我试图重现您的问题,但未能成功。 我有一个完全连贯的行为。
n=100
sequential_method (0) time = 0.000023339001928
parallel_method (1) time = 0.000023508997401
parallel_method (2) time = 0.000013864002540
parallel_method (4) time = 0.000008979986887
n=1000
sequential_method (0) time = 0.001439775005565
parallel_method (1) time = 0.001437967992388
parallel_method (2) time = 0.000701391996699
parallel_method (4) time = 0.000372130998080
n=10000
sequential_method (0) time = 0.140988592000213
parallel_method (1) time = 0.133375317003811
parallel_method (2) time = 0.077803490007180
parallel_method (4) time = 0.044142695999355
除了线程开销很大的小尺寸外,结果或多或少符合预期。
我做了什么:
所有措施都在同一个运行
我运行所有功能一次,没有定时预热缓存
在实际代码估计中,我也会
多次连续执行相同的函数,特别是如果时间很短以减少小的变化
运行多次实验,保留最小的一个来抑制异常值。 (我更喜欢最小值,但你也可以计算平均值)。
你应该把你所有的代码都贴出来了,我不知道你的方法是什么。但我认为您的估计是在不同的 运行 中完成的,并且没有预热缓存。对于此代码,缓存影响非常重要,核心必须存储相同的信息 (B)。而且问题还不够大,无法从更大的 L1/L2 缓存中获益。这些倍数负载可能解释了并行代码的较差性能。
关于您的代码的最后评论。每个线程都有自己的 i 值。因此 C[i] 只能由一个线程访问,原子 pragma 是无用的。