Maison > développement back-end > C++ > Comment les instructions AVX2 et BMI2 peuvent-elles mettre en œuvre efficacement un emballage à gauche basé sur un masque ?

Comment les instructions AVX2 et BMI2 peuvent-elles mettre en œuvre efficacement un emballage à gauche basé sur un masque ?

Susan Sarandon
Libérer: 2024-12-29 19:34:11
original
242 Les gens l'ont consulté

How Can AVX2 and BMI2 Instructions Efficiently Implement Left Packing Based on a Mask?

Mise en œuvre efficace d'AVX2 pour l'emballage laissé en fonction d'un masque

Contrairement à SSE, AVX ne dispose pas d'instructions dédiées pour l'emballage laissé en fonction d'un masque. Cependant, une combinaison d'instructions AVX2 et BMI2 peut être utilisée pour réaliser cette tâche efficacement.

Utilisation d'AVX2 et BMI2

L'approche exploite l'instruction vpermps (_mm256_permutevar8x32_ps), qui effectue un brassage variable de croisement de voies, et le pdep (_pdep_u64) instruction de BMI2, qui fournit une extraction au niveau du bit.

Étapes de l'algorithme

  1. Créez une constante avec des indices condensés de 3 bits représentant la permutation souhaitée.
  2. Utilisez pdep pour extraire les indices pertinents du mask.
  3. Décompressez les index à un par octet.
  4. Convertissez les index décompressés en un masque de contrôle pour vpermps.
  5. Effectuez la lecture aléatoire des variables à l'aide de vpermps.

Détails de mise en œuvre

Le code ci-dessous fournit une implémentation dans AVX2 BMI2 :

#include <immintrin.h>

__m256 compress256(__m256 src, unsigned int mask)
{
  uint64_t expanded_mask = _pdep_u64(mask, 0x0101010101010101);  // unpack each bit to a byte
  expanded_mask *= 0xFF;    // mask |= mask<<1 | mask<<2 | ... | mask<<7;
  // ABC... -> AAAAAAAABBBBBBBBCCCCCCCC...: replicate each bit to fill its byte

  const uint64_t identity_indices = 0x0706050403020100;    // the identity shuffle for vpermps, packed to one index per byte
  uint64_t wanted_indices = _pext_u64(identity_indices, expanded_mask);

  __m128i bytevec = _mm_cvtsi64_si128(wanted_indices);
  __m256i shufmask = _mm256_cvtepu8_epi32(bytevec);

  return _mm256_permutevar8x32_ps(src, shufmask);
}
Copier après la connexion

Analyse des performances

Cette implémentation entraîne 6 uops avec une latence de 16c. Il peut potentiellement supporter un débit d'une itération tous les 4 cycles, gardant plusieurs itérations en vol.

Approches alternatives

Pour les processeurs AMD antérieurs à Zen 3, pext/pdep sont très lents, des approches alternatives peuvent donc être préférables. Pour les éléments de 16 bits, une approche vectorielle de 128 bits pourrait être utilisée. Pour les éléments de 8 bits, une technique différente impliquant plusieurs morceaux superposés peut être utilisée.

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!

source:php.cn
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
Derniers articles par auteur
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal