【问题标题】:Parallel incrementing of array elements with OpenMP使用 OpenMP 并行递增数组元素
【发布时间】:2015-05-30 20:41:09
【问题描述】:

我有大小为 N 的数组 a 和随机数。使用 OpenMP,我想为 A 中的每个数字递增数组 b 的元素 0 到 9,大小为 10。语言是 C。

#pragma omp parallel for
for(i = 0; i < N; i++)
   b[a[i]]++;

不幸的是,在 b 的某些元素中显然存在同时写入,结果与预期不符。我尝试将 b 设置为 firstprivate 和 lastprivate 但这也没有帮助。

任务看起来很简单,但我不知道该怎么做,因为 OpenMP 中没有数组的 atomic。我可以为线程数创建一个新数组,然后最后将它们加在一起,但这似乎不是最佳选择。

在数组b 的元素中计算a 中的数字出现次数的最快方法是什么?

【问题讨论】:

  • 独立求和,然后合并结果。
  • @BrianCain 我不确定你的意思。 “总和”是指增量吗?使用“独立”是指我应该创建一个新的私有变量吗?使用合并,您的意思是我应该最后将所有版本的私有变量相加吗?因为这对我来说似乎是低效的。你能用一个简单的代码片段告诉我你的意思吗?
  • 算法并不像我想象的那么简单。但最终这是一个权衡,它是否有效可能取决于 N 与b 的大小之比(它真的总是 10 吗?)。一个更简单的替代方法是使用一系列互斥锁。
  • 我不明白“OpenMP 中的数组没有atomic”。您指的是哪个 OpenMP 规范?而且您并没有尝试在数组上进行原子操作。您正在尝试以原子方式递增数组的单个元素,但我找不到任何证据表明这不起作用。

标签: c arrays for-loop openmp increment


【解决方案1】:

如果 a[] 中的任何值相同,那么您将同时写入 b 的相同元素。

a[0] = 1 和 a[1] = 1 那么您将同时写入 b[1]。

【讨论】:

    【解决方案2】:

    您可以为每个数组使用 2 个“for()”

    【讨论】:

    • 这应该是一条评论
    【解决方案3】:

    您的问题本质上是我提出的问题的重复 fill-histograms-in-parallel-with-openmp-without-using-a-critical-section.

    在您的情况下,简单的解决方案是

    #pragma omp parallel
    {
        int i, b_local[10] = {0};
        #pragma omp for nowait 
        for(i = 0; i < n; i++) b_local[a[i]]++;
        #pragma omp critical
        for(i=0; i<10; i++) b[i] += b_local[i];    
    }
    

    可以在没有关键部分的情况下执行此操作(请参阅我的问题),但不一定更有效。

    这是一个工作示例

    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    
    #define N 100
    
    void foo(int *b, int *a, int n) {
        #pragma omp parallel
        {
            int i, b_local[10];
            memset(b_local, 0, 10*sizeof(int));
            #pragma omp for 
            for(i = 0; i < n; i++) b_local[a[i]]++;
    
    
            #pragma omp critical
            {     
                for(i=0; i<10; i++) {
                    b[i] += b_local[i]; 
                }
            }
    
        }
    }
    
    int main() {   
        int i;
        int b[10] = {0,1,2,3,4,5,6,7,8,9};
        int b2[10] = {0,1,2,3,4,5,6,7,8,9};
        int a[N];
        for(i=0; i<N; i++) a[i] = rand()%10;
    
        foo(b,a,N);
        for(i=0; i<N; i++) b2[a[i]]++;
        for(i=0; i<10; i++) printf("%d ", b[i]); puts("");
        for(i=0; i<10; i++) printf("%d ", b2[i]); puts("");
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-10-01
      • 2018-05-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-11-16
      • 1970-01-01
      相关资源
      最近更新 更多