2017-09-03 103 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