假设我有一个方法将两个 std::vector
相乘:
double multiply(std::vector<double> const& a, std::vector<double> const& b){
double tmp(0);
/*here I could easily do a parallelization with*/
/*#pragma omp parallel loop for*/
for(unsigned int i=0;i<a.size();i++){
tmp += a[i]*b[i];
}
return tmp;
}
如果我在此函数中设置 pragma 宏,将运行对 multiply(...)
的调用
在所有线程上。
现在假设我想在其他地方做很多 vector 乘法:
void many_multiplication(std::vector<double>* a, std::vector<double>* b, unsigned int N){
/*here I could easily do a parallelization with*/
/*#pragma omp parallel loop for*/
for(unsigned int i=0;i<N;i++){
for(unsigned int j=0;j<N;j++){
multiply(a[i],b[j]);
}
}
}
我也可以用同样的方式进行并行化。但这会导致 不需要的嵌套并行性。
我如何检查是否在并行区域内调用了 multiply(..)
,
然后 multiply(...)
的 pragma
宏被“关闭”。如果它被称为
来自非平行区域,然后它“打开”。
最佳答案
嵌套并行性默认禁用,除非通过设置 OMP_NESTED
专门启用至 true
或调用 omp_set_nested(1);
(OpenMP specification 的第 2.3.2 节)按照 Avi Ginsburg 的建议明确修改嵌套设置是个坏主意。相反,您应该使用基于嵌套级别的条件并行执行:
double multiply(std::vector<double> const& a, std::vector<double> const& b){
double tmp(0);
int active_levels = omp_get_active_level();
#pragma omp parallel for reduction(+:tmp) if(active_level < 1)
for(unsigned int i=0;i<a.size();i++){
tmp += a[i]+b[i];
}
return tmp;
}
omp_get_active_level()
返回调用时封闭线程的事件并行区域的数量。它返回 0
如果从平行区域外部或不活动的外部区域调用。感谢if(active_level < 1)
子句,只有当并行区域未包含在事件区域中时,并行区域才会被激活,即并行运行,无论嵌套设置如何。
如果您的编译器不支持 OpenMP 3.0 或更高版本(例如,任何版本的 MS Visual C/C++ 编译器),则 omp_in_parallel()
call 可以改用:
double multiply(std::vector<double> const& a, std::vector<double> const& b){
double tmp(0);
int in_parallel = omp_in_parallel();
#pragma omp parallel for reduction(+:tmp) if(in_parallel == 0)
for(unsigned int i=0;i<a.size();i++){
tmp += a[i]+b[i];
}
return tmp;
}
omp_in_parallel()
如果至少一个封闭的平行区域处于事件状态,则返回非零值,但不提供有关嵌套深度的信息,即灵 active 稍差。
无论如何,编写这样的代码都是一种不好的做法。您应该简单地保留并行区域,让最终用户选择是否启用嵌套并行。
关于c++ - 打开 : check if nested parallesim,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31520326/