Maison > développement back-end > C++ > Comment puis-je convertir efficacement entre des flottants double précision et des entiers 64 bits à l'aide des instructions SSE/AVX ?

Comment puis-je convertir efficacement entre des flottants double précision et des entiers 64 bits à l'aide des instructions SSE/AVX ?

Barbara Streisand
Libérer: 2024-12-08 03:02:15
original
563 Les gens l'ont consulté

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

Conversions efficaces Double/int64 avec SSE/AVX

SSE2 fournit des éléments intrinsèques pour convertir des vecteurs entre des flottants simple précision et des entiers 32 bits, mais il lui manque des équivalents directs pour les entiers à virgule flottante double précision et 64 bits. AVX ne propose pas non plus ces conversions.

Méthodes de simulation des intrinsèques

1. Pour les valeurs limitées :

Si certaines limitations sont tolérées, les conversions entre doubles et int64 peuvent être effectuées avec seulement deux instructions :

  • 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))
      );
    }
    Copier après la connexion
  • 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))
      );
    }
    Copier après la connexion
  • 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));
    }
    Copier après la connexion
  • 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));
    }
    Copier après la connexion

2. Gamme complète int64 -> double :

Pour convertir la plage complète int64 en double, 5 instructions sont nécessaires pour uint64_t et 6 instructions pour int64_t :

  • 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));
    }
    Copier après la connexion
  • 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));
    }
    Copier après la connexion

AVX512

AVX512 offre des conversions directes vers/depuis des entiers 64 bits, signés et non signés signé. Ces conversions sont effectuées à l'aide d'intrinsèques tels que _mm512_cvtpd_epi64 et _mm256_cvtpd_epi64.

Veuillez noter que ces solutions ne sont pas fournies sous forme de code complet. Le lecteur est invité à les compléter et à les optimiser si nécessaire pour les adapter à son contexte spécifique.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal