使用OpenMP

时间:2016-05-25 16:27:44

标签: c++ openmp

我有以下代码,我尝试使用OpenMP进行并行化。

int ncip(int dim, double R){
int n, r = (int)floor(R);

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

#pragma omp task shared(n, dim)
n = ncip(dim-1, R); // last coord 0

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

}
return n;
}

我需要应用基于任务的并行性,因为递归调用但我没有在计算中显示任何加速。我究竟做错了什么 ?有什么建议可以帮助加快计算速度吗?

1 个答案:

答案 0 :(得分:0)

并行性不是免费的,因此,无论如何,一个简单的pragma看起来像是,例如#pragma omp task,它需要付出很大的代价,因为它隐藏了创建和同步线程,分配和排队任务等的整个逻辑。只有当你在计算强度,多线程本身的费用之间找到平衡时,和问题的大小,(更不用说多线程的副作用,如错误共享等),你会观察到正(> 1)加速。

另外,请记住,线程数总是有限的。一旦你已经为每个线程创建了足够的工作负载,不要试图通过添加额外的工作共享结构来增强代码 - 一个线程不能神奇地划分为两个单独的指令流。也就是说,如果你有一个已经并行的最顶层循环,并且它有足够的迭代来保持所有可用线程忙,那么你将无法获得任何试图提取嵌套并行性的东西。

话虽如此,除非你可以利用其他一些技术,比如记忆部分结果,或者完全删除递归,然后只使用一个最顶层的并行循环和一个reduction子句来确保对共享变量的线程安全访问:

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

然后是一个简单的顺序函数:

int ncip(int dim, double R)
{
    int n, r = (int)floor(R);

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

    n = ncip(dim-1, R);

    for (int i = 1; i <= r; ++i)
    {   
        n = n + (2 * ncip(dim-1, sqrt(R*R - i*i)));
    }

    return n;
}

DEMO