使用OpenMP并行递增数组元素

时间:2015-03-26 17:31:07

标签: c arrays for-loop openmp increment

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

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

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

任务看起来很简单但我不知道如何操作,因为OpenMP中的数组没有atomic。我可以为线程数创建一个新数组,然后将它们最终添加到一起,但这看起来并不是最佳的。

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

3 个答案:

答案 0 :(得分:2)

您的问题基本上与我提出的问题重复 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("");
}

答案 1 :(得分:0)

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

a [0] = 1且a [1] = 1,那么你将同时写入b [1]。

答案 2 :(得分:0)

你可以使用2“for()”每个数组一个