使用 OpenMP 进行数组缩减导致 "user defined reduction not found for"
Array reduction with OpenMP leads to "user defined reduction not found for"
我正在做一项学术工作,我必须从图像中获取直方图。
一切顺利,但是当我尝试使代码与 OpenMP 并行时,编译器 returns 给我这个错误:user defined reduction not found for 'histog'
我使用的代码是这样的:
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]]++;
}
}
}
}
Main中函数的调用是:HistogramaParaleloRed(histog_pal_red);
错误
user defined reduction not found for
可能是因为代码是使用不支持 OpenMP 4.5 数组缩减功能的编译器编译的(或者该编译器配置错误)或者因为您正在尝试缩减 naked 指针(就像你的例子一样)。在后者中,编译器无法告诉要减少多少元素。
因此,要么使用支持 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]);
}
}
错误是试图直接减少参数指针 int *histog
。您必须改为减少本地 array,并将减少的结果复制到 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];
}
}
}
我正在做一项学术工作,我必须从图像中获取直方图。
一切顺利,但是当我尝试使代码与 OpenMP 并行时,编译器 returns 给我这个错误:user defined reduction not found for 'histog'
我使用的代码是这样的:
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]]++;
}
}
}
}
Main中函数的调用是:HistogramaParaleloRed(histog_pal_red);
错误
user defined reduction not found for
可能是因为代码是使用不支持 OpenMP 4.5 数组缩减功能的编译器编译的(或者该编译器配置错误)或者因为您正在尝试缩减 naked 指针(就像你的例子一样)。在后者中,编译器无法告诉要减少多少元素。
因此,要么使用支持 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]);
}
}
错误是试图直接减少参数指针 int *histog
。您必须改为减少本地 array,并将减少的结果复制到 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];
}
}
}