>백엔드 개발 >C++ >SSE/AVX 명령어를 사용하여 배정밀도 부동 소수점과 64비트 정수 간에 효율적으로 변환하려면 어떻게 해야 합니까?

SSE/AVX 명령어를 사용하여 배정밀도 부동 소수점과 64비트 정수 간에 효율적으로 변환하려면 어떻게 해야 합니까?

Barbara Streisand
Barbara Streisand원래의
2024-12-08 03:02:15466검색

How Can I Efficiently Convert Between Double-Precision Floats and 64-bit Integers Using SSE/AVX Instructions?

SSE/AVX를 사용한 효율적인 Double/int64 변환

SSE2는 단정밀도 부동 소수점과 32비트 정수 간의 벡터 변환을 위한 내장 함수를 제공합니다. 그러나 배정밀도 부동 소수점 및 64비트 정수에 대한 직접적인 대응 요소는 부족합니다. AVX는 이러한 변환도 제공하지 않습니다.

내장 함수 시뮬레이션 방법

1. 제한된 값의 경우:

특정 제한이 허용되는 경우 두 개의 문만 사용하여 double과 int64 간의 변환을 수행할 수 있습니다:

  • double -> ; uint64_t:

    __m128i double_to_uint64(__m128d x){
      x = _mm_add_pd(x, _mm_set1_pd(0x0010000000000000));
      return _mm_xor_si128(
          _mm_castpd_si128(x),
          _mm_castpd_si128(_mm_set1_pd(0x0010000000000000))
      );
    }
  • 더블 -> int64_t:

    __m128i double_to_int64(__m128d x){
      x = _mm_add_pd(x, _mm_set1_pd(0x0018000000000000));
      return _mm_sub_epi64(
          _mm_castpd_si128(x),
          _mm_castpd_si128(_mm_set1_pd(0x0018000000000000))
      );
    }
  • uint64_t -> 더블:

    __m128d uint64_to_double(__m128i x){
      x = _mm_or_si128(x, _mm_castpd_si128(_mm_set1_pd(0x0010000000000000)));
      return _mm_sub_pd(_mm_castsi128_pd(x), _mm_set1_pd(0x0010000000000000));
    }
  • int64_t -> 더블:

    __m128d int64_to_double(__m128i x){
      x = _mm_add_epi64(x, _mm_castpd_si128(_mm_set1_pd(0x0018000000000000)));
      return _mm_sub_pd(_mm_castsi128_pd(x), _mm_set1_pd(0x0018000000000000));
    }

2. 전체 범위 int64 -> double:

전체 범위 int64를 double로 변환하려면 uint64_t에 5개의 명령어가 필요하고 int64_t에 6개의 명령어가 필요합니다.

  • uint64_t -> ; 더블:

    __m128d uint64_to_double_full(__m128i x){
      __m128i xH = _mm_srli_epi64(x, 32);
      xH = _mm_or_si128(xH, _mm_castpd_si128(_mm_set1_pd(19342813113834066795298816.)));          //  2^84
      __m128i xL = _mm_blend_epi16(x, _mm_castpd_si128(_mm_set1_pd(0x0010000000000000)), 0xcc);   //  2^52
      __m128d f = _mm_sub_pd(_mm_castsi128_pd(xH), _mm_set1_pd(19342813118337666422669312.));     //  2^84 + 2^52
      return _mm_add_pd(f, _mm_castsi128_pd(xL));
    }
  • int64_t -> double:

    __m128d int64_to_double_full(__m128i x){
      __m128i xH = _mm_srai_epi32(x, 16);
      xH = _mm_blend_epi16(xH, _mm_setzero_si128(), 0x33);
      xH = _mm_add_epi64(xH, _mm_castpd_si128(_mm_set1_pd(442721857769029238784.)));              //  3*2^67
      __m128i xL = _mm_blend_epi16(x, _mm_castpd_si128(_mm_set1_pd(0x0010000000000000)), 0x88);   //  2^52
      __m128d f = _mm_sub_pd(_mm_castsi128_pd(xH), _mm_set1_pd(442726361368656609280.));          //  3*2^67 + 2^52
      return _mm_add_pd(f, _mm_castsi128_pd(xL));
    }

AVX512

AVX512는 부호 있는 정수와 부호 없는 정수 모두에서 64비트 정수로의 직접 변환을 제공합니다. 서명했습니다. 이러한 변환은 _mm512_cvtpd_epi64 및 _mm256_cvtpd_epi64와 같은 내장 함수를 사용하여 수행됩니다.

이러한 솔루션은 완전한 코드로 제공되지 않습니다. 독자는 특정 상황에 맞게 내용을 완성하고 필요에 따라 최적화해야 합니다.

위 내용은 SSE/AVX 명령어를 사용하여 배정밀도 부동 소수점과 64비트 정수 간에 효율적으로 변환하려면 어떻게 해야 합니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.