我希望并行化此代码以获得最佳性能。 “直方图”存储某种颜色的服饰数量(有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]]++;
}
}
有什么建议吗?谢谢。
答案 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;