gpt4 book ai didi

c++ - 初始化变量以减少 omp

转载 作者:行者123 更新时间:2023-11-30 01:18:13 25 4
gpt4 key购买 nike

OpenMP 标准指定了缩减变量的初始值。那么我是否必须初始化变量以及在以下情况下我将如何初始化:

int sum;
//...
for(int it=0;i<maxIt;i++){
#pragma omp parallel
{
#pragma omp for nowait
for(int i=0;i<ct;i++)
arrayX[i]=arrayY[i];

sum = 0;
#pragma omp for reduction(+:sum)
for(int i=0;i<ct;i++)
sum+=arrayZ[i];
}
//Use sum
}

请注意,我只使用一个并行区域来最小化开销并允许第一个循环中的 nowait。按原样使用它会导致数据竞争 (IMO),因为在其他线程开始第二个循环后来自第一个循环的线程将重置总和。
当然,我可以在外循环的顶部执行此操作,但在一般情况下,对于大型代码库,您可能会忘记您需要或已将其设置在那里,这会产生意想不到的结果。
“omp single”在这里有帮助吗?我怀疑当线程A执行single时,另一个线程可能已经进入了reduction loop。“omp barrier”是可能的,但我想避免它,因为它会打败“nowait”。

最后一个例子:

#pragma omp parallel
{
sum = 0;
#pragma omp for reduction(+:sum)
for(int i=0;i<ct;i++)
sum+=arrayZ[i];
//Use sum
sum = 0;
#pragma omp for reduction(+:sum)
for(int i=0;i<ct;i++)
sum+=arrayZ[i];
//Use sum
}

我将如何(重新)初始化这里?

最佳答案

编辑:这个答案是错误的,因为它做出了不在 OpenMP 规范中的假设。由于无法删除已接受的答案,我将其留在这里作为一个例子,人们应该始终怀疑和验证在 Internet 上找到的代码和/或声明。

实际上,代码并没有表现出数据竞争:

#pragma omp parallel
{
...
sum = 0;
#pragma omp for reduction(+:sum)
for(int i=0;i<ct;i++)
sum+=arrayZ[i];
...
}

这里发生的是 sum 的私有(private)拷贝在工作共享结构中创建并初始化为 0 (+ 运算符的初始化值)。每个本地拷贝都由循环体更新。一旦给定的线程完成,它就会在 for 末尾的隐式屏障处等待。构造。一旦所有线程都到达屏障,它们的本地拷贝 sum被加在一起,结果被添加到共享值。

所有线程都可能执行sum = 0;并不重要在不同的时间,因为它的值只有在达到障碍后才会更新。想想上面的代码执行类似的操作:

...
sum = 0;
// Start of the for worksharing construct
int local_sum = 0; // ^
for(int i = i_start; i < i_end; i++) // | sum not used here
local_sum += arrayZ[i]; // v
// Implicit construct barrier
#pragma omp barrier
// Reduction
#pragma omp atomic update
sum += local_sum;
#pragma omp barrier
// End of the worksharing construct
...

同样适用于第二个例子。

关于c++ - 初始化变量以减少 omp,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22938901/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com