OpenCV平方差异速度的总和

ncR*_*ert 6 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]);
Run Code Online (Sandbox Code Playgroud)

如果我查看源代码以查看繁重发生的位置,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;
}
Run Code Online (Sandbox Code Playgroud)

此计算用于无符号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;
}
Run Code Online (Sandbox Code Playgroud)

我想知道是否有人有任何想法如果打破一个4块这样的块可能会加快代码?我应该补充一点,在这段代码中没有发生多线程.

Mat*_*att 4

我的猜测是,这只是展开循环的一个简单实现- 它在循环的每次传递中节省了 3 次加法和 3 次比较,例如,如果检查len涉及缓存未命中,这可能是一个很大的节省。缺点是这种优化增加了代码复杂性(例如,如果长度不能被 4 整除,则在末尾附加 for 循环来完成剩余 len % 4 项的循环),当然,这是一种依赖于体系结构的优化其改进幅度将因硬件/编译器/等而异......

尽管如此,与大多数优化相比,它仍然很容易遵循,并且无论架构如何,都可能会导致某种性能的提高,因此将其扔在那里并希望得到最好的结果的风险很低。由于 OpenCV 是一个得到良好支持的代码块,我确信有人对这些代码块进行了检测,并发现它们非常值得 - 正如您自己所做的那样。