如何分析/识别紧密处理循环中的慢速步骤?

时间:2012-05-08 15:06:00

标签: c image-processing opencv profiling

我有一些专有的图像处理代码。它遍历图像并计算图像的一些统计数据。我正在讨论的代码类型的一个例子可以在下面看到,虽然这是需要优化的算法。

我的问题是,有哪些工具可用于分析这些紧密循环,以确定哪些方面很慢?困了,Windows性能分析器都更专注于识别哪些方法/功能很慢。我已经知道什么功能很慢,我只需要弄清楚如何优化它。

void BGR2YUV(IplImage* bgrImg, IplImage* yuvImg)
{
    const int height    = bgrImg->height;
    const int width     = bgrImg->width;
    const int step      = bgrImg->widthStep;
    const int channels  = bgrImg->nChannels;

    assert(channels == 3);
    assert(bgrImg->height == yuvImg->height);
    assert(bgrImg->width == yuvImg->width);
    // for reasons that are not clear to me, these are not the same.
    // Code below has been modified to reflect this fact, but if they 
    // could be the same, the code below gets sped up a bit.
//  assert(bgrImg->widthStep == yuvImg->widthStep);
    assert(bgrImg->nChannels == yuvImg->nChannels);

    const uchar* bgr = (uchar*) bgrImg->imageData;
          uchar* yuv = (uchar*) yuvImg->imageData;

    for (int i = 0; i < height; i++) 
    {
        for (int j = 0; j < width; j++) 
        {
            const int ixBGR = i*step+j*channels;
            const int b = (int) bgr[ixBGR+0];
            const int g = (int) bgr[ixBGR+1];
            const int r = (int) bgr[ixBGR+2];

            const int y = (int) (0.299 * r + 0.587 * g + 0.114 * b);
            const double di = 0.596 * r - 0.274 * g - 0.322 * b;
            const double dq = 0.211 * r - 0.523 * g + 0.312 * b;
            // Do some shifting and trimming to get i & q to fit into uchars.
            const int iv = (int) (128 + max(-128.0, min(127.0, di)));
            const int q = (int) (128 + max(-128.0, min(127.0, dq)));

            const int ixYUV = i*yuvImg->widthStep + j*channels;
            yuv[ixYUV+0] = (uchar)y;
            yuv[ixYUV+1] = (uchar)iv;
            yuv[ixYUV+2] = (uchar)q;
        }
    }
}

1 个答案:

答案 0 :(得分:1)

由于你无法分享代码,我有一些一般的建议。首先要记住,分析器会告诉您代码的哪一部分需要花费更多时间,而更高级的代码可以建议进行一些修改以提高速度。但总的来说,算法优化比调整代码获得更快的速度。对于您共享的示例代码,如果您使用google高效或快速RGB到YUV转换,您将找到大量方法(从使用查找表到SSE2和GPU利用率),这些方法大大提高了速度,我确信没有任何分析器可以推荐任何一个。

因此,一旦您知道该方法的哪个部分很慢,您就可以执行以下两个步骤:

  1. 算法优化:了解算法正在做什么,并尝试提出更优化的算法。谷歌是你的朋友,可能有人已经考虑过优化该算法并与全世界分享这个想法/代码。通过,通常你应该考虑你的约束。例如,加速代码的最简单但最有效的图像处理方法是将图像的大小减小到尽可能小。一个好的经验法则是质疑代码/算法中的每一个假设。例如,是否需要处理800x600图像?或者可以在不影响准确性的情况下将尺寸减小到320x240?处理三通道图像是否必要?或者用灰度图像可以实现相同的效果?我想你应该已经明白了。

  2. 实施优化:一些高级分析工具可以建议如何调整代码,您可以尝试找到价格合理的代码。有些人可能不同意,但我认为没有必要使用这些工具。通常不需要图像处理精确值,例如,可以使用例如整数的滤波器响应的粗略近似来代替双浮点的精确计算。 SIMD指令和最近的GPU已被证明非常适合优化图像处理方法。如果可以的话,你应该考虑一下。你总是可以谷歌如何优化循环或一些特定的操作。毕竟你可以做的一件事就是将你的代码分解成更小的逻辑部分并进行更改,以便通过共享部分来揭示算法或方法。然后你可以在SO上分享每一篇文章,并询问其他人对如何优化它的看法。