使用openmp并行化计数for循环

时间:2014-06-02 21:43:43

标签: c++ openmp

我有一个二维图像,我想计算所有颜色并将结果存储在一个数组中。我知道颜色的数量,所以我可以先设置数组的大小。我现在的问题是计数持续时间太长了。如何使用OpenMP加快计数?
我目前的序列号是

std::vector<int> ref_color_num_thread;
    ref_color_num.resize(ref_color.size());
    std::fill(ref_color_num.begin(), ref_color_num.end(), 0);
    ref_color_num_thread.resize(ref_color.size());
    std::fill(ref_color_num_thread.begin(), ref_color_num_thread.end(), 0);

    for (int i = 0; i < image.width(); i++)
    {
        for (int j = 0; j < image.height(); j++)
        {
            for (int k = 0; k < (int)ref_color.size(); k++)
            {
                if (image(i, j, 0, 0) == ref_color[k].R && image(i, j, 0, 1) == ref_color[k].G && image(i, j, 0, 2) == ref_color[k].B)
                    ref_color_num_thread[k]++;
            }
        }
    }

第一种方法是在每个循环中设置#pragma omp parallel for(每次尝试在另一个循环中),但每次因为错误的内存访问而导致程序崩溃。我必须使用private()作为我的载体吗?

2 个答案:

答案 0 :(得分:3)

您正在做的是填充颜色的直方图。这与使用OpenMP在C / C ++中进行数组缩减等效。在C / C ++中,OpenMP没有内置的支持(但它在Fortran中确实存在,因为Fortran中的数组大小是已知的,在C / C ++中它只有静态数组才知道)。但是,使用OpenMP自行完成C / C ++数组缩减很容易。

#pragma omp parallel 
{
    std:vector<int> ref_color_num_thread_private(ref_color.size(),0);
    #pragma omp for
    for (int i = 0; i < image.width(); i++) {
        for (int j = 0; j < image.height(); j++) {
            for (int k = 0; k < (int)ref_color.size(); k++) {
                if (image(i, j, 0, 0) == ref_color[k].R && image(i, j, 0, 1) == ref_color[k].G && image(i, j, 0, 2) == ref_color[k].B) 
                    ref_color_num_thread_private[k]++;
            }
        }
    }
    #pragma omp critical 
    {   
        for(int i=0; i<(int)ref_color.size(); i++) {
             ref_color_num_thread[i] += ref_color_num_thread_private[i];
        }
    }
}

我详细介绍了他的Fill histograms (array reduction) in parallel with OpenMP without using a critical section

我展示了如何在没有关键部分的情况下减少阵列,但它更加棘手。你应该测试第一个案例,看看它是否适合你。只要颜色数(ref_color.size())与像素数相比较小就应该很好地并行化。否则,您可能需要尝试没有关键部分的第二种情况。

答案 1 :(得分:1)

如果外部两个循环(i或j)中的一个是并行化的,则存在竞争条件,因为内部循环在向量(k)上迭代。我认为你的崩溃就是因为这个原因。

您必须重组您的计划。这不是一件容易的事,但有一个想法是每个线程都使用ref_color_num_thread向量的本地副本。计算完成后,您可以总结所有向量。

如果k足够大以提供足够的并行性,则可以交换循环。而不是“i,j,k”,你可以按“k,i,j”的顺序迭代。如果我没有弄错的话,就没有违反的依赖关系。然后你可以并行化外部k循环,让内部i和j循环顺序执行。

<强>更新

pragma omp也支持减少,例如:

#pragma omp for reduction(+ : nSum)

以下是指向某些documentation的链接。

也许这可以帮助您重组您的计划。