我的代码用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;
}
请帮我解决一下?
非常感谢!
答案 0 :(得分:1)
你在第二种情况下表现不佳的原因是整个循环体都在critical
,所以它实际上不能并行执行任何东西。
由于您说calcul
函数中存在某些竞争条件,因此请考虑在critical
内的func
部分放置calcul
部分。这样,文件可以并行读取(可能是I / O,无论如何都会降低执行速度)。
如果性能仍然很差,您需要查看嵌套的critical
函数并尝试识别竞争条件。
基本上,您希望尽可能地将任何atomic
部分向下推或完全消除它们。如果归结为对共享变量的非常简单的更新,在某些情况下,您可以使用OpenMP {{1}}编译指示,它具有更好的性能但灵活性更低。
答案 1 :(得分:0)
即使代码中的所有内容都是正确的,由于操作(添加)的关联性,您仍可能从OpenMP减少中得到不同的结果。 为了能够为给定数量的线程重现相同的结果,您需要通过将每个线程的部分和存储在共享数组中来自行实现减少。在并行区域之后,主线程可以添加这些结果。这种方法意味着线程总是执行相同的迭代,即静态调度策略。