ホームページ > バックエンド開発 > C++ > SSE/AVX 命令を使用して倍精度浮動小数点と 64 ビット整数の間で効率的に変換するにはどうすればよいですか?

SSE/AVX 命令を使用して倍精度浮動小数点と 64 ビット整数の間で効率的に変換するにはどうすればよいですか?

Barbara Streisand
リリース: 2024-12-08 03:02:15
オリジナル
467 人が閲覧しました

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 の間の変換は 2 つのステートメントだけで実行できます:

  • 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))
      );
    }
    ログイン後にコピー
  • double -> 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 -> double:

    __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 -> double:

    __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 -> ; double:

    __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 中国語 Web サイトの他の関連記事を参照してください。

ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
著者別の最新記事
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート