2017-09-03 104 views
0

我自己的實現咬我回來試圖優化與SSE4以下時:SSE4內存差別位置比較

std::distance(byteptr, std::mismatch(byteptr, ptr + lenght, dataptr).first) 

這比較byteptr和數據,並返回其中字節不匹配的索引。 我真的需要原始速度,因爲我正在處理這麼多的內存,RAM速度已經是一個瓶頸。在SSE4上獲取和比較16個字節會提供一個速度提升,因爲在時間上比較16個字節更快。

這是我目前的代碼,我無法工作。 它使用GCC上證所內部函數,需要SSE4.2:

// define SIMD 128-bit type of bytes. 
typedef char v128i __attribute__ ((vector_size(16))); 
// mask of four low bits set. 
const uintptr_t aligned_16_imask = (uintptr_t)15; 
// mask of four low bits unset. 
const uintptr_t aligned_16_mask = ~aligned_16_imask; 

inline unsigned int cmp_16b_sse4(v128i *a, v128i *b) { 
    return __builtin_ia32_pcmpistri128(__builtin_ia32_lddqu((char*)a), *b, 0x18); 
} 

size_t memcmp_pos(const char * ptr1, const char * ptr2, size_t lenght) 
{ 
    size_t nro = 0; 
    size_t cmpsz; 
    size_t alignlen = lenght & aligned_16_mask; 
    // process 16-bytes at time. 
    while(nro < alignlen) { 
     cmpsz = cmp_16b_sse4((v128i*)ptr1, (v128i*)ptr2); 
     ptr1 += cmpsz; 
     ptr2 += cmpsz; 
     nro += cmpsz; 
     // if compare failed return now. 
     if(cmpsz < 16) 
      return nro; 
     if(cmpsz != 16) 
      break; 
    } 
    // process remainder 15 bytes: 
    while(*ptr1 == *ptr2 && nro < lenght) { 
     ++nro; 
     ++ptr1; 
     ++ptr2; 
    } 
    return nro; 
} 

當測試它工作的時間,但在某些情況下,失敗最上面的功能。

+0

「失敗」是什麼意思?崩潰,誤報/否定......? – zx485

+0

上面的SSE代碼產生不同於std :: mismatch的結果。 – JATothrim

+2

我發現我做錯了:代碼應該使用'pcmpestri'來代替,因爲'pcmpistri'實際上試圖處理空字節。我的輸入數據本質上是非結構化的,所以這打破了代碼。 – JATothrim

回答

2

pcmpistri的一個已知問題是它總是讀取完整的16個字節 - 甚至超過變量的末尾。這成爲頁面邊界上分配給未分配存儲器的邊界上的問題。見here (scroll down to "Renat Saifutdinov")

即使支持未對齊的讀取,也可以通過僅使用對齊的源讀取來避免這種情況,see this SO answer

這可能是您的代碼失敗的原因之一。

+0

我認爲代碼不會遇到這些問題。對於每個循環的16字節,我有'lenght&aligned_16_mask',它將第一個循環中要處理的字節數修改爲16的倍數。 – JATothrim