2016-12-26 17 views
6

SSE 유형간에 변환을 구현하고 있으며 SSE4 이전 대상에 대해 int8-> int64 확장 변환을 구현하는 것이 번거롭다는 것을 발견했습니다.SSE로 int8/int64 변환을 효율적으로 수행하는 방법은 무엇입니까?

inline __m128i convert_i8_i64(__m128i a) 
{ 
#ifdef __SSE4_1__ 
    return _mm_cvtepi8_epi64(a); 
#else 
    a = _mm_unpacklo_epi8(a, a); 
    a = _mm_unpacklo_epi16(a, a); 
    a = _mm_unpacklo_epi32(a, a); 
    return _mm_srai_epi64(a, 56); // missing instrinsic! 
#endif 
} 

그러나 AVX-512은,이 시점에서 옵션이 될 때까지 _mm_srai_epi64부터 존재하지 않습니다 :

똑 바른 구현 될 _mm_srai_epi64, 또는

  • 을 구현

    • convert_i8_i64을 다른 방식으로 구현합니다.

    어느 것이 가장 효율적인 솔루션인지 확실하지 않습니다. 어떤 생각?

  • 답변

    4

    여기서 언 패킹 내장 함수는 재미있는 방식으로 사용됩니다. 예상대로 서명 확장을 추가하는 대신 데이터를 "복제"합니다. 예를 들어, 첫 번째 반복 전에 당신이 ab 16 비트를 변환하는 경우

    x x x x x x x x x x x x x x a b 
    

    을 다음 당신의 레지스터에있는, 당신이 얻을해야합니다

    x x x x x x x x x x x x A a B b 
    
    다음

    AB이 기호 -이다 ab의 확장자, 즉 둘 다 0 또는 -1입니다. 대신이의

    , 당신의 코드는

    x x x x x x x x x x x x a a b b 
    

    을 제공합니다 그리고 당신은 바로 이동하여 적절한 결과로 변환합니다.

    그러나 "언팩"내장 함수에서 동일한 피연산자를 두 번 사용해야 할 의무는 없습니다.

    x x x x x x x x x x x x x x a b 
    x x x x x x x x x x x x x x A B 
    

    즉 : 당신이 "압축 해제"다음 두 레지스터 경우 원하는 결과를 얻을 수

    a = _mm_unpacklo_epi8(a, _mm_srai_epi8(a, 8)); 
    

    (있는 경우 그 _mm_srai_epi8 고유 실제로 존재)


    당신이 할 수있는 전환의 마지막 단계에서 같은 생각을 적용하십시오. 다음 두 레지스터 "압축 해제"할 :

    x x x x x x x x A A A a B B B b 
    x x x x x x x x A A A A B B B B 
    

    그들을 얻으려면, 마우스 오른쪽 시프트 32 비트 데이터 : 그래서

    _mm_srai_epi32(a, 24) 
    _mm_srai_epi32(a, 32) 
    

    마지막이다 "압축"

    _mm_unpacklo_epi32(_mm_srai_epi32(a, 24), _mm_srai_epi32(a, 32)); 
    
    2

    SSSE3을 사용하면 대부분의 포장을 피하기 위해 pshufb을 사용할 수 있습니다.아나톨리의 a/A 표기 사용 : SSSE3없이

    ;; input in xmm0    ;; x x x x x x x x | x x x x x x a b 
    pshufb xmm0, [low_to_upper] ;; a 0 0 0 0 0 0 0 | b 0 0 0 0 0 0 0 
    psrad xmm0, 24    ;; A A A a 0 0 0 0 | B B B b 0 0 0 0 
    pshufb xmm0, [bcast_signextend]; A A A A A A A a | B B B B B B B b 
    

    을, 당신이 PSHUFLW, PSHUFD 뭔가를 할 수있을 것 같아요, 대신 PUNPCK 단계의 일부 어쩌면 POR. 하지만 Core2 나 다른 느린 셔플 CPU를 쓰지 않는 한, 언팩보다 실제로 더 좋은 생각이 없습니다. pshuflwpunpcklbw보다 빠릅니다.