Multithreading Openmp中循环的内部关键部分

Multithreading Openmp中循环的内部关键部分,multithreading,openmp,critical-section,Multithreading,Openmp,Critical Section,我有以下代码: #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 { newmembe

我有以下代码:

#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;
    }
}
#专用pragma omp并行(dist,i,j)

对于(k=0;k删除<代码>临界段将是一个数据竞争。考虑以下执行:

(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
#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];
        }
    }
}
因此,您最终会得到一个非最小值的解决方案。您甚至可能会得到冲突的
min\u dist
/
newmembership

另一种方法是创建线程
private
local\u min\u dist
/
local\u newmembership
数组,并在执行结束时合并它们:

(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
#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并行
{
//注意:隐式私有,因为在并行区域内定义
int local_newmembership[N];
int local_min_dist[N];
#私人用pragma omp(i,j区)
对于(k=0;k本地最小距离[i])
{
newmembership[i]=本地_newmembership[i];
local_min_dist[i]=local_min_dist[i];
}
}
}

请养成习惯,不要包含所有引用变量的声明。最好包含实际变量。