OpenCV平方差异速度的总和

时间:2012-04-14 17:46:49

标签: c++ algorithm computer-vision

我一直在使用openCV做一些块匹配,我注意到它的平方差异代码的总和与这样的直接for循环相比非常快:

int SSD = 0;
for(int i =0; i < arraySize; i++)
    SSD += (array1[i] - array2[i] )*(array1[i] - array2[i]);

如果我查看源代码以查看繁重发生的位置,那么 OpenCV人员的for循环在循环的每次迭代中一次进行4个平方差计算。执行块匹配的功能如下所示。

int64
icvCmpBlocksL2_8u_C1( const uchar * vec1, const uchar * vec2, int len )
{
int i, s = 0;
int64 sum = 0;

for( i = 0; i <= len - 4; i += 4 ) 
{   
    int v = vec1[i] - vec2[i];
    int e = v * v;

    v = vec1[i + 1] - vec2[i + 1]; 
    e += v * v;
    v = vec1[i + 2] - vec2[i + 2];
    e += v * v;
    v = vec1[i + 3] - vec2[i + 3];
    e += v * v;
    sum += e;
}

for( ; i < len; i++ )
{
    int v = vec1[i] - vec2[i];

    s += v * v;
}

return sum + s;
}

此计算适用于无符号8位整数。它们在此函数中对32位浮点执行类似的计算:

double
icvCmpBlocksL2_32f_C1( const float *vec1, const float *vec2, int len )
{
double sum = 0;
int i;

for( i = 0; i <= len - 4; i += 4 )
{
    double v0 = vec1[i] - vec2[i];
    double v1 = vec1[i + 1] - vec2[i + 1];
    double v2 = vec1[i + 2] - vec2[i + 2];
    double v3 = vec1[i + 3] - vec2[i + 3];

    sum += v0 * v0 + v1 * v1 + v2 * v2 + v3 * v3;
}
for( ; i < len; i++ )
{
    double v = vec1[i] - vec2[i];

    sum += v * v;
}
return sum;
}

我想知道是否有人知道如果将一个循环分成4个这样的块可能会加速代码?我应该补充一点,在这段代码中没有发生多线程。

2 个答案:

答案 0 :(得分:4)

我的猜测是这只是unrolling the loop的一个简单实现 - 它在循环的每次传递中节省了3次加法和3次比较,如果例如检查{{1},这可以节省很多涉及缓存未命中。缺点是这种优化增加了代码的复杂性(例如,如果长度不能被4整除,那么最后的额外for循环将完成len%4项的循环),当然,它是依赖于体系结构的优化其改进程度因硬件/编译器等而异......

然而,与大多数优化相比,它可以直接进行,并且无论架构如何,都可能会带来某种性能提升,因此将其投入到那里并希望获得最佳效果的风险很低。由于OpenCV是一个支持良好的代码块,我确信有人会对这些代码块进行检测并发现它们非常值得 - 正如您自己所做的那样。

答案 1 :(得分:2)

您的代码有一个明显的优化,即:

int SSD = 0;
for(int i = 0; i < arraySize; i++)
{
    int v = array1[i] - array2[i];
    SSD += v * v;
}