【问题标题】:OpenMP using loops and array reductionsOpenMP 使用循环和数组缩减
【发布时间】:2015-09-09 14:54:41
【问题描述】:

我写了一个程序如下:

#include "omp.h"
#include "stdio.h"

int main()
{
    int i, j, cnt[] = {0,0,0,0};
    #pragma omp parallel
    {
        int cnt_private[] = {0,0,0,0};
        #pragma omp for private(j)
        for(int i = 1 ; i <= 10 ; i++) {
            for(j = 1 ; j <= 10 ; j++) {
                int l= omp_get_thread_num();
                cnt_private[l]++;         
            }
            #pragma omp critical
            {   
               for(int m=0; m<3; m++){
                   cnt[m] = cnt_private[m];
               }
            }
           printf("%d %d %d %d %d\n",i,cnt[0],cnt[1],cnt[2],cnt[3]);
        }
     }
     return 0;
}

它应该打印每个线程对每个 i 执行的次数。由于只有一个线程采用特定的 i,因此预期输出应满足每行之和为 100。但我得到的输出形式为:

1 10 0 0 0
2 20 0 0 0
3 30 0 0 0
7 0 0 10 0
8 0 0 20 0
9 0 0 0 0
10 0 0 0 0
4 0 10 0 0
5 0 20 0 0
6 0 30 0 0

问题出在哪里?会不会是我对 OpenMP 的基本理解?还是我的还原过程错误? (我使用 GNU gcc 编译器和 4 核机器) 编译步骤:

g++ -fopenmp BlaBla.cpp
export OMP_NUM_THREADS=4
./a.out  

【问题讨论】:

  • 你声明了 i 两次。不是错误,而是...
  • 每个线程都有自己的私有cnt_private,所以它只会有来自自己线程ID的条目;而cnt 中只有一份cnt_private 数据的副本——从哪个线程运行当前的i 索引。所以你所拥有的(过早地停止m 循环)是正确的。特别是,您没有对cnt进行缩减。

标签: c++ parallel-processing openmp computation


【解决方案1】:

我不明白为什么每行的总和应该是 100。

您将cnt_private 声明为私有:

#pragma omp parallel
{
    int cnt_private[] = {0,0,0,0};
    // ...
}

因此,存储在其中的总和不会在线程之间共享。如果线程l 被执行,则只有cnt_private[l] 将递增,所有其他线程将保持为零。然后你将cnt_private 的内容分配给cnt,这不是私有的。您也分配每个为零的条目!

#pragma omp critical
{   
    for(int m=0; m<4; m++){ // I guess you want 'm<4' for the number of threads
        cnt[m] = cnt_private[m];
    }
}

i 范围从 0 到 10,程序使用 4 个线程,每个线程获得 2 到 3 个i。因此,我希望每列的总和为 30(10+20) 或 60(10+20+30)。

【讨论】:

  • 是的,我现在明白了,我在 m 循环上有一个错字...谢谢。
  • 那么,数组计数器的缩减是不是做的不准确呢?为了获得预期的结果,我是否也必须将“cnt”设为私有?
  • 我不知道你期望什么结果,你能详细说明一下结果应该是什么样子吗?也许您只想分配 cnt[l] = cnt_private[l]; 或删除 cnt_private 并改用 cnt。
  • 我只想知道数组的归约是否正确,因为我们不能直接在 C 中的数组变量上使用归约子句?
  • 还原是正确的,有一个小错误。在cnt[m] = cnt_private[m]; 行中,当前线程覆盖了其他线程计算的值。这通常是不想要的。你通常想要cnt[m] += cnt_private[m];
猜你喜欢
  • 2023-03-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-16
  • 2014-09-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多