web-dev-qa-db-fra.com

Qu'est-ce que FLOP / s et est-ce une bonne mesure des performances?

On m'a demandé de mesurer les performances d'un programme fortran qui résout des équations différentielles sur un système multi-CPU. Mon employeur insiste pour que je mesure les FLOP/s (opérations flottantes par seconde) et que je compare les résultats avec des références ( LINPACK ) mais je ne suis pas convaincu que ce soit la façon aller, tout simplement parce que personne ne peut m'expliquer ce qu'est un FLOP.

J'ai fait des recherches sur ce qu'est exactement un FLOP et j'ai obtenu des réponses assez contradictoires. L'une des réponses les plus populaires que j'ai obtenues était "1 FLOP = un ajout et une opération de multiplication". Est-ce vrai? Si oui, encore une fois, physiquement, qu'est-ce que cela signifie exactement?

Quelle que soit la méthode que j'utilise, elle doit être évolutive. Certaines versions du code résolvent des systèmes comportant plusieurs millions d'inconnues et leur exécution prend des jours.

Quels seraient d'autres moyens efficaces de mesurer les performances dans mon cas (résumé de mon cas étant du code fortran qui effectue maintes et maintes fois des calculs arithmétiques pendant des jours sur plusieurs centaines de CPU)?

41
caglarozdag

C'est une mesure assez décente de la performance, tant que vous comprenez exactement ce qu'elle mesure.

FLOPS est, comme son nom l'indique OPÉRATIONS en virgule flottante par seconde, exactement ce qui constitue un FLOP peut varier selon le CPU. (Certains processeurs peuvent effectuer l'addition et la multiplication en une seule opération, d'autres non, par exemple). Cela signifie qu'en tant que mesure de performance, il est assez proche du matériel, ce qui signifie que 1) vous devez connaître votre matériel pour calculer l'idéal FLOPS sur l'architecture donnée, et vous devez connaître votre algorithme et votre implémentation pour déterminer le nombre d'opérations à virgule flottante qu'il comprend réellement.

Dans tous les cas, c'est un outil utile pour examiner dans quelle mesure vous utilisez le CPU. Si vous connaissez les performances maximales théoriques du processeur dans FLOPS, vous pouvez déterminer l'efficacité avec laquelle vous utilisez les unités à virgule flottante du processeur, qui sont souvent l'une des plus difficiles à utiliser efficacement. Un programme qui exécute 30% du FLOPS dont le processeur est capable, a de la place pour l'optimisation. Un programme qui fonctionne à 70% ne va probablement pas devenir beaucoup plus efficace à moins que vous ne changiez l'algorithme de base . Pour les algorithmes riches en mathématiques comme le vôtre, c'est à peu près la façon standard de mesurer les performances. Vous pouvez simplement mesurer la durée d'exécution d'un programme, mais cela varie énormément en fonction du processeur. Mais si votre programme a une utilisation du processeur de 50% (par rapport au pic FLOPS count), c'est une valeur un peu plus constante (elle variera toujours entre des architectures CPU radicalement différentes, mais elle est beaucoup plus cohérente que le temps d'exécution).

Mais savoir que "mon processeur est capable de X GFLOPS, et que je n'atteins en fait qu'un débit de, disons, 20% de cela" est très des informations précieuses dans un logiciel hautes performances. Cela signifie que quelque chose autre que les opérations en virgule flottante vous retient et empêche les unités FP de fonctionner efficacement. Et puisque les FP les unités constituent la majeure partie du travail, cela signifie que votre logiciel a un problème.

Il est facile de mesurer "Mon programme s'exécute en X minutes", et si vous pensez que c'est inacceptable, alors vous pouvez aller "Je me demande si je peux couper 30% de cela", mais vous ne le faites pas savoir si cela est possible, sauf si vous déterminez exactement combien de travail est effectué, et exactement ce que le processeur est capable de faire au maximum. Combien de temps voulez-vous passer à l'optimiser, si vous ne savez même pas si le CPU est fondamentalement capable d'exécuter plus d'instructions par seconde?

Il est très facile d'empêcher l'utilisation efficace de l'unité FP FP), en ayant trop de dépendances entre FP ops, ou en ayant trop de branches ou similaire empêchant une planification efficace. Et si c'est ce qui retient votre implémentation, vous avez besoin de le savoir. Vous devez savoir que "Je n'obtiens pas le débit FP cela devrait être possible, donc clairement d'autres parties de mon code empêchent les instructions FP d'être disponibles lorsque le CPU est prêt à en émettre une ").

