使用 OpenMP 进行归约以计算矩阵元素的最终求和值
Make a reduction with OpenMP to compute the final summed value of an element of matrix
我有以下双循环,我在其中计算矩阵 Fisher_M[FX][FY]
的元素。
我尝试通过放一个OMP pragma来优化它#pragma omp parallel for schedule(dynamic, num_threads)
,但是增益没有预期的那么好。
有没有一种方法可以使用 OpenMP(总和)进行归约以快速计算元素 Fisher_M[FX][FY]
?或者也许这对 MAGMA 或 CUDA 可行?
#define num_threads 8
#pragma omp parallel for schedule(dynamic, num_threads)
for(int i=0; i<CO_CL_WL.size(); i++){
for(int j=0; j<CO_CL_WL.size(); j++){
if( CO_CL_WL[i][j] != 0 || CO_CL_WL_D[i][j] != 0){
Fisher_M[FX][FY] += CO_CL_WL[i][j]*CO_CL_WL_D[i][j];
}
}
}
您的代码在第 Fisher_M[FX][FY] += ...
行存在竞争条件。可以用reduce来解决:
double sum=0; //change the type as needed
#pragma omp parallel for reduction(+:sum)
for(int i=0; i<CO_CL_WL.size(); i++){
for(int j=0; j<CO_CL_WL.size(); j++){
if( CO_CL_WL[i][j] != 0 || CO_CL_WL_D[i][j] != 0){
sum += CO_CL_WL[i][j]*CO_CL_WL_D[i][j];
}
}
}
Fisher_M[FX][FY] += sum;
请注意,此代码受内存限制,计算量不大,因此并行化带来的性能增益可能小于预期(并且取决于您的硬件)。
Ps:为什么需要这个条件if( CO_CL_WL[i][j] != 0 || CO_CL_WL_D[i][j] != 0)
?如果其中任何一个为零,则总和不会改变。如果删除它,编译器可以生成更好的矢量化代码。
Ps2:在schedule(dynamic, num_threads)
子句中,第二个参数是块大小而不是使用的线程数。我建议根据您的情况将其删除。如果您想指定使用的线程数,请添加 num_threads
子句或使用 omp_set_num_threads
函数。
我有以下双循环,我在其中计算矩阵 Fisher_M[FX][FY]
的元素。
我尝试通过放一个OMP pragma来优化它#pragma omp parallel for schedule(dynamic, num_threads)
,但是增益没有预期的那么好。
有没有一种方法可以使用 OpenMP(总和)进行归约以快速计算元素 Fisher_M[FX][FY]
?或者也许这对 MAGMA 或 CUDA 可行?
#define num_threads 8
#pragma omp parallel for schedule(dynamic, num_threads)
for(int i=0; i<CO_CL_WL.size(); i++){
for(int j=0; j<CO_CL_WL.size(); j++){
if( CO_CL_WL[i][j] != 0 || CO_CL_WL_D[i][j] != 0){
Fisher_M[FX][FY] += CO_CL_WL[i][j]*CO_CL_WL_D[i][j];
}
}
}
您的代码在第 Fisher_M[FX][FY] += ...
行存在竞争条件。可以用reduce来解决:
double sum=0; //change the type as needed
#pragma omp parallel for reduction(+:sum)
for(int i=0; i<CO_CL_WL.size(); i++){
for(int j=0; j<CO_CL_WL.size(); j++){
if( CO_CL_WL[i][j] != 0 || CO_CL_WL_D[i][j] != 0){
sum += CO_CL_WL[i][j]*CO_CL_WL_D[i][j];
}
}
}
Fisher_M[FX][FY] += sum;
请注意,此代码受内存限制,计算量不大,因此并行化带来的性能增益可能小于预期(并且取决于您的硬件)。
Ps:为什么需要这个条件if( CO_CL_WL[i][j] != 0 || CO_CL_WL_D[i][j] != 0)
?如果其中任何一个为零,则总和不会改变。如果删除它,编译器可以生成更好的矢量化代码。
Ps2:在schedule(dynamic, num_threads)
子句中,第二个参数是块大小而不是使用的线程数。我建议根据您的情况将其删除。如果您想指定使用的线程数,请添加 num_threads
子句或使用 omp_set_num_threads
函数。