2014-02-15 33 views
0

我試圖利用由knc(Xeon Phi)提供的SIMD 512來提高使用intel intrinsics的以下C代碼的性能。然而,我的內在的嵌入代碼的運行速度比自動向量化代碼在KNC(Xeon Phi)中查找矢量數組中的數字實例

C代碼

int64_t match=0; 
int *myArray __attribute__((align(64))); 
myArray = (int*) malloc (sizeof(int)*SIZE); //SIZE is array size taken from user 
radomize(myArray); //to fill some random data 
int searchVal=24; 
#pragma vector always 
for(int i=0;i<SIZE;i++) { 
    if (myArray[i]==searchVal) match++; 
return match; 

內在嵌入代碼慢: 在下面的代碼,我第一次加載陣列,並將其與搜索鍵比較。內部函數返回使用_mm512_mask_reduce_add_epi32()減少的16位掩碼值。

register int64_t match=0; 
int *myArray __attribute__((align(64))); 
myArray = (int*) malloc (sizeof(int)*SIZE); //SIZE is array size taken from user 
const int values[16]=\ 
       { 1,1,1,1,\ 
        1,1,1,1,\ 
        1,1,1,1,\ 
        1,1,1,1,\ 
       }; 
__m512i const flag = _mm512_load_epi32((void*) values); 
__mmask16 countMask; 

__m512i searchVal = _mm512_set1_epi32(16); 
__m512i kV = _mm512_setzero_epi32(); 


for (int i=0;i<SIZE;i+=16) 
{ 
    // kV = _mm512_setzero_epi32(); 
    kV = _mm512_loadunpacklo_epi32(kV,(void*)(&myArray[i])); 
    kV = _mm512_loadunpackhi_epi32(kV,(void*)(&myArray[i + 16])); 

    countMask = _mm512_cmpeq_epi32_mask(kV, searchVal); 
    match += _mm512_mask_reduce_add_epi32(countMask,flag); 
} 
return match; 

我相信我有一些如何引入額外的週期在這段代碼,因此它正在運行緩慢相比,自動向量化代碼。與SIMD128直接返回128位寄存器中的比較值不同,SIMD512返回掩碼寄存器中的值,這增加了我的代碼的複雜性。我在這裏錯過了什麼,必須有出路才能直接比較並保持成功搜索的次數,而不是使用諸如異或操作的掩碼。

最後,請建議我使用內在函數來提高此代碼性能的方法。我相信我可以使用內在函數來榨取更多性能。對於SIMD128來說,這至少是正確的,在SIMD128中,使用內在函數使我獲得25%的性能。

+2

爲什麼使用兩個負載來填充'kV'?爲什麼不只是一個'_mm512_load_epi32'? –

回答

1

我建議如下優化:

  • 使用預取。你的代碼執行的計算量非常小,幾乎肯定會帶寬限制。 Xeon Phi僅爲L2緩存提供硬件預取功能,因此爲了獲得最佳性能,您需要手動插入預取指令。
  • 按照@PaulR的提示使用對齊的閱讀_mm512_load_epi32。使用memalign函數而不是malloc來保證數組在64個字節上真正對齊。如果您需要未對齊的指令,請使用_mm512_undefined_epi32()作爲第一個未對齊加載的源代碼,因爲它會破壞對kV(在您當前的代碼中)的依賴,並讓編譯器執行其他優化。
  • 將數組展開2或使用至少兩個線程來隱藏指令延遲。
  • 避免使用int變量作爲索引。 unsigned int,size_tssize_t是更好的選擇。
+0

使用malloc和_mm512_load_epi32時出現分段錯誤。然而,它現在使用memalign。任何關於減少我的代碼中比較和減少計算週期的建議。 – user2749262

+0

您可以嘗試用'_mm_countbits(_mm512_mask2int(countMask))'替換'_mm512_mask_reduce_add_epi32(countMask,flag)',但我懷疑它會有什麼影響。 –

+0

感謝您的建議,_mm_countbits()比使用_mm512_mask_reduce_add_epi32()方法要慢。 考慮到之前評論中的所有其他建議之後,我的代碼現在運行速度比自動矢量化代碼快50%。 我編譯的代碼如下: icc -mmic -O -std = c99 – user2749262