用于在 OpenMP 中添加局部矩阵的并行 for 循环

Parallel for loop for addition of local matrices in OpenMP

我在 n 个线程中有 n 个矩阵的本地副本,比如 'local'。我想更新一个全局共享矩阵 's' ,其元素是所有局部矩阵对应元素的总和。 例如。 s[0][0] = local_1[0][0] + local_2[0][0]+...+local_n[0][0].

我写了下面的循环来实现它 -

#pragma omp parallel for
for(int i=0;i<rows;i++)
{   
    for(int j=0;j<cols;j++)
        s[i][j]=s[i][j]+local[i][j];
}  

这似乎不起作用。有人可以指出我哪里错了吗?

更新了示例 -

假设有 3 个线程,具有以下局部矩阵 -


线程 1
本地 = 1 2
         3 4

线程 2 
本地 = 5 6
         7 8

线程 3 
本地 = 1 0
         0 1

共享矩阵将是

小号 = 7 8
        10 13

在整个回答过程中,我假设您已在每个线程上正确创建了私有版本的 local 作为您的问题和示例,但不是您的代码片段,请指出。

在您编写代码时,变量 iprivate,即每个线程都有自己的副本。因为它是最外层循环的迭代变量,所以每个线程都将获得自己的一组值来处理。假设您有 3 个线程和 3 行,那么线程 0 将获得 i0,线程 1 将获得 1,依此类推。显然(或没有)在每个线程上迭代更多行将获得更多 i 值来处理。在所有情况下,每个线程都将获得 i 采用的所有值集合的不相交子集。

但是,如果线程 0i==0 进行计算

s[i][j]=s[i][j]+local[i][j];

只会在线程 0 上的 local 的第 0 行工作。在示例中,我在线程 0 上使用 i,永远不会等于 1,因此线程 local 的第 1 行中的值 0 永远不会添加到 s 的第 1 行。

在它们之间,3 个线程将更新 s 的 3 行,但每个线程只会添加自己版本的 local 的行。

至于如何做你想做的,看看this question and the accepted answer. You are attempting an array reduction which, for reasons explained here,在C或C++中不直接支持。

如果允许的话,这应该是对答案最后一段的评论。
引用问题中的第一种方法是并行化数组填充而不是数组缩减。根据规范 (v4 p122):
关键构造将关联结构化块的执行限制为 一次一个线程。
每个线程减少数组中自己的部分,但只是一个接一个,本质上代码是运行串行。求和循环位于并行区域内的唯一原因是数组对于每个线程都是本地的,只有当填充它们受益于并行性时才有意义。