Métriques

Nous l’avons déjà mentionné, perf stat est capable de calculer automatiquement certaines métriques de performance à partir des mesures brutes que vous demandez.

Mais il est également possible de prendre le problème dans l’autre sens, et d’indiquer les métriques que vous recherchez en laissant le soin à perf de sélectionner les bons événements matériels à mesurer pour les calculer. Cela se fait avec l’option --metrics, qui s’abbrévie en -M.

Par exemple, si on souhaite tout savoir sur les calculs flottants effectués à chaque cycle CPU, on peut demander la métrique FLOPc (opérations flottants par cycle) :

srun --pty \
    perf stat -M FLOPc \
    ./scale.bin 2048 10000000

Statistiques des opérations flottantes

Le détail des opérations flottantes qui est associé à cette métrique nous permet d’avancer dans la compréhension des faibles performances de notre exemple :

  • Le code n’utilise que des opérations 256-bit, pas les opérations 512-bit natives du matériel. En effet, GCC et clang n’utilisent pas ces dernières par défaut, en raison du trop grand nombre de CPUs Intel où elles sont mal émulées par des unités de calcul 256-bit.
  • Le code n’effectue qu’une opération flottante tous les deux cycles environ (rappelez vous qu’en présence d’hyperthreading, perf compte deux cycles CPU par cycle d’horloge réellement écoulé), alors qu’en principe le matériel est capable de traiter deux opérations par cycle.

Il serait un peu long d’expliquer le second problème avec juste perf stat, nous serons plus productifs avec perf annotate. Mais perf stat suffit pour étudier le premier problème.

Exercice : Recompilez le code en activant la vectorisation 512-bit, ce que vous pouvez faire avec la commande…

rm -f scale.bin && srun make OPTS='-O3 -mprefer-vector-width=512' scale.bin

…puis répétez l’analyse précédente.

Vous noterez que l’accélération dépasse le facteur 2. C’est un phénomène intriguant pour lequel je n’ai pas d’explication. Il semblerait que pour une raison ou pour une autre, le CPU manie plus efficacement les instructions vectorielles de largeur native, et ce en dépit d’une réduction de la fréquence d’horloge que vous pouvez observer avec perf stat sans arguments.