OpenMP嵌套For循环竞争条件

时间:2018-02-14 04:41:38

标签: c multithreading openmp race-condition

我目前的情况遇到了种族问题。我正在尝试创建线程数量,因为有核心,在OMP上使用锁定。我曾尝试#pragma omp critical#pragma amp atomic,但没有一个人在帮忙。我得到一些疯狂的负数...我知道如何使用私有,但我想实际同步线程,而不是为线程创建多个变量,然后在最后组合。

// multiplication
#pragma omp parallel for
for (i = 0; i < N; i++)
{
     for (j = 0; j < N; j++)
     {
          c[i][j] = 0.;
          for (k = 0; k < N; k++) 
          {        
               omp_set_lock(&lock);
               //#pragma omp critical
               //#pragma omp atomic
               c[i][j] += a[i][k] * b[k][j];
               threadTasks[omp_get_thread_num()]++;
               omp_unset_lock(&lock);
          }
          printf("[%d, %d]: Thread ID %d\n", i, j, omp_get_thread_num());
     }
}

2 个答案:

答案 0 :(得分:1)

对于此矩阵乘法,您不需要针对竞争条件的任何保护(锁定,原子,关键部分)。事实上,它会完全扼杀你的表现。由于每个线程正在执行不同的i,因此不同的线程永远不能写入或读取c[i][j]的相同索引。

但是,您需要为内部循环设置私有循环变量,否则一切都会出错。通常,将所有变量声明为尽可能本地。然后它们是隐式私有的,对于在私有部分之外不需要的变量几乎总是正确的。

  

我知道如何使用private来实现它,但我想实际同步线程,而不是为线程创建多个变量,然后在最后组合。

对于内部循环变量,除了将它们设为私有之外别无选择。很多时候,减少(私有副本,最后的聚合)可以比共享结果变量更好地执行。在这种情况下,共享结果应该没问题。

答案 1 :(得分:0)

对于具有各种操作的多个嵌套循环,我将不使用#pragma omp parallel for,而是将其分解为#pragma omp parallel#pragma omp for collapse(2)。 请参阅下面的完整代码:

#pragma omp parallel
{
#pragma omp for collapse(2)
    for (i = 0; i < N; i++){
        for (j = 0; j < N; j++){
            c_parallel[i][j] = 0.;
            for (k = 0; k < N; k++) {  
               c_parallel[i][j] += a_parallel[i][k] * b_parallel[k][j];    
            }
        }
    }

}//end parallel region

我将vector< vector<float>>用于矩阵,并在i5 4核/ Win10上获得了300%的更快性能。