Coûts des recherches par rapport aux calculs

12

Je souhaite configurer des calculs pour vérifier si un critère de distance est satisfait: c'est-à-dire que la distance entre un vecteur et un vecteur d'anthère doit être inférieure à une valeur . Mes données sont partitionnées selon une grille orthogonale de coordonnées. Étant donné que ma coupure est plus petite que la distance entre les extrémités des coordonnées du plus proche voisin, j'aimerais ajouter une variable "octant" pour vérifier si les choses sont correctement configurées:x j r m a xxixjrmax

if octant[j] in allowed_list continue

comme un "court-circuit"

if dist(x[i], x[j]) < r_max

Ma question est: quelle est l'efficacité des recherches et des comparaisons booléennes par rapport aux opérations en virgule flottante? Cela vaut-il la peine de le faire sur les architectures modernes?

aeismail
la source
3
Seriez-vous prêt à connecter votre code et à le tester? Je pense que la réponse standard à la plupart de ces "vaut mieux le coder (dans un sens) ou (d'une autre manière)?" types de questions est "Essayez-le et comparez-le."
Geoff Oxberry
1
Juste mes 2 cents. Comme Geoff l'a écrit, ce genre de conseils est ce que j'ai toujours reçu lorsque je posais des questions similaires sur stackoverflow, concernant le code C ++: codez tout d'abord, organisez le code de manière à ce que je reste modulaire et réutilisable, et seulement ensuite commencez le refactoring. Il existe une règle 80-20: le logiciel passe 80% du temps sur 20% du code. Attendez que la structure soit en place, puis changez, testez, changez, testez ...
tmaric
@GeoffOxberry: Ma question n'est pas si spécifique: je veux juste savoir s'il y a un avantage matériel ou compilateur à faire une vérification booléenne par rapport à une opération à virgule flottante.
aeismail
3
Mais votre question est trop générale. Personne ne peut le dire sans avoir vu de code concret. Il y a une règle d'or qui dit que même les meilleurs programmeurs ne peuvent pas dire où se trouvent les goulots d'étranglement de leur code sans profilage. J'ai passé mes 25 dernières années à programmer et je sais que c'est vrai pour moi.
Wolfgang Bangerth

Réponses:

15

Ma règle générale est que si vous pouvez calculer une certaine quantité efficacement (bonne utilisation du FPU) en moins de 50 flops par valeur de double précision, il vaut mieux recalculer que stocker. La tendance, qui est constante depuis des décennies, est que la capacité en virgule flottante s'améliore plus rapidement que les performances de la mémoire, et ne risque pas de fléchir en raison des contraintes physiques et des besoins énergétiques de la mémoire rapide. La valeur de 50 est de la bonne ampleur pour toutes les plates-formes informatiques populaires (Intel / AMD, Blue Gene et GPU).

Estimation approximative des coûts par cœur

[directives pour les machines basées sur Intel et AMD 2011/2012]

  • 0.05 ns: temps pour effectuer une opération à virgule flottante double précision dans le cadre d'un code vectorisé sans dépendances de données et multiplication / ajout entrelacée
  • 0.2 ns: temps pour effectuer une opération à virgule flottante non vectorisée sans vectorisation ni dépendances de données
  • 0.4 ns: temps pour effectuer une opération à virgule flottante non vectorisée sans vectorisation ni dépendances de données, mais sans multiplication / addition entrelacée (1 cycle d'horloge)
  • 0,80.4 à ns: latence pour référencer le cache L10.8
  • 2 ns: latence d'une opération en virgule flottante (vectorisée ou non)
  • 53 à ns: il est temps de charger une valeur de double précision à partir de la mémoire dans le cadre d'un flux parfaitement prérécupéré et pleinement utilisé5
  • 53 à ns: appel de fonction indirecte (méthode virtuelle ou pointeur de fonction, sans pression de registre)5
  • 5 ns: mauvaise prévision de branche conditionnelle
  • 84 à ns: temps pour une division (vectorisé ou non, ne peut pas s'exécuter simultanément avec d'autres instructions)8
  • 12 ns: échec de cache L1 satisfait de L2 local
  • 12 ns: instruction atomique de comparaison et d'échange ou d'extraction et d'ajout dans le meilleur des cas
  • 5030 - ns: échec du cache d'écriture L1 ou instruction atomique dans laquelle la ligne de cache est disponible localement, mais le noyau actuel doit obtenir un accès exclusif50
  • 100 ns: échec du cache ou instruction atomique satisfaite depuis le socket ou la mémoire
  • 1 μ103 ns ( s): latence du réseau matériel pour un réseau de fantaisie1 μ
  • 10 μ104 ns ( s): échange de voisins à faibles données lorsque bien mappé au réseau10 μ
  • 106 ns (1 ms): temps (par processus) pour créer un fichier sur un système de fichiers parallèle
  • 2106 ns (2 ms): petites données MPI_Allreduce(par exemple une norme ou un produit scalaire) sur une grande machine
  • 107 ns (10 ms): recherche de disque local
  • 5108 ns (500 ms): temps de réécrire toute la mémoire disponible
  • 1.81012 ns (0,5 heure): temps pour vérifier l'état de la machine entière sur le disque

Lectures complémentaires

Jed Brown
la source
J'ai trouvé ces informations vraiment utiles. Au fait, où avez-vous obtenu ces données? Je cherche des références à citer.
Eldila