2014-07-24 8 views
3

AVX는 부동 소수점 데이터 유형 __m256 및 __m256d 및/또는와 같은 비트 논리 연산을 허용합니다.avx 부동 소수점 논리 연산의 이유는 무엇입니까?

그러나 C++에서는 float 및 double에 대한 비트 연산을 허용하지 않습니다. 맞다면 컴파일러가 IEEE754를 사용할 지 여부와 상관없이 플로트의 내부 표현에 대한 보장이 없으므로 프로그래머는 플로트 비트가 어떻게 보이는지에 대해 확신 할 수 없습니다. -1의 표현이 0xffffffff를 그대로 대신

있는 동안 나는 출력이

1,0,0,4,0,6,0,0 

것으로 예상, IEEE754를 사용한다고 가정

#include <immintrin.h> 
#include <iostream> 
#include <limits> 
#include <cassert> 

int main() { 

    float x[8] = {1,2,3,4,5,6,7,8}; 
    float mask[8] = {-1,0,0,-1,0,-1,0,0}; 
    float x_masked[8]; 

    assert(std::numeric_limits<float>::is_iec559); 

    __m256 x_ = _mm256_load_ps(x); 
    __m256 mask_ = _mm256_load_ps(mask); 

    __m256 x_masked_ = _mm256_and_ps(x_,mask_); 

    _mm256_store_ps(x_masked,x_masked_); 

    for(int i = 0; i < 8; i++) 
     std::cout << x_masked[i] << " "; 

    return 0; 
} 

:

이 예제를 고려

1 0 0 1.17549e-38 0 1.17549e-38 0 0 

따라서 내부 표현에 대한 내 가정은 틀렸을 수도 있습니다. 어리석은 실수).

그래서 질문은 : 논리 부동 소수점을 사용하고 결과가 의미가 있다는 사실에 대해 안전 할 수있는 방법이 있습니까?

+5

IEEE-414에서 -1은 0xffffffff가 아니며 0xbf800000입니다. – genisage

+1

@ genisage와 비교하면 '_mm256_cmp_ps (x, y, 1)'-1 = 0xffffffff가 아닌 0xbf800000을 반환합니다. 부동 소수점 AVX 비트 연산자는 정수형 대신 부동 소수점 실행 uni에서 작동한다는 점을 제외하면 정수형 AVX 연산자와 동일하게 작동합니다. –

+0

C++에서 float에 대해 비트 연산자를 사용할 수 있습니다. 내 대답을 보라. x86-64 코드의 모든 부동 소수점 연산이 IEEE754를 사용한다는 것은 꽤 좋은 가정입니다. –

답변

7

AVX intrinsics를 사용한다면, AVX가하는 일이기 때문에 IEEE754 플로트를 사용하고 있다는 것을 알 수 있습니다. SSE4.1의 우리가 blendvps을 가지고 있지만, 옌스 '대답으로, 의미를

  • 선택하는 수레와 그 친척에

    비트 단위 작업의 일부

    는해야 할 일이 하나 개의 명령어
  • 을에 절대치
  • 부정 (-0와 XOR)
  • 전송 기호
  • 지수를 추출 (드문) (부호를 얻어, 마스크 테이블)

주로 부호를 조작하거나 전체 수레를 선택적으로 제로화하기위한 것입니다. 지수 또는 significand의 개별 비트를 사용하는 것은 아닙니다.하지만 할 수는 있지만 거의 유용하지는 않습니다.

+0

좋은 답변입니다. 지금까지 SSE2와 비교했을 때 avx를 거의 사용하지 못했지만, avx를 사용하는 이유는 분명히 blendvps 작업입니다. –

+0

AVX2 정수 연산을 사용하여 부동 소수점 값에 대해 이러한 연산을 모두 수행 할 수 있습니다. 문제는'mm256_and_si256'을 사용할 수 있었을 때'_mm256_and_ps'가 필요한 이유입니다. –

+1

@ Zboson 어쩌면. 그래도 그 질문이 내게 어떻게 읽히는지는 아닙니다. 제목은 물어 보려는 것처럼 보였지만 질문의 본문은 처음에는 수렁에 대한 비트 연산이 어떻게 의미가 있는지와 관련이있는 것처럼 보였습니다. – harold

2

프로그래머는 단 정밀도 부동 소수점이 어떻게 표현되는지 완벽하게 확신 할 수 있습니다. 기능이 어떻게 구현되는지는 또 다른 이야기입니다. 나는 IEEE-754에 부합하는 반 정밀도 플로트를 구현하기 위해 비트 연산을 사용했다. 또한 2003 년에 IBM이 특허를 제출하기 전에 지사 제거 작업을 사용했습니다.

static inline __m128 _mm_sel_ps(__m128 a, __m128 b, __m128 mask) { 
    b = _mm_and_ps(b, mask); 
    a = _mm_andnot_ps(mask, a); 
    return _mm_or_ps(a, b); 
} 

이 예제는 SSE2를 사용하여 부동 소수점 분기를 제거하는 방법을 보여줍니다. AVX를 사용하여 동일한 결과를 얻을 수 있습니다. 스칼라를 사용하여 브랜치를 제거하려는 경우 (동일한 기술) 컨텍스트 전환으로 인해 성능이 저하되지 않습니다 (x86에 적용 - fpsel 연산이있는 ARM에는 적용되지 않음)

4

이유는 실행 단위 도메인간에 전환하는 데 불이익이있을 수 있기 때문입니다. bypass-delays-when-switching-execution-unit-domainswhy-do-some-sse-mov-instructions-specify-that-they-move-floating-point-values. 이 경우 부동 소수점 AVX 실행 유닛에서 정수 실행 AVX 유닛으로 전환합니다.의 당신은 AVX는 xy를 등록 부동 소수점 비교하고 싶은 말은하자 예를 들어

z = _mm256_cmp_ps(x, y, 1); 

AVX 레지스터 z는 부울 정수 값을 포함합니다 (0 또는 -1)하는 할 수 있습니다 다음 논리 AND _mm256_and_ps를 사용하거나 원한다면 _mm256_and_si256으로. 그러나 _mm256_and_ps은 동일한 실행 장치에 있으며 _mm256_and_si256 스위치 장치는 우회 지연을 초래할 수 있습니다.

편집 : C++의 부동 소수점 연산자에 관해서는 확실히 가능하며 때로는 유용합니다. 다음은 간단한 예입니다.

union { 
    float f; 
    int i; 
} u; 
u.i ^= 0x80000000; // flip sign bit of u.f 
u.i &= 0x7FFFFFFF; // set sign bit to zero //take absolute value