【问题标题】:Starting a thread for each inner loop in OpenMP为 OpenMP 中的每个内部循环启动一个线程
【发布时间】:2010-02-07 03:37:44
【问题描述】:

我是 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 项目启动了一个线程?我将如何测试?如果错了,正确的做法是什么?谢谢!

注意:代码已大大简化

【问题讨论】:

  • 可能想用您正在使用的语言对其进行标记,尽管您必须删除现有标记之一。
  • 好点 mmyers - 供参考,看起来他正在使用 c/c++(openMP 仅适用于 c/c++ 和 fortran)

标签: c arrays loops parallel-processing openmp


【解决方案1】:

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

#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

至于你的其余代码,你可能想在一个新问题中加入更多细节(从小样本很难看出),但例如,当j 是后来才宣布。在我上面的示例中,它自动是私有的。我猜diff 是我们在示例中看不到的变量。此外,循环变量 i 自动是私有的(来自 version 2.5 spec - 在 3.0 规范中相同)

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

编辑:以上所有内容对于您和我展示的代码都是正确的,但您可能对以下内容感兴趣。对于 OpenMP 版本 3.0(在例如 gcc version 4.4 中可用,但不是版本 4.3)有一个 collapse 子句,您可以在其中编写代码,但使用 #pragma omp parallel for collapse (2) 并行化两个 for 循环(参见 the spec)。

编辑:好的,我下载了 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

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

【讨论】:

    【解决方案2】:

    您可以尝试使用嵌套的 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);
    
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-14
      • 1970-01-01
      • 2021-01-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多