使用OpenMP计算直方图

时间:2014-02-14 11:12:52

标签: c parallel-processing openmp

我希望并行化此代码以获得最佳性能。 “直方图”存储某种颜色的服饰数量(有10种不同的颜色,因此直方图的大小为10)。 “img”是存储特定图像信息的阵列。在img的每个索引中存储一个颜色(int值,范围0..9)。这是代码:

for( i=0; i<N1; i++ ){
  for( j=0; j<N2; j++ ){
    histogram[ img[i][j] ]  = histogram[ img[i][j] ] + 1;
  }
}

我尝试了这个,但性能非常糟糕(比串行执行更糟糕):

#pragma omp parallel for schedule(static, N1/nthreads) private(i,j)
for(i=0; i<N1; i++){
  for(j=0; j<N2; j++)
  {
    #pragma omp atomic
    histogram[img[i][j]]++;
  }
}

有什么建议吗?谢谢。

3 个答案:

答案 0 :(得分:4)

使用OpenMP 4.5,您只需在C:

中使用数组缩减
int histogram[BINS] = {0};
#pragma omp parallel for reduction(+:hist)
for(i=0; i<N1; i++) {
   for(j=0; j<N2; j++) {    
       histogram[img[i][j]]++;
   }
}

答案 1 :(得分:3)

我已经详细介绍了如何解决这个问题 Fill histograms (array reduction) in parallel with OpenMP without using a critical section

它与数组缩减相同。 OpenMP在C / C ++中没有内置支持(但它在Fortran中支持),所以你必须自己做。

简单的解决方案是创建直方图的私有版本,并行填充它们,然后将它们合并到临界区中的一个直方图中。在你的情况下,你可以这样做:

int i, histogram[10];
for(i=0; i<10; i++) histogram[i] = 0;
#pragma omp parallel
{
    int i, j, histogram_private[10];
    for(i=0; i<10; i++) histogram_private[i] = 0;
    #pragma omp for nowait
    for(i=0; i<N1; i++) {
       for(j=0; j<N2; j++) {    
           histogram_private[img[i][j]]++;
       }
    }      
    #pragma omp critical 
    {
        for(i=0; i<10; i++) histogram[i] += histogram_private[i];
    }
}

也可以并行合并,但这更复杂。请参阅我提到的第一个链接以获取更多详细信息。

答案 2 :(得分:0)

你想要创建一种“减少”,所以每个线程都应该有自己的直方图数组,你必须在第二个循环中合并所有组件....参见下面的伪代码:

histogram = new int[256];
histogram_thread = new int[nbthread * 256];

#pragma omp parallel 
for(i=0; i<N1; i++){
  current_thread_id = omp_get_thread_num();
  for(j=0; j<N2; j++)
  {
    histogram_thread[current_thread_id*256 + img[i][j]]++;
  }
}

//merge
for(unsigned int ui = 0 ; ui < 256 ; ++ui)
{ 
   for(int t=0; t<nbthread ; ++t) 
   {
      histogram [i] += histogram_thread[t * 256 + i];
   }
}

delete [] histogram_thread;