Pourquoi avez-vous besoin d'autres façons de mesurer les performances? Qu'y a-t-il de mal à simplement calculer le FLOPS compte comme votre patron vous l'a demandé?;)

49
jalf

Je voudrais juste ajouter quelques points plus fins:

  • division est spécial. Étant donné que la plupart des processeurs peuvent effectuer un ajout, une comparaison ou une multiplication en un seul cycle, ceux-ci sont tous comptés comme un flop. Mais la division prend toujours plus de temps. La durée dépend du processeur, mais il existe une sorte de standard de facto dans la communauté HPC pour compter une division comme 4 flops.

  • Si un processeur a une instruction fusion multipliée-ajoutée qui fait une multiplication et un ajout dans une seule instruction - généralement A + = B * C - qui compte pour 2 opérations.

  • Faites toujours attention en distinguant flops simple précision et flops double précision. Un processeur qui est capable de tant de gigaflops simple précision ne peut être capable que d'une petite fraction de ce nombre de gigaflops double précision. Les processeurs AMD Athlon et Phenom peuvent généralement faire deux fois moins de flops en double précision qu'en simple précision. Les processeurs ATI Firestream peuvent généralement faire 1/5e autant de flops double précision que la précision simple. Si quelqu'un essaie de vous vendre un processeur ou un progiciel et qu'il cite simplement des flops sans dire lequel, vous devez l'appeler.

  • Les termes mégaflop, gigaflop, téraflop, etc. sont couramment utilisés. Ceux-ci se réfèrent à des facteurs de 10, et non 1024 . Par exemple, 1 mégaflop = 1000000 flop/sec et non 1048576. Tout comme avec les tailles de lecteur de disque, il y a une certaine confusion à ce sujet.

27
Die in Sente

Ancienne question avec de vieilles réponses, si elles sont populaires, qui ne sont pas exactement géniales, OMI.

Un "FLOP" est une opération mathématique à virgule flottante. "FLOPS" peut signifier l'une des deux choses suivantes:

  • Le pluriel simple de "FLOP" (c'est-à-dire "opération [~ # ~] x [~ # ~] prend 50 FLOPs")
  • Le taux de FLOPs dans le premier sens (c'est-à-dire les opérations mathématiques à virgule flottante par seconde)

Lorsque ce n'est pas clair à partir du contexte, lequel de ces termes est souvent désambiguïsé en écrivant les premiers comme "FLOP" et les seconds comme "FLOP/s".

Les FLOP sont appelés ainsi pour les distinguer des autres types d'opérations CPU , telles que les opérations mathématiques entières, les opérations logiques, les opérations au niveau du bit, les opérations de mémoire et les branchements opérations, qui ont des coûts différents (lire "prennent différentes durées") qui leur sont associés.

La pratique du "comptage FLOP" remonte aux tout premiers jours du calcul scientifique, lorsque les FLOP étaient, relativement parlant, extrêmement coûteux, prenant chacun de nombreux cycles CPU. Un coprocesseur mathématique 80387, par exemple, a pris quelque chose comme 300 cycles pour une seule multiplication. C'était à la fois avant le pipelining et avant que le fossé entre les vitesses d'horloge du processeur et les vitesses de mémoire ne se soit vraiment ouvert: les opérations de mémoire ne prenaient qu'un ou deux cycles, et la ramification ("prise de décision") était également bon marché. À l'époque, si vous pouviez éliminer un seul FLOP au profit d'une dizaine d'accès mémoire, vous avez fait un gain. Si vous pouviez éliminer un seul FLOP au profit d'une dizaine de branches, vous gagniez. Donc, dans le passé, il était logique de compter les FLOP et de ne pas trop se soucier des références de mémoire et des branches car les FLOP dominaient fortement le temps d'exécution car ils étaient individuellement très cher par rapport à d'autres types d'opérations.

Plus récemment, la situation s'est inversée. Les FLOP sont devenus très bon marché - tout Intel moderne - core peut exécuter environ deux FLOP par cycle (bien que la division reste relativement chère) - et les accès à la mémoire et les branches sont comparativement beaucoup plus chers: un hit de cache L1 coûte peut-être 3 ou 4 cycles, une extraction de la mémoire principale coûte 150–200. Compte tenu de cette inversion, il n'est plus le cas que l'élimination d'un FLOP au profit d'un accès mémoire se traduise par un gain ; en fait, c'est peu probable. De même, il est souvent moins cher de "faire juste" un FLOP, même s'il est redondant, plutôt que de décider de le faire ou non. C'est à peu près le contraire de la situation d'il y a 25 ans.

Malheureusement, la pratique du comptage aveugle des FLOP en tant que métrique absolue du mérite algorithmique a persisté bien après sa date de péremption. Le calcul scientifique moderne concerne beaucoup plus la gestion de la bande passante mémoire - essayer de garder les unités d'exécution qui faites les FLOP sont constamment alimentés avec des données - que de réduire le nombre de FLOP. La référence à [~ # ~] linpack [~ # ~] (qui était essentiellement obsolète par [~ # ~] lapack [~ # ~] 20 il y a quelques années) me porte à croire que votre employeur est probablement d'une très vieille école qui n'a pas intériorisé le fait que l'établissement des attentes de performance n'est plus seulement une question de FLOP. Un solveur qui fait deux fois plus de FLOP pourrait encore être vingt fois plus rapide qu'un autre s'il a un modèle d'accès à la mémoire et une disposition des données beaucoup plus favorables.

Le résultat de tout cela est que l'évaluation des performances des logiciels à forte intensité de calcul est devenue beaucoup plus complexe qu'auparavant . Le fait que les FLOP soient devenus bon marché est extrêmement compliqué par l'énorme variabilité des coûts des opérations de mémoire et des branches. Lorsqu'il s'agit d'évaluer algorithmes, le simple comptage FLOP n'informe plus les attentes de performances globales.

Peut-être une meilleure façon de penser les attentes et l'évaluation des performances est fournie par le soi-disant modèle de ligne de toit , qui est loin d'être parfait, mais a l'avantage de vous faire pensez au compromis entre les points à virgule flottante et la bande passante mémoire en même temps , fournissant une "image 2D" plus informative et plus perspicace qui permet la comparaison des mesures de performance et des attentes de performance.

Ça vaut le coup d'oeil.

5
Emmet

"comparer les résultats avec des repères" et faire quoi?

FLOPS signifie que vous avez besoin

1) FLOP par unité de travail.

2) le temps pour cette unité de travail.

