Maison >développement back-end >C++ >Pourquoi le remplacement d'un compteur de boucles 32 bits par un compteur 64 bits entraîne-t-il une dégradation des performances par « _mm_popcnt_u64 » sur les processeurs Intel ?

Pourquoi le remplacement d'un compteur de boucles 32 bits par un compteur 64 bits entraîne-t-il une dégradation des performances par « _mm_popcnt_u64 » sur les processeurs Intel ?

Patricia Arquette
Patricia Arquetteoriginal
2024-12-03 15:04:10798parcourir

Why Does Replacing a 32-bit Loop Counter with 64-bit Cause Performance Degradation with `_mm_popcnt_u64` on Intel CPUs?

Le remplacement d'un compteur de boucle 32 bits par 64 bits introduit des écarts de performances fous avec mm_popcnt_u64 sur les processeurs Intel

Résumé

L'article étudie un écart de performances rencontré lors du remplacement d'un compteur de boucle 32 bits par un Compteur 64 bits dans une boucle critique en termes de performances utilisant l'intrinsèque _mm_popcnt_u64. Le problème a entraîné une baisse significative des performances des processeurs Intel, entraînant des vitesses d'exécution différentes. L'auteur explore les raisons de ce comportement et propose des solutions potentielles.

Détails

Le code en question implique une boucle qui parcourt un tableau de données et effectue un popcount opération à l’aide de l’instruction intrinsèque x86. La variable du compteur de boucles était initialement un entier non signé, mais son remplacement par un entier non signé de 64 bits (uint64_t) a entraîné une baisse de performances d'environ 50 %.

Pour en rechercher la cause, l'auteur a compilé le code avec divers indicateurs d'optimisation et analysé le code assembleur résultant. Ils ont observé que des assemblys différents étaient générés pour les versions 32 bits et 64 bits, ce qui les a amenés à soupçonner un bug du compilateur.

Cependant, après avoir testé le code avec différents compilateurs, l'auteur a conclu que le problème ne venait pas causé par un bug du compilateur mais plutôt par une fausse dépendance de données dans le matériel. L'instruction _mm_popcnt_u64, lorsqu'elle est utilisée sur les processeurs Intel Sandy/Ivy Bridge et Haswell, présente une fausse dépendance sur le registre de destination, où l'instruction attend que la destination soit prête avant de s'exécuter. Cette fausse dépendance peut se propager à travers les itérations de boucle, empêchant le processeur de paralléliser différentes itérations et entraînant une perte de performances.

L'auteur présente des tests d'assemblage en ligne qui démontrent les différences de performances en isolant l'opération popcount et en brisant la fausse dépendance. chaîne. Ces tests montrent que la fausse dépendance a un impact significatif sur les performances, entraînant une réduction de vitesse de 18,6195 Go/s à 8,49272 Go/s.

L'article souligne également que le problème affecte les processeurs Intel, tandis que les processeurs AMD ne semble pas avoir ce faux dépendance.

Solutions

Pour atténuer ce problème de performances, l'auteur suggère plusieurs solutions :

  • Utilisez plutôt un compteur de boucles 32 bits d'un compteur de 64 bits pour cette boucle spécifique.
  • Si l'utilisation d'un compteur de boucle de 64 bits est nécessaire, rompez la fausse dépendance chaîne en mettant explicitement à zéro le registre de destination avant de l'utiliser dans l'opération popcount.
  • Utilisez un compilateur qui est conscient de cette fausse dépendance et génère du code pour la compenser.

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