2017-01-12 11 views
3

8 x 16 비트 부호없는 int 요소를 포함하는 최대 두 벡터를 찾고 싶습니다. SSE2 내장 함수 - 부호없는 두 짧은 벡터의 최대 값을 찾습니다

__m128i vi_A= _mm_loadu_si128(reinterpret_cast<const __m128i*>(&pSrc[0])); // 8 16-Bit Elements 
__m128i vi_B= _mm_loadu_si128(reinterpret_cast<const __m128i*>(&pSrc1[0])); // 8 16-Bit Elements 
__m128i vi_Max = _mm_max_epi16(vi_A,vi_B); //<-- Error 

그러나이 _mm_max_epi16는 서명 INT 비교이며,이 오버 플로우가 발생합니다. 그래서 나는

vi_Max = _mm_max_epu16(vi_A,vi_B); 

고유 SSE4.1을 사용하여 그것의 서명되지 않은 버전을 사용하려고하지만은 SSE4.1의 내장 함수를 사용하도록 허용하고 있지 않다. 그렇다면이 요소들의 최대 값을 찾는 효율적인 방법은 무엇입니까?

답변

4

하나는 0x8000으로하여 상기 입력 값을 상쇄하고 추가 이것은 다시 그 결과로 예를 상쇄하는 일의 (다소 비효율적) 방법 : GCC의

#ifndef __SSE4_1__ 
inline __m128i _mm_max_epu16(const __m128i v0, const __m128i v1) 
{ 
    return _mm_add_epi16(
       _mm_max_epi16(
        _mm_sub_epi16(v0, _mm_set1_epi16(0x8000)), 
        _mm_sub_epi16(v1, _mm_set1_epi16(0x8000))), 
       _mm_set1_epi16(0x8000)); 
} 
#endif 

또는이 하나 개의로드 명령의 생성 연타 상수 및 4 개의 산술 명령 당신이 의도에 틀림없이 명확하다, _mm_add_epi16/_mm_sub_epi16의 장소에서 _mm_xor_si128을 사용할 수 있으며, 목표 아키텍처에 더 나은 성능을 제공 할 수 있음을


참고 :

#ifndef __SSE4_1__ 
inline __m128i _mm_max_epu16(const __m128i v0, const __m128i v1) 
{ 
    return _mm_xor_si128(
       _mm_max_epi16(
        _mm_xor_si128(v0, _mm_set1_epi16(0x8000)), 
        _mm_xor_si128(v1, _mm_set1_epi16(0x8000))), 
       _mm_set1_epi16(0x8000)); 
} 
#endif 
+1

와우 귀하의 빠른 응답 주셔서 감사합니다! 그것은 매력처럼 일했습니다! –

+0

XORing은 매우 빠르지 만 더 중요한 것은 오버 플로우의 가능성을 제거합니다. –

+1

@CodyGray 어떤 오버플로가 발생합니까? 0x8000을 가진 16 비트 int를 더하기/빼기/xoring하는 것은 완전히 똑같습니다. 가장자리 케이스가 없습니다. – harold