Disons que vous avez un fichier d'entrée qui effectue 1 000 itérations sur une boucle. La boucle est une unité de travail pratique. Il est exécuté 1000 fois. Ça prend une heure.

La boucle a quelques ajouts et multiplications et quelques divisions et une racine carrée. Vous pouvez compter les ajouts, les multiplications et les divisions. Vous pouvez compter cela dans la source, en recherchant +, * et /. Vous pouvez trouver la sortie en langage assembleur du compilateur et les compter également. Vous pouvez obtenir des numéros différents. Lequel a raison? Demandez à votre patron.

Vous pouvez compter les racines carrées, mais vous ne savez pas ce que cela fait vraiment en termes de multiplications et d'ajouts. Donc, vous devrez faire quelque chose comme la multiplication de référence par rapport à la racine carrée pour avoir une idée du temps que prend une racine carrée.

Vous connaissez maintenant le FLOPS dans votre boucle. Et vous savez le temps de l'exécuter 1000 fois. Vous savez FLOPS par seconde).

Ensuite, vous regardez LINPACK et constatez que vous êtes plus lent. Maintenant quoi? Votre programme n'est pas LINPACK et il est plus lent que LINPACK. Les chances sont vraiment bonnes que votre code soit plus lent. À moins que votre code ne soit écrit et optimisé pendant le même nombre d'années qu'un LINPACK, vous serez plus lent.

Voici l'autre partie. Votre processeur a une note définie FLOPS par rapport à divers benchmarks. Votre algorithme n'est pas un de ces benchmarks, donc vous êtes en deçà des benchmarks. Est-ce mauvais? Ou est-ce la conséquence évidente de ne pas être une référence?

Quel sera le résultat réalisable?

La mesure par rapport à une base de code de référence ne fera que vous dire que votre algorithme n'est pas l'algorithme de référence. Il est évident que vous serez différent; généralement plus lent.

De toute évidence, le résultat de la mesure par rapport à LINPACK sera (a) vous êtes différent et donc (b) vous devez optimiser.

La mesure n'est vraiment utile que lorsqu'elle est effectuée contre vous-même. Pas un mélange d'instructions hypothétique, mais votre propre mélange d'instructions. Mesurez vos propres performances. Faire un changement. Voyez si vos performances - par rapport à vous-même - s'améliorent ou empirent.

