错误
user defined reduction not found for
这可能是由于编译器不支持
OpenMP 4.5的数组约简特性(或编译器配置错误),或者您试图缩减一个
裸指针(就像您示例中所示)导致的。在后一种情况下,编译器无法
确定要缩减多少个元素。
因此,您需要使用支持OpenMP 5.0
的编译器,并利用数组段特性,如下:
void HistogramaParaleloRed(int *histog)
{
#pragma omp parallel
{
#pragma omp for
for (int i = 0; i < NG; i++)
{
histog[i] = 0;
}
#pragma omp for reduction(+ : histog[:N])
for (int i = 0; i < N; i++)
{
for (int j = 0; j < N; j++)
{
histog[IMAGEN[i][j]]++;
}
}
}
}
或者,手动实现这个降低操作。
手动实现降低操作
一种方法是在线程之间创建一个共享结构(即thread_histog),然后每个线程更新自己的位置,然后将共享结构的值降低到原始的histog数组中。
void HistogramaParaleloRed(int *histog, int number_threads)
{
int thread_histog[number_threads][NG] = {{0}};
#pragma omp parallel
{
int thread_id = omp_get_thread_num();
#pragma omp for
for (int i = 0; i < N; i++)
for (int j = 0; j < N; j++)
thread_histog[thread_id][IMAGEN[i][j]]++;
#pragma omp for no_wait
for (int i = 0; i < NG; i++)
for(int j = 0; j < number_threads; j++)
histog[i] += thread_histog[j][i]
}
}
另一种方法是创建锁的数组,其中每个锁都对应于
histog
数组的一个元素。每当线程更新给定的
histog
位置时,它首先获取该位置对应的锁,以确保没有其他线程会同时更新相同的数组位置。
void HistogramaParaleloRed(int *histog)
{
omp_lock_t locks[NG];
#pragma omp parallel
{
#pragma omp for
for (int i = 0; i < NG; i++)
omp_init_lock(&locks[i]);
int thread_id = omp_get_thread_num();
#pragma omp for
for (int i = 0; i < N; i++)
for (int j = 0; j < N; j++){
int pos = IMAGEN[i][j]
omp_set_lock(&locks[pos]);
thread_histog[thread_id][pos]++;
omp_unset_lock(&locks[pos]);
}
#pragma omp for no_wait
for (int i = 0; i < NG; i++)
omp_destroy_lock(&locks[i]);
}
}