私はopenCVを使用してブロックマッチングを行ってきましたが、差の二乗和のコードは、次のような単純なforループと比較して非常に高速であることに気付きました。
int SSD = 0;
for(int i =0; i < arraySize; i++)
SSD += (array1[i] - array2[i] )*(array1[i] - array2[i]);
ソースコードを見て、重労働が発生する場所を確認すると、OpenCVの人々は、ループの各反復で一度に4つの2乗差分計算をforループで実行します。ブロックマッチングを行う関数は次のようになります。
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つのチャンクに分割すると、コードが高速化されるのではないかと誰かが考えているのではないかと思いました。このコードではマルチスレッドが発生していないことを付け加えておきます。