我正在尝试使用OpenMP优化有关图像处理的代码。我仍在学习它,我来到经典的并行for循环,这比我的单线程实现要慢。
我尝试并行化的for循环只有50次迭代,我看到它解释了为什么OpenMP在这种情况下使用由于开销操作而无用。
但是有可能评估这些成本吗?共享/私有/ firstprivate(...)子句之间的成本差异是什么?
这是我要并行化的for循环:
#pragma omp parallel for \
shared(img_in, img_height, img_width, w, update_gauss, MoGInitparameters, nb_motion_bloc) \
firstprivate(img_fg, gaussStruct) \
private(ContrastHisto, j, x, y) \
schedule(dynamic, 1) \
num_threads(max_threads)
for(i = 0; i<h; i++){ // h=50
for(j = 0; j<w; j++){
ComputeContrastHistogram_generic1D_rect(img_in, H_DESC_STEP*i, W_DESC_STEP*j, ContrastHisto, H_DESC_SIZE, W_DESC_SIZE, 2, img_height, img_width);
x = i;
y = w - 1 - j;
img_fg->data[y][x] = 1-MatchMoG_GaussianInt(ContrastHisto, gaussStruct->gauss[i*w+j], update_gauss, MoGInitparameters);;
#pragma omp critical
{
nb_motion_bloc += img_fg->data[y][x];
nb_motion_bloc += img_fg->data[y][x];
}
}
}
也许我犯了一些错误,但如果是这样,请告诉我原因!!
答案 0 :(得分:2)
有几点不能解决您的具体问题。
尽量避免使用#pragma omp critical
。在这种情况下,您可以通过向reduction(+:nb_motion_bloc )
行添加omp parallel for
子句并使用nb_motion_bloc += 2*img_fg->data[y][x];
来完全删除它。
根据每次迭代需要做多少工作,短循环会产生(更多)更多的开销,而不是它们的价值。
现在回答问题。如果您没有更改任何变量,请不要将它们分类为shared / private / firstprivate。如果它们应该被每个线程使用并丢弃,你可以使用像
这样的结构#pragma omp parallel
{
int x, y;
#pragma omp for
for(i = 0; i<h; i++)
{
...
}
}
如果工作负载达到平衡,请考虑使用schedule(static)
。
关于shared / private / firstprivate之间的差异,请参阅this和this个问题。来自wikipedia:
- shared:并行区域内的数据是共享的,这意味着所有线程同时可见并可访问。默认情况下,工作共享区域中的所有变量都是共享的,但循环迭代计数器除外。
- private:并行区域内的数据对每个线程都是私有的,这意味着每个线程都有一个本地副本并将其用作临时变量。未初始化私有变量,并且不维护该值以在并行区域之外使用。默认情况下,OpenMP循环结构中的循环迭代计数器是私有的。
- default:允许程序员声明并行区域中的默认数据范围将是共享的,或者对于C / C ++是无共享的,或者对于Fortran是共享的,firstprivate的,private的,或者是none。 none选项强制程序员使用数据共享属性子句声明并行区域中的每个变量。
- firstprivate:喜欢私有,除了初始化为原始值。
- lastprivate:与private相同,但在构造之后更新原始值。