我假设如果你有一个嵌套循环,你想使用OpenMP,你必须为内循环私有制作循环变量,如下所示。
int x,y,z;
#pragma omp parallel for private(y,z)
for (x=0;x<100;x++)
{
for (y=0;y<100;y++)
{
for (z=0;z<100;z++)
{
a[x+y+z]=a[x]+a[y]+a[z]; //arbitrary code, a is just an arbitrary array
}
}
}
然而,当我在没有private(y,z)
的情况下运行相同的循环时,它仍然运行良好。那么您实际需要使用private
/ shared
的情况是什么?
答案 0 :(得分:1)
a[x+y+z]=a[x]+a[y]+a[z];
的值不会向您显示任何问题,因为它恰好与您正在寻找的潜在错误完全相同。
尝试一个对每个数组元素唯一的计算,并且每个数组元素只写一次
例如。取较小的数组,大小为1000,循环0-9,计算索引x + 10 * y + 100 * y并将索引写入值
然后尝试引发错误,例如在计算中交换x,y,z
你会注意到结果不干净,因为y和z是共享的。一些数组元素将不会被写入(将它们初始化为例如1111以通知),而有些则不会写入它们的索引
也许写一个检查器,验证之后每个条目的索引和值是否相同。
答案 1 :(得分:1)
了解共享和私有之间的区别非常重要,而且您似乎做得很好。接下来要学习的是,在并行区域之外声明的变量是隐式shared
,而在内部声明的变量是隐式private
。如果您考虑它并且您可以并且应该通过始终尽可能在本地声明变量来保存自己的显式声明,这是非常有意义的。
在您的代码中,这意味着:
#pragma omp parallel for private(y,z)
for (int x=0;x<100;x++)
{
for (int y=0;y<100;y++)
{
for (int z=0;z<100;z++)
{
a[x+y+z]=a[x]+a[y]+a[z]; //arbitrary code, a is just an arbitrary array
}
}
}
这使得使用和不使用OpenMP可以更轻松地推理您的代码。对于OpenMP,默认情况下代码正确 1 。 (a
隐含shared
,x,z,y
隐式private
)
显式数据共享子句会产生冗余,除非您确切知道自己在做什么,否则也可能是危险的:私有变量即使在并行区域之外具有有效值也未初始化,甚至使用私有变量也意味着什么并行区域后的变量?因此,我强烈建议使用隐式默认方法,除非高级用法需要。
1 您的代码实际上是错误的,因为多个线程将不同的值写入同一个内存位置 - 甚至可以同时从它们读取。但我不打算详细说明,因为你提到它就是一个例子。然而,共享很可能是你想要的这种循环。