我是SSE編程新手,所以我希望有人能幫助我。我最近使用GCC SSE內在函數實現了一個函數來計算32位整數數組的總和。下面給出了我的實現代碼。大型陣列尺寸的SSE性能下降
int ssum(const int *d, unsigned int len)
{
static const unsigned int BLOCKSIZE=4;
unsigned int i,remainder;
int output;
__m128i xmm0, accumulator;
__m128i* src;
remainder = len%BLOCKSIZE;
src = (__m128i*)d;
accumulator = _mm_loadu_si128(src);
output = 0;
for(i=BLOCKSIZE;i<len-remainder;i+=BLOCKSIZE){
xmm0 = _mm_loadu_si128(++src);
accumulator = _mm_add_epi32(accumulator,xmm0);
}
accumulator = _mm_add_epi32(accumulator, _mm_srli_si128(accumulator, 8));
accumulator = _mm_add_epi32(accumulator, _mm_srli_si128(accumulator, 4));
output = _mm_cvtsi128_si32(accumulator);
for(i=len-remainder;i<len;i++){
output += d[i];
}
return output;
}
正如你可以看到,這是一個相當簡單的實現方式,其中我使用擴展XMM寄存器在一個時間求和陣列4,然後通過加入餘下的元件清理在末端。
然後,我將該SIMD實現的性能與普通的for循環進行了比較。這個實驗的結果可以在這裏找到:
正如你可以看到,相較於一個for循環,這個實現確實表現出約〜60%的加速爲輸入尺寸(指的長度陣列)高達約5M元素。然而,對於輸入大小的較大值,與for循環有關的性能會急劇下降,並且只會產生大約20%的加速。
我無法解釋這種戲劇性的下降。我或多或少地通過內存線性地步進,所以緩存未命中和頁面錯誤的影響應該對於兩種實現大致相同。我在這裏錯過了什麼?有什麼辦法可以將這條曲線弄平嗎?任何想法將不勝感激。
你使用的是什麼CPU? –
首先,你是否檢查gcc是否會自動化標量代碼?其次,你可能會受限於內存帶寬。 – EOF
正如@EOF所說,你在循環中幾乎不做任何事(一個SIMD算術指令),所以當你有大的數組時,你很可能會限制內存帶寬。 –