减少Openmp会在代码

时间:2016-06-30 03:47:01

标签: openmp reduction

我的代码用openmp使用" reduction"从运行到运行不会返回相同的结果。

案例1:使用"减少"

sum = 0;
omp_set_num_threads(4);
#pragma omp parallel for reduction(+:sum)
for(ii = 0; ii < 100; i++)
   sum = sum + func(ii);

与func(ii)有副作用。实际上,func(ii)使用了另一个calcul()函数,它可以在并行执行中导致竞争条件。我认为calcul()函数可能是导致此问题的原因。但是,我使用&#34; critical&#34;,结果始终相同,但此解决方案对性能不利。

案例2:使用&#34; critical&#34;

sum = 0;
#pragma omp parallel for
for(ii = 0; ii < 100; i++)
{
   #pragma omp critical
   sum = sum + func(ii);
}

使用func(ii)函数

func(int val) 
{
   read_file(val);
   calcul(); /*calculate something from reading_file(val)*/
   return val_fin;
}

请帮我解决一下?

非常感谢!

2 个答案:

答案 0 :(得分:1)

你在第二种情况下表现不佳的原因是整个循环体都在critical,所以它实际上不能并行执行任何东西。

由于您说calcul函数中存在某些竞争条件,因此请考虑在critical内的func部分放置calcul部分。这样,文件可以并行读取(可能是I / O,无论如何都会降低执行速度)。

如果性能仍然很差,您需要查看嵌套的critical函数并尝试识别竞争条件。

基本上,您希望尽可能地将任何atomic部分向下推或完全消除它们。如果归结为对共享变量的非常简单的更新,在某些情况下,您可以使用OpenMP {{1}}编译指示,它具有更好的性能但灵活性更低。

答案 1 :(得分:0)

即使代码中的所有内容都是正确的,由于操作(添加)的关联性,您仍可能从OpenMP减少中得到不同的结果。 为了能够为给定数量的线程重现相同的结果,您需要通过将每个线程的部分和存储在共享数组中来自行实现减少。在并行区域之后,主线程可以添加这些结果。这种方法意味着线程总是执行相同的迭代,即静态调度策略。

相关问题: Order of execution in Reduction Operation in OpenMP