[英]Array reduction with OpenMP leads to “user defined reduction not found for”
I'm doing a scholar work and I have to obtain the histogram from a IMAGE.我正在做一项学术工作,我必须从图像中获取直方图。
All is going well, but when I tried to make the code parallel with the OpenMP, the compiler returns me this error: user defined reduction not found for 'histog'
一切进展顺利,但是当我尝试使代码与 OpenMP 并行时,编译器返回此错误:
user defined reduction not found for 'histog'
The code that I used is this:我使用的代码是这样的:
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)
for (int i = 0; i < N; i++)
{
for (int j = 0; j < N; j++)
{
histog[IMAGEN[i][j]]++;
}
}
}
}
And the call to the function in Main is: HistogramaParaleloRed(histog_pal_red);
在 Main 中对 function 的调用是:
HistogramaParaleloRed(histog_pal_red);
The error错误
user defined reduction not found for
can happen because either the code was compiled with a compiler that does not support the OpenMP 4.5 array reduction feature (or that compiler is misconfigured) or because your are trying the reduce a naked pointer ( like it is the case of your example ).可能会发生,因为代码是使用不支持OpenMP 4.5数组缩减功能的编译器编译的(或者该编译器配置错误),或者因为您正在尝试缩减裸指针(就像您的示例一样)。 In the latter, the compiler cannot tell how many elements are to be reduce.
在后者中,编译器无法确定要减少多少元素。
So either you use a compiler that supports OpenMP 5.0
and take advantage of array sections feature as follows:因此,您可以使用支持
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]]++;
}
}
}
}
or alternatively, implement the reduction yourself.或者,自己实施减少。
Implement the Reduction manually手动实施归约
One approach is to create a shared structure among threads ( ie, thread_histog ), then each thread updates its position, and afterward, threads reduce the values of the shared structure into the original histog array.一种方法是在线程之间创建一个共享结构(即thread_histog ),然后每个线程更新它的position,然后,线程将共享结构的值减少到原始的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]
}
}
Another approach is to create an array of locks, one for each element of the histog
array.另一种方法是创建一个锁数组,一个用于
histog
数组的每个元素。 Whenever a thread updates a given histog
position, first acquires the lock corresponded to that position so that no other thread will be updating concurrently the same array position.每当一个线程更新给定的
histog
时,首先获取对应于该 position 的锁,这样其他线程就不会同时更新同一个数组 position。
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]);
}
}
The error is attempting to directly reduce the argument pointer int *histog
.该错误试图直接减少参数指针
int *histog
。 You must instead reduce a local array , and copy over the reduced results to histog
.您必须改为减少本地数组,并将减少的结果复制到
histog
。
void HistogramaParaleloRed(int *histog)
{
int localHistog[NG];
/*
* your code as before, replacing histog with localHistog
*/
#pragma omp parallel
{
#pragma omp for
for (int i = 0; i < NG; i++)
{
localHistog[i] = 0;
}
#pragma omp for reduction(+ : localHistog)
for (int i = 0; i < N; i++)
{
for (int j = 0; j < N; j++)
{
localHistog[IMAGEN[i][j]]++;
}
}
/*
* copy localHistog into output histog
*/
#pragma omp for
for (int i = 0; i < NG; i++)
{
histog[i] = localHistog[i];
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.