这个神话般的post教会了我很多,但我还有一个问题。对于以下代码:
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;
}
如果从另一个并行部分调用multiply()
:
#pragma omp parallel for
for (int i = 0; i < count; i++) {
multiply(a[i], b[i]);
}
因为外循环迭代取决于count
变量,如果count
是一个大数字,那么它是合理的。但是,如果count
仅为1
且我们的服务器是多核机器(例如,具有512
核心),则multiply()
函数仅生成1
线。所以在这种情况下,服务器利用不足。顺便说一句,答案还提到:
无论如何,编写这样的代码是一种不好的做法。您应该简单地保留并行区域,并允许最终用户选择是否应该启用嵌套并行。
那么在使用OpenMP
时如何平衡嵌套情况下的线程数?
答案 0 :(得分:0)
考虑使用OpenMP任务(omp taskloop
在一个并行部分和一个中间omp single
)。这允许您在不同的嵌套级别上灵活地使用OpenMP中的线程,而不是手动定义每个级别的线程数或超额订阅OS线程。
然而,这会增加调度成本。在一天结束时,没有完美的解决方案总能做到最好。相反,你必须继续测量和分析你在实际输入上的表现。