Openmp中for循环内的关键部分
Critical Section inside for loop in Openmp
我有以下代码:
#pragma omp parallel for private(dist,i,j)
for(k=0;k<K;k++)
{
//some code
for(i=0;i<N;i++)
{
#pragma omp critical
{
if(min_dist[i]>dist[i])//The point i belongs to the cluster k
{
newmembership[i]=k;
min_dist[i]=dist[i];
}
}
dist[i]=0;
}
}
dist 是一个私有变量,而 newmemebership 和 min_dist 是共享的 variable.For 我的测试用例 如果我们 运行 代码没有添加临界区 [=18],代码仍然有效=] 据我所知,它不应该因为两个线程可能 运行 宁在相同的 i 值上并且可能修改 min_dist[i] 和 newmembership[i] 导致冲突。
请解释是否有必要添加关键部分构造,还有是否有更好的方法来实现上述内容,即使用锁或信号量?
删除 critical
部分将是一场数据竞赛。考虑以下执行:
(min_dist[42] == 100)
time | Thread 0 | Thread 1
----------------------------------------------------------------------
0 | k = 13 |
1 | i = 42 | k = 14
2 | dist[i] = 50 | i = 42
3 | min_dist[i] > dist[i] ==> true | dist[i] = 75
4 | newmembership[i] = 13 | min_dist[i] > dist[i] ==> true
5 | min_dist[i]=50 | newmembership[i] = 14
6 | ... | min_dist[i]=75
所以你最终得到了一个非最小解。您甚至可能会得到冲突的 min_dist
/ newmembership
值。
另一种方法是创建线程 private
local_min_dist
/ local_newmembership
数组,并在执行结束时合并它们:
#pragma omp parallel
{
// Note: implicitly private because defined inside the parallel region
int local_newmembership[N];
int local_min_dist[N];
#pragma omp for private(dist,i,j)
for(k=0;k<K;k++)
{
//some code
for(i=0;i<N;i++)
{
// NOTE: No critical region necessary
// as we operate on private variables
if(local_min_dist[i]>dist[i])//The point i belongs to the cluster k
{
local_newmembership[i]=k;
local_min_dist[i]=dist[i];
}
dist[i]=0;
}
}
for (i = 0; i < N; i++)
{
// Here we have a critical region,
// but it is outside of the k-loop
#pragma omp critical
if (min_dist[i] > local_min_dist[i])
{
newmembership[i] = local_newmembership[i];
local_min_dist[i] = local_min_dist[i];
}
}
}
我有以下代码:
#pragma omp parallel for private(dist,i,j)
for(k=0;k<K;k++)
{
//some code
for(i=0;i<N;i++)
{
#pragma omp critical
{
if(min_dist[i]>dist[i])//The point i belongs to the cluster k
{
newmembership[i]=k;
min_dist[i]=dist[i];
}
}
dist[i]=0;
}
}
dist 是一个私有变量,而 newmemebership 和 min_dist 是共享的 variable.For 我的测试用例 如果我们 运行 代码没有添加临界区 [=18],代码仍然有效=] 据我所知,它不应该因为两个线程可能 运行 宁在相同的 i 值上并且可能修改 min_dist[i] 和 newmembership[i] 导致冲突。
请解释是否有必要添加关键部分构造,还有是否有更好的方法来实现上述内容,即使用锁或信号量?
删除 critical
部分将是一场数据竞赛。考虑以下执行:
(min_dist[42] == 100)
time | Thread 0 | Thread 1
----------------------------------------------------------------------
0 | k = 13 |
1 | i = 42 | k = 14
2 | dist[i] = 50 | i = 42
3 | min_dist[i] > dist[i] ==> true | dist[i] = 75
4 | newmembership[i] = 13 | min_dist[i] > dist[i] ==> true
5 | min_dist[i]=50 | newmembership[i] = 14
6 | ... | min_dist[i]=75
所以你最终得到了一个非最小解。您甚至可能会得到冲突的 min_dist
/ newmembership
值。
另一种方法是创建线程 private
local_min_dist
/ local_newmembership
数组,并在执行结束时合并它们:
#pragma omp parallel
{
// Note: implicitly private because defined inside the parallel region
int local_newmembership[N];
int local_min_dist[N];
#pragma omp for private(dist,i,j)
for(k=0;k<K;k++)
{
//some code
for(i=0;i<N;i++)
{
// NOTE: No critical region necessary
// as we operate on private variables
if(local_min_dist[i]>dist[i])//The point i belongs to the cluster k
{
local_newmembership[i]=k;
local_min_dist[i]=dist[i];
}
dist[i]=0;
}
}
for (i = 0; i < N; i++)
{
// Here we have a critical region,
// but it is outside of the k-loop
#pragma omp critical
if (min_dist[i] > local_min_dist[i])
{
newmembership[i] = local_newmembership[i];
local_min_dist[i] = local_min_dist[i];
}
}
}