6

我对 OpenMP 相当陌生,我正在尝试启动一个单独的线程来处理 2D 数组中的每个项目。

所以本质上,这个:

for (i = 0; i < dimension; i++) {
    for (int j = 0; j < dimension; j++) {
        a[i][j] = b[i][j] + c[i][j];

我正在做的是这样的:

#pragma omp parallel for shared(a,b,c) private(i,j) reduction(+:diff) schedule(dynamic)
    for (i = 0; i < dimension; i++) {
        for (int j = 0; j < dimension; j++) {
            a[i][j] = b[i][j] + c[i][j];

这实际上是否为每个 2D 项目启动了一个线程?我将如何测试?如果错了,正确的做法是什么?谢谢!

注:代码已大大简化

4

2 回答 2

7

在您的代码示例中,只有外部循环是并行的。您可以通过在内部循环中打印来进行测试omp_get_thread_num(),您会看到,对于给定i的 ,线程 num 是相同的(当然,这个测试是说明性的而不是确定性的,因为不同的运行会给出不同的结果)。例如,使用:

#include <stdio.h>
#include <omp.h>
#define dimension 4

int main() {
    #pragma omp parallel for
    for (int i = 0; i < dimension; i++)
        for (int j = 0; j < dimension; j++)
            printf("i=%d, j=%d, thread = %d\n", i, j, omp_get_thread_num());
    }

我得到:

i=1, j=0, thread = 1
i=3, j=0, thread = 3
i=2, j=0, thread = 2
i=0, j=0, thread = 0
i=1, j=1, thread = 1
i=3, j=1, thread = 3
i=2, j=1, thread = 2
i=0, j=1, thread = 0
i=1, j=2, thread = 1
i=3, j=2, thread = 3
i=2, j=2, thread = 2
i=0, j=2, thread = 0
i=1, j=3, thread = 1
i=3, j=3, thread = 3
i=2, j=3, thread = 2
i=0, j=3, thread = 0

至于其余代码,您可能希望在新问题中添加更多细节(从小示例中很难分辨),但例如,您不能将private(j)whenj仅在稍后声明。在我上面的示例中,它自动是私有的。我猜diff这是我们在样本中看不到的变量。此外,循环变量i是自动私有的(来自2.5 版规范- 与 3.0 版规范相同)

for 或并行 for 构造的 for 循环中的循环迭代变量在该构造中是私有的。

编辑:以上所有内容对于您和我展示的代码都是正确的,但您可能对以下内容感兴趣。对于 OpenMP 3.0 版(在例如gcc 4.4版中可用,但在 4.3 版中不可用)有一个collapse子句,您可以按照自己的方式编写代码,但 #pragma omp parallel for collapse (2)可以并行化两个 for 循环(请参阅规范)。

编辑:好的,我下载了 gcc 4.5.0 并运行了上面的代码,但是使用collapse (2)得到以下输出,显示了现在并行化的内部循环:

i=0, j=0, thread = 0
i=0, j=2, thread = 1
i=1, j=0, thread = 2
i=2, j=0, thread = 4
i=0, j=1, thread = 0
i=1, j=2, thread = 3
i=3, j=0, thread = 6
i=2, j=2, thread = 5
i=3, j=2, thread = 7
i=0, j=3, thread = 1
i=1, j=1, thread = 2
i=2, j=1, thread = 4
i=1, j=3, thread = 3
i=3, j=1, thread = 6
i=2, j=3, thread = 5
i=3, j=3, thread = 7

如果您想并行化两个循环,此处的评论(搜索“Workarounds”)也与版本 2.5 中的解决方法相关,但上面引用的版本 2.5 规范非常明确(请参阅第A.35节中的不合格示例) .

于 2010-02-07T04:00:41.077 回答
0

您可以尝试使用嵌套的 omp 并行 fors(omp_set_nested(1)调用后),但并非所有 openmp 实现都支持它们。

所以我想制作一些 2D 网格并从单个开始网格上的所有线程(例如固定的 4x4 线程网格):

#pragma omp parallel for
for(k = 0; k < 16; k++)
{
    int i,j,i_min,j_min,i_max,j_max;
    i_min=(k/4) * (dimension/4);
    i_max=(k/4 + 1) * (dimension/4);
    j_min=(k%4) * (dimension/4);
    j_max=(k%4 + 1) * (dimension/4);

    for(i=i_min;i<i_max;i++)
      for(j=j_min;j<j_max;j++)
       f(i,j);

}
于 2010-02-07T05:01:47.577 回答