【问题标题】:Parallelizing C++ code using OpenMP, calculations actually slower in parallel使用 OpenMP 并行化 C++ 代码,并行计算实际上更慢
【发布时间】:2016-05-24 17:35:07
【问题描述】:

我有以下要并行化的代码:

int ncip( int dim, double R)
{   
    int i;
    int r = (int)floor(R);
    if (dim == 1)
    {   
        return 1 + 2*r; 
    }
    int n = ncip(dim-1, R); // last coord 0

    #pragma omp parallel for
    for(i=1; i<=r; ++i)
    {   
        n += 2*ncip(dim-1, sqrt(R*R - i*i) ); // last coord +- i
    }

    return n;
}

在没有 openmp 的情况下运行的程序执行时间是 6.956 秒,当我尝试并行化 for 循环时,我的执行时间大于 3 分钟(那是因为我自己结束了它)。我在并行化这段代码方面做错了什么?

第二次尝试

    int ncip( int dim, double R)
{   
int i;
int r = (int)floor( R);
if ( dim == 1)
{   return 1 + 2*r; 
}


#pragma omp parallel 
{
int n = ncip( dim-1, R); // last coord 0
#pragma omp for reduction (+:n)
for( i=1; i<=r; ++i)
{   
    n += 2*ncip( dim-1, sqrt( R*R - i*i) ); // last coord +- i
}

}

return n;

}

【问题讨论】:

  • 您是否启用了嵌套并行?您是否尝试过使用 pragma omp task ?你可以产生多少线程?你用什么处理器?你传递了什么参数?
  • 你似乎在每次迭代中更新n,这样是非法的,除非你使用reduction
  • 使用任务并将中间结果存储在数组中。最后,将所有结果相加
  • 您能否为您观察到的运行时提供一个具体的可重现示例(请参阅minimal reproducible example

标签: c++ parallel-processing openmp


【解决方案1】:

你做错了!

(1) 变量n 中存在数据竞争。如果要并行化在同一内存区域中写入的代码,则必须使用 reduction(在 for 中)、atomiccritical 避免数据危害。

(2) 可能你启用了嵌套并行,所以每次调用函数ncip 时程序都会创建一个新的并行区域。应该是这个主要问题。对于递归函数,我建议您只创建 一个 并行区域,然后使用 pragma omp task

不要与#pragma omp for 并行化并尝试使用#pragma omp task。看这个例子:

int ncip(int dim, double R){
    ...
    #pragma omp task
    ncip(XX, XX);

    #pragma omp taskwait
    ...
}

int main(int argc, char *argv[]) {
    #pragma omp parallel
    {
        #pragma omp single 
        ncip(XX, XX);
    } 
    return(0); 
}

更新:

//Detailed version (without omp for and data races)
int ncip(int dim, double R){
    int n, r = (int)floor(R);

    if (dim == 1) return 1 + 2*r; 

    n = ncip(dim-1, R); // last coord 0

    for(int i=1; i<=r; ++i){   
        #pragma omp task
        {
            int aux = 2*ncip(dim-1, sqrt(R*R - i*i) ); // last coord +- i

            #pragma omp atomic
            n += aux;
        }
    }
    #pragma omp taskwait
    return n;
}

PS:您不会因此而获得加速,因为创建任务的开销大于单个任务的工作量。您可以做的最好的事情是将此算法重新编写为迭代版本,然后尝试将其并行化。

【讨论】:

猜你喜欢
  • 1970-01-01
  • 2015-05-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多