OpenMP - “#pragma omp critical”重要性

OpenMP - "#pragma omp critical" importance

所以我开始使用 OpenMP(多线程)来提高我的矩阵乘法的速度,我目睹了一些奇怪的事情:当我关闭 OpenMP 支持时(在 Visual Studio 2019) 我的嵌套 for 循环完成速度提高了 2 倍。 所以我删除了“#pragma omp critical”以测试它是否显着减慢了进程,进程速度提高了 4 倍比以前(支持 OpenMP 开启)。

这是我的问题:“#pragma omp critical”在嵌套循环中重要吗?不能跳过吗?

        #pragma omp parallel for collapse(3)
        for (int i = 0; i < this->I; i++)
        {
            for (int j = 0; j < A.J; j++)
            {
                m.matrix[i][j] = 0;
                for (int k = 0; k < A.I; k++)
                {   
                        #pragma omp critical
                        m.matrix[i][j] += this->matrix[i][k] * A.matrix[k][j];                                            
                }
            }
        }

#pragma omp critical 在这里是必需的,因为有(远程)机会两个线程可以写入特定的 m.matrix[i][j] 值。这会损害性能,因为一次只有一个线程可以访问受保护的赋值语句。

没有 collapse 部分可能会更好(然后您可以删除 #pragma omp critical)。将总和累加到一个临时局部变量,然后在 k 循环完成后将其存储在 m.matrix[i][j] 中。

Here's my question: is "#pragma omp critical" important in nested loop? Can't I just skip it?

如果矩阵 mthisA 不同,则不需要任何临界区。相反,您需要确保每个线程将写入矩阵 m 的不同位置,如下所示:

       #pragma omp parallel for collapse(2)
        for (int i = 0; i < this->I; i++)
        {
            for (int j = 0; j < A.J; j++)
            {
                m.matrix[i][j] = 0;
                for (int k = 0; k < A.I; k++)
                {   
                    m.matrix[i][j] += this->matrix[i][k] * A.matrix[k][j];                                            
                }
            }
        }

collapse 子句将为每个线程分配不同的一对 (i, j) 因此不会有多个线程写入矩阵的相同位置 m (竞争条件)。