2011-11-03 3 views
11

__m128i 변수가 SSE-2 이전 프로세서에서 0이 아닌 값을 가지면 어떻게 테스트합니까?__m128i 변수는 0입니까?

+0

0이 아닌 비트 또는 8/16/32 비트 정수 요소를 의미합니까? –

+0

@BrettHale : 모두 0인지 테스트하려고합니다. – Mehrdad

답변

11

SSE2에서 당신은 할 수 있습니다 : 제로 다음, 그래서 int 대응하는 각각의 사용자의 비트 오프셋 (offset)는 0에있을 것, 각 바이트 4를 마스크를 돌려 대

__m128i zero = _mm_setzero_si128(); 
if(_mm_movemask_epi8(_mm_cmpeq_epi32(x,zero)) == 0xFFFF) 
{ 
    //the code... 
} 

이 네 INT의의를 시험 할 것이다, 8 & 12,하지만 위의 테스트는 비트가 설정되면 잡아낼 수 있습니다. 마스크를 유지하면 필요한 경우 더 세밀한 조각으로 직접 작업 할 수 있습니다.

+2

+1, 내 것이 낫다. :) 나는 당신이 그것을 할 수 있다는 것을 몰랐기 때문에 나는 movemask 명령어를 사용한 적이 없다. XD – Mysticial

+0

+1 가장 컴팩트 한 솔루션은 내가 봤어, 고마워! – Mehrdad

+3

그렇지 않으면 훌륭한 대답에 버그가 있습니다. 모든 0을 확인하는 경우'if (_mm_movemask_epi8 (_mm_cmpeq_epi32 (x, zero)) == 0xFFFF)'여야합니다. 왜냐하면'_mm_cmpeq_epi32'가 int를 0이 아닌 모든 0이 아닌 모든 1로 설정하고,'_mm_movemask_epi8'가 인수의 각 바이트의 최상위 비트를 기준으로 처음 16 비트를 설정하기 때문입니다. 저자가 대답을 편집 할 수 있기를 바랍니다. 시도했지만 거부되었습니다. – FarmerBob

1

완벽을 기하기 위해 SSE4에서는 _mm_testz_si128을 사용할 수 있습니다. 모든 비트 제로를 경우이 사실 것을

const bool isAllZero = _mm_testz_si128(a,a); 

참고.

+1

이것은 실제로 약간 더 빠르며 테스트를 위해 모두 0 인 레지스터가 필요하지 않습니다. 'ptest' /'jz'는 2 + 1uop입니다 (매크로 퓨즈는 아닙니다). 'pcmpeq' (1uop) /'pmovmsk' (1uop) /'와 0xffff' (1uop) /'cmp 0xffff/je' (1uop)입니다. 다른 모든 경우 (* 모든 * 0 요소가 아닌 * 모든 0 요소)를 테스트 중이면 현재 Intel 및 AMD CPU에서 거의 동일한 성능을 보입니다.'ptest' /'jnz' (3 uops) vs 'pcmpeq' /'pmovmsk' /'test/jnz' (3 uops). –

+0

@PeterCordes이 경우 레지스터가 모두 1로 설정되고'_mm_testc_si128'을 사용하면 어떨까요? 'const bool atLeastOneZero = _mm_testc_si128 (a, allOnes) '와 같은 것. – Antonio

+1

다시 말하지만,'ptest'는 약간 더 빠릅니다. 'ptest'를 사용하지 않고 실행하려면 all-ones vector에 대해'pcmpeq'를 실행 한 다음 똑같은 순서로 진행하여 모든 요소가 일치하는지 확인하십시오. 'pcmpeq'로 all-zero 또는 all-one을 체크하는 것은 다른 패턴에 대해 ==를 체크하는 것과 동일하다. 단, 상수는 즉시 생성하는 것이 더 쉽다 ('pxor same, same' 또는'pcmpeqw same, 동일). –

관련 문제