c - 使用 OpenMP 进行数组缩减导致 "user defined reduction not found for"

标签 c multithreading parallel-processing openmp reduction

我正在做一项学术工作,我必须从图像中获取直方图。

一切顺利,但当我尝试使代码与 OpenMP 并行时,编译器返回此错误: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 的编译器编译的数组缩减功能(或编译器配置错误)或因为您正在尝试缩减 指针(就像您的示例的情况)。在后者中,编译器无法告诉要减少多少元素。

因此,要么使用支持 OpenMP 5.0 的编译器,要么利用array sections 功能,如下所示:

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]);
    }
}

关于c - 使用 OpenMP 进行数组缩减导致 "user defined reduction not found for",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65852864/

相关文章:

multithreading - 什么时候不使用 volatile?

c# - 按值对 ConcurrentDictionary 进行排序

c - C99 支持真的还没有普及吗?

c - 程序何时会受益于预取和非临时加载/存储?

python - 函数调用无延迟

Java Game Server线程安全接收websocket消息

c++ - 有人可以帮我并行化这个 C++ 代码吗?

c - 如何使用所有处理器在 MPI 中发送/接收

objective-c - 从 Swift 调用可变参数 Objective-C 函数

c - 源代码找不到包含头文件?