LES FLOPS n'ont pas d'importance. Ce qui compte, c'est le temps par unité de travail. Vous ne correspondrez jamais aux paramètres de conception de votre matériel, car vous n'utilisez pas la référence que vos concepteurs de matériel attendaient.

LINPACK n'a pas d'importance. Ce qui compte, c'est votre base de code et les modifications que vous apportez pour modifier les performances.

4
S.Lott

J'essaierais simplement de faire en sorte que cela aille le plus vite possible, et cela nécessite de savoir où il passe du temps, surtout s'il y a des appels de fonction qui pourraient être évités.

Je le fais par la méthode simple de simplement l'interrompre quelques fois pendant qu'il fonctionne et de voir ce qu'il fait. Voici le genre de choses que je trouve:

  • La plupart du temps, il est en train de calculer la dérivée et/ou la jacobienne. Une grande partie de ce temps peut être consacrée aux appels de fonctions mathématiques tels que exp(), log() et sqrt(). Ceux-ci sont souvent répétés avec des arguments identiques et peuvent être mémorisés. (Accélération massive.)

  • Une grande partie du temps est consacrée à calculer les dérivées trop souvent car les tolérances d'intégration sont plus strictes que nécessaire. (Plus rapide)

  • Si un algorithme d'intégration implicite (tel que DLSODE Gear) est utilisé parce que les équations sont considérées comme rigides, il est probable qu'elles ne le soient pas, et quelque chose comme Runge-Kutta pourrait être utilisé. (DVERK). (Toujours plus vite)

  • Un algorithme exposant de matrice pourrait éventuellement être utilisé si le modèle est linéaire (DGPADM). C'est une grande victoire à la fois pour les performances et la précision, et est insensible à la rigidité. (Beaucoup plus rapide)

  • Plus haut dans la pile d'appels, il se pourrait que les mêmes intégrations soient effectuées à plusieurs reprises avec des paramètres légèrement différents, afin de déterminer un gradient de différence directe ou centrale de la solution par rapport à ces paramètres. Si les équations différentielles sont elles-mêmes différenciables, il peut être possible d'obtenir ces gradients analytiquement, ou en augmentant les équations avec des équations de sensibilité. Ce n'est pas seulement beaucoup plus rapide, mais beaucoup plus précis, ce qui peut accélérer les choses encore plus haut dans la pile.

Vous pouvez regarder chaque niveau de la pile comme une opportunité de trouver des choses à optimiser, et les accélérations s'accumuleront. Ensuite, lorsque vous passez à plusieurs processeurs, en supposant qu'il soit parallélisable, cela devrait fournir son propre facteur multiplicatif.

Revenons donc aux FLOP. Vous pouvez essayer de maximiserFLOPs / second, mais il peut aussi être beaucoup plus utile pour minimzeFLOPs / run, en optimisant à tous les niveaux de la pile. Dans tous les cas, juste mesure eux ne vous dit presque rien.

1
Mike Dunlavey

A FLOPS est, comme vous l'avez dit, une opération à virgule flottante par seconde. Par exemple, si vous prenez exactement une seconde pour une opération (comme ajouter, soustraire, multiplier ou diviser deux valeurs) et renvoyant le résultat), vos performances sont simplement de 1 FLOPS. Un processeur récent réalisera facilement plusieurs GigaFLOPS, soit plusieurs milliards d'opérations en virgule flottante par seconde.

1
Sören Kuklau

Votre employeur a raison.
La seule façon de mesurer l'efficacité de votre programme Fortran (ou de tout autre programme, btw) est de le tester par rapport à des références standard, si elles existent.

Et, à propos des FLOP, il signifie "opérations à virgule flottante par seconde" - voir la définition sur Wikipédia.

0
Gabriele D'Antona

Je ne pense pas que mesurer FLOPS sera très utile.

Le nombre de FLOPS atteints vous indiquera à quel point votre algorithme garde le CPU, mais ne vous dira pas à quel point votre algorithme lui-même fonctionne.

Vous pouvez trouver deux algorithmes différents qui font que le processeur effectue le même nombre de FLOPS mais l'un vous fournit le résultat souhaité en deux fois moins de temps).

Je pense que vous feriez mieux de regarder une statistique de niveau beaucoup plus élevé, comme le nombre d'équations différentielles résolues par unité de temps (c'est, après tout, le but de votre algorithme).

D'un autre côté, mesurer le nombre de FLOPS atteints) peut vous aider à améliorer votre algorithme car il vous indiquera à quel point vous êtes occupé à garder le CPU.

0
Chris Roberts