2014-04-24 4 views
0

int 배열 [10000]을 가지고 있으며 다음 위치에서 반복하여 0이 아닌 인덱스를 찾고자합니다. 현재 내가 기본 while 루프를 사용intrinsics를 사용하여 배열에서 0이 아닌 다음을 찾습니다.

while(array[i] == 0){ 
    pos++; 
} 

내가 한 번에 제로 4의 정수를 테스트 할 수있는 내장으로 알고 있지만,의 벡터 인덱스를 나타내는 뭔가를 반환하는 방법이입니다 " 첫 번째 "0이 아닌?

+1

당신이 간단한 해결책를 시도보다는 한 번에 8의 int를 처리 할 수 ​​있습니다 : ['표준 : find'] (HTTP를 : //en.cppreference.com/w/cpp/algorithm/find)? 수백만 건의 레코드를 검색하고 싶지 않다면 복잡한 일은 없습니다. –

+0

@JoachimPileborg 저 레이턴시가 가치가 있으므로 찾고 있습니다. 나는 내가 그것을 필요로하지 않는 지에 관해 묻는 것을 괴롭히지 않을 것이다. 충고를 좋아하지만 속도가 필요하기 때문에 내장 함수에 대해 묻습니다. – user997112

+0

다음 인덱스가 아닌 0이 아닌 * 항목 *을 찾고 있다고 생각하십니까? – CiaPan

답변

3

그것은이 일을 매우 간단하지만 (배열이 이미 캐시되지 않은 경우) 당신은 아마 메모리 대역폭에 의해 제한되기 때문에 처리량 개선, 중대하지 않을 수 있습니다

int index = -1; 
for (i = 0; i < n; i += 4) 
{ 
    __m128i v = _mm_load_si128(&A[i]); 
    __m128i vcmp = _mm_cmpeq_epi32(v, _mm_setzero_si128()); 
    int mask = _mm_movemask_epi8(vcmp); 
    if (mask != 0xffff) 
    { 
     break; 
    } 
} 
if (i < n) 
{ 
    for (j = i; j < i + 4; ++j) 
    { 
     if (A[j] != 0) 
     { 
      index = j; 
      break; 
     } 
    } 
} 

이 있다고 가정합니다 배열 A 는 16 바이트 정렬이며, 크기는 n이며 4의 배수이며 int는 32 비트입니다.

특히 입력 데이터가 크고/또는 희소성이 낮은 경우 루프를 푸는 것이 도움이 될 수 있습니다. 당신이 (나중에 하 스웰과) AVX2이있는 경우

int index = -1; 
for (i = 0; i < n; i += 8) 
{ 
    __m128i v0 = _mm_load_si128(&A[i]); 
    __m128i v1 = _mm_load_si128(&A[i + 4]); 
    __m128i vcmp0 = _mm_cmpeq_epi32(v0, _mm_setzero_si128()); 
    __m128i vcmp1 = _mm_cmpeq_epi32(v1, _mm_setzero_si128()); 
    int mask0 = _mm_movemask_epi8(vcmp0); 
    int mask1 = _mm_movemask_epi8(vcmp1); 
    if ((mask0 | mask1) != 0xffff) 
    { 
     break; 
    } 
} 
if (i < n) 
{ 
    for (j = i; j < i + 8; ++j) 
    { 
     if (A[j] != 0) 
     { 
      index = j; 
      break; 
     } 
    } 
} 

당신은 4

+0

을 참조하십시오. loop와 mask는 연속 조건입니까? – user997112

+0

나는 그것이 많은 차이를 만들 것이라고 생각하지 않지만, 계속 시도해보십시오. –

+0

오, 어떻게 그런 식으로 지정했는지 AVX2가 있었으면 좋겠다 !!! – user997112