2017-09-03 4 views
0

내 자신의 구현을 비교합니다. RAM 속도가 이미 병목 현상이 너무 많은 메모리를 처리하고 있기 때문에 원시 속도가 실제로 필요합니다. SSE4와 함께 16 바이트를 가져오고 비교하면 속도가 16 바이트보다 빠르기 때문에 속도가 향상됩니다.SSE4 메모리는 날 다시 물어 차이의 위치에

다음은 현재 작동하지 않는 코드입니다. 그것은 GCC SSE의 내장 함수를 사용하고 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'가 실제로 null 바이트를 처리하려고하기 때문에 대신'pcmpestri'를 사용해야했습니다. 입력 데이터는 본질적으로 구조화되지 않은 비트이므로 코드가 파기됩니다. – JATothrim

답변

2

pcmpistri의 한 가지 알려진 문제점은 변수의 끝을 넘어서서 항상 전체 16 바이트를 읽는다는 것입니다. 이는 할당되지 않은 메모리에 할당 된 경계에서 페이지 경계에서 문제가됩니다. here (scroll down to "Renat Saifutdinov")을 참조하십시오.

정렬되지 않은 읽기가 지원되는 경우에도 소스의 정렬 된 읽기 인 see this SO answer을 사용하여 피할 수 있습니다.

이것은 코드가 실패 할 가능성 중 하나 일 수 있습니다.

+0

코드가 이러한 문제를 겪지 않는다고 생각합니다. 라운드 당 16 바이트 루프의 경우 첫 번째 루프에서 처리 할 바이트 수를 16의 배수로 반올림하는'길이 및 정렬 _16_ 마스크 '가 있습니다. – JATothrim