2012-04-14 63 views
5

我一直在使用OpenCV的做一些塊匹配,而且我發現它的平方差之和代碼是非常快相比,直線前進的循環是這樣的:OpenCV的總和加快

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塊?我應該補充說,在這段代碼中沒有多線程發生。

回答

4

我的猜測是,這只是unrolling the loop的一個簡單實現 - 它在循環的每次通過時節省了3次增加和3次比較,如果例如檢查len涉及緩存未命中,這可以節省很多。缺點是這種優化會增加代碼的複雜性(例如,如果長度不能被4整除,那麼最後的循環會完成剩餘的%4項的循環),當然,這是一個依賴於體系結構的優化其改進的程度會因硬件/編譯器等而異......

儘管如此,跟大多數優化相比,它很簡單,並且可能會導致某種性能提升,而不管架構如何,所以它的風險低把它扔在那裏,希望最好。由於OpenCV支持的代碼如此之好,我相信有人安裝了這些代碼塊並發現它們非常值得 - 就像你自己做的那樣。

1

有代碼的一個明顯的優化,即:

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

我有點對優化我的代碼。爲什麼將平方差計算分成兩行會帶來速度優勢? – ncRubert 2012-04-14 18:18:08

+0

另外,l和c在做什麼? – ncRubert 2012-04-14 18:48:03

+0

@ncRubert重點不是打破平方差計算,而是計算兩倍不同的'array1 [i] - array2 [i]'。 – Antonio 2015-10-01 12:22:52