我有一个大小为 N 的随机数数组 a
。使用 OpenMP,我想为 A 中的每个数字增加大小为 10 的数组 b
的元素 0 到 9。语言是 C。
#pragma omp parallel for
for(i = 0; i < N; i++)
b[a[i]]++;
不幸的是,b 的某些元素显然是同时写入的,结果与预期不符。我尝试将 b 设置为 firstprivate 和 lastprivate,但这也没有帮助。
这个任务看起来很简单,但我不知道该怎么做,因为在 OpenMP 中没有用于数组的 atomic
。我可以为线程数创建一个新数组,然后在最后将它们加在一起,但这似乎不是最佳选择。
在数组 b
的元素中计算 a
中的数字出现次数的最快方法是什么?
最佳答案
你的问题本质上是我问过的问题的重复 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("");
}
关于c - 使用 OpenMP 并行递增数组元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29285110/