c - 什么时候应该忽略关键部分以及什么时候不需要等待?开放式MP

标签 c multithreading performance parallel-processing openmp

我正在学习 OpenMP,我有一些问题,我相信这些问题可以理清我的思路。

我有一个矩阵乘法 A*B 的小例子,其中 A、B、C 是全局变量。我知道如何并行化 for 循环一次一个或两个循环一起崩溃,但我的问题是:

如果我在哪个循环中使用#pragma omp for,我是否应该忽略check1中的关键部分,我们需要在那里添加,因为C是一个全局变量,并且也在我应该在哪个循环中使用关键字 nowait 以避免循环中出现障碍,因为我知道 #pragma omp for 它会自动拥有它。当我尝试对这个嵌套 for 循环进行编程时,我正在制作:my_approach

int i,j,sum;
for(int i=0;i<N;i++) # loop1
    for(j=0;j<N;j++){ #loop2
         for(k=sum=0;k<N;k++) #loop3
             sum += A[i][j]*B[k][J]
         C[i][j] = sum  # check1
     };

我的方法

#pragma omp parallel num_threads(4)
{
    #pragma omp for schedule(static) nowait // **one**
     for(int i=0;i<N;i++) # loop1
        for(j=0;j<N;j++){ #loop2
             for(k=sum=0;k<N;k++) #loop3
                 sum += A[i][j]*B[k][J]
             #pragma omp critical //  **two**
             C[i][j] = sum  # check1
         };
}
  1. 一个:我在那里放了“nowait”,因为这样代码运行得更快,我不知道原因,也不知道我是否做出了正确的决定
  2. 两个:我使用临界区来思考如何使用线程构建它。

所以我们可以说这是正确的,那么并行化第二个 for 循环或第三个循环我是否需要这些东西呢?如果有人可以向我解释何时需要添加关键部分,或者如果我一次并行化此嵌套 for 循环,我将不胜感激!

最佳答案

在您的示例中,您既不需要 nowait 也不需要 ritic:

 #pragma omp parallel for schedule(static) num_threads(4) // **one**
 for(int i=0;i<N;i++) # loop1
    for(j=0;j<N;j++){ #loop2
         for(k=0;k < N;k++) #loop3
             C[i][j] += A[i][j]*B[k][J]
  

不存在竞争条件,在更新全局矩阵C期间,每个线程都会更新该矩阵的不同位置。然而,您有一个不同的竞争条件,即在变量jk更新期间,因为两者在线程之间共享,修复此竞争条件只需将它们设为私有(private)即可,例如,如下所示:

 #pragma omp parallel for schedule(static) num_threads(4) // **one**
 for(int i=0;i<N;i++) # loop1
    for(int j=0;j<N;j++){ #loop2
         for(int k=0;k < N;k++) #loop3
             C[i][j] += A[i][j]*B[k][J]

one : I put "nowait" there because code runs faster with that , I dont know the reason or if I am making the right decision

那么,您不应该在没有充分理由的情况下盲目删除它。在这里您可以安全地删除,因为 1) 在并行 for 和并行区域之间没有使用任何代码,2) 并行区域也有一个隐式屏障。

#pragma omp parallel num_threads(4)
{
    #pragma omp for schedule(static) nowait // **one**
     ...
   // There no code here
} // <-- implicit barrier

尽管如此,在您的情况下,您可以将两个编译指示合并为一个并删除 nowait 子句:

#pragma omp parallel for schedule(static) num_threads(4)

So let's say that this is right what about with parallelizing the second for loop or third do I need those things or not ?

一般答案取决于。它取决于太多因素,但通常您应该从最外层循环开始,因为这些循环将生成具有最高粒度的任务,但这又取决于具体情况。尽管如此,在您的具体示例中,您可以并行化最外层循环。

您可以尝试并行化嵌套循环来查看性能是否有任何提升。通过并行化最外层循环与并行化前两个最外层循环进行测试,并检查是否获得任何性能增益。

关于c - 什么时候应该忽略关键部分以及什么时候不需要等待?开放式MP,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67370226/

相关文章:

c - 我在 VS 中收到预期的常量表达式错误,但它在 tutorialspoint 网络编译器上运行?

c - C语言以2为底的对数

linux - 在 Linux 中实现快速 "GetCurrentThreadId"

java - 在使用 Ehcache 刷新只读缓存之前,我需要锁定它吗?

c - WSAWaitForMultipleObjects 阻塞除最后一个以外的任何线程

python - c 程序 SWIG 到 python 给出 'ImportError: dynamic module does not define init function'

c - 如何在 C 中使用 'fread' 从文件中读取并获取分离的数据?

java - Java源代码生成中的霍夫曼代码解码器编码器

java - "A single Server tick took 60,00 seconds (should be max 0,05)"

php - 如何从两端对 PHP 网站进行负载测试