我有大小为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
中数字出现次数的最快方法?
答案 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()”每个数组一个