J'ai trouvé cet outil intéressant et puissant appelé IACA (Intel Architecture Code Analyzer) , mais j'ai du mal à le comprendre. Que puis-je en faire, quelles sont ses limites et comment puis-je:
2019-04 : Atteint [~ # ~] eol [~ # ~] . Alternative suggérée : LLVM-MCA
2017-11 : Version 3.0 publiée (dernière version du 18/05/2019)
2017-03 : Version 2.3 publiée
IACA (Intel Architecture Code Analyzer) est un ( 2019: logiciel gratuit en fin de vie ), source fermée statique outil d'analyse fabriqué par Intel pour analyser statiquement la planification des instructions lorsqu'elles sont exécutées par des processeurs Intel modernes. Cela lui permet de calculer, pour un extrait donné,
en supposant des conditions d'exécution optimales (tous les accès à la mémoire atteignent le cache L1 et il n'y a aucun défaut de page).
IACA prend en charge les ordonnancements informatiques pour les processeurs Nehalem, Westmere, Sandy Bridge, Ivy Bridge, Haswell, Broadwell et Skylake à partir de la version 2.3 et Haswell, Broadwell et Skylake à partir de la version 3.0.
IACA est un outil en ligne de commande qui produit des rapports de texte ASCII et des diagrammes Graphviz. Les versions 2.1 et inférieures prennent en charge Linux 32 et 64 bits, Mac OS X et Windows et l'analyse de 32 bits et Code 64 bits; les versions 2.2 et supérieures ne prennent en charge que les systèmes d'exploitation 64 bits et l'analyse du code 64 bits.
L'entrée de l'IACA est un binaire compilé de votre code, dans lequel ont été injectés deux marqueurs: a marqueur de début et un marqueur de fin. Les marqueurs rendent le code impossible à exécuter, mais permettent à l'outil de trouver rapidement les morceaux de code pertinents et de les analyser.
Vous n'avez pas besoin de pouvoir exécuter le binaire sur votre système; En fait, le binaire fourni à IACA ne peut pas s'exécute quand même à cause de la présence des marqueurs injectés dans le code. IACA nécessite uniquement la capacité de lire le binaire à analyser. Ainsi, il est possible, en utilisant IACA, d'analyser un binaire Haswell en utilisant des instructions FMA sur une machine Pentium III.
En C et C++, on accède aux macros d'injection de marqueurs avec #include "iacaMarks.h"
, où iacaMarks.h
est un en-tête fourni avec l'outil dans le include/
sous-répertoire.
On insère ensuite les marqueurs autour de la boucle la plus intérieure d'intérêt, ou le morceau linéaire d'intérêt, comme suit :
/* C or C++ usage of IACA */
while(cond){
IACA_START
/* Loop body */
/* ... */
}
IACA_END
L'application est ensuite reconstruite comme elle le ferait autrement avec les optimisations activées (en mode Release pour les utilisateurs d'IDE tels que Visual Studio). La sortie est un binaire identique à tous égards à la version Release, sauf en présence des marques, qui rendent l'application non exécutable.
IACA compte sur le compilateur pour ne pas réorganiser les marques de manière excessive; En tant que tel, pour de telles analyses, certaines optimisations puissantes peuvent devoir être désactivées si elles réordonnent les marques pour inclure du code superflu ne se trouvant pas dans la boucle la plus interne, ou excluant du code à l'intérieur.
Les marqueurs IACA sont des modèles d'octets magiques injectés à l'emplacement correct dans le code. Lors de l'utilisation de iacaMarks.h
en C ou C++, le compilateur gère l'insertion des octets magiques spécifiés par l'en-tête à l'emplacement correct. Dans Assembly, cependant, vous devez insérer manuellement ces marques. Ainsi, il faut faire ce qui suit:
; NASM usage of IACA
mov ebx, 111 ; Start marker bytes
db 0x64, 0x67, 0x90 ; Start marker bytes
.innermostlooplabel:
; Loop body
; ...
jne .innermostlooplabel ; Conditional branch backwards to top of loop
mov ebx, 222 ; End marker bytes
db 0x64, 0x67, 0x90 ; End marker bytes
Il est essentiel pour les programmeurs C/C++ que le compilateur réalise ce même modèle.
À titre d'exemple, analysons le exemple d'assembleur suivant sur l'architecture Haswell :
.L2:
vmovaps ymm1, [rdi+rax] ;L2
vfmadd231ps ymm1, ymm2, [rsi+rax] ;L2
vmovaps [rdx+rax], ymm1 ; S1
add rax, 32 ; ADD
jne .L2 ; JMP
Nous ajoutons immédiatement avant le .L2
étiquette le marqueur de début et immédiatement après jne
le marqueur de fin. Nous reconstruisons ensuite le logiciel et invoquons IACA ainsi (sous Linux, suppose que le bin/
répertoire pour être dans le chemin et foo
pour être un objet ELF64 contenant les marques IACA):
iaca.sh -64 -Arch HSW -graph insndeps.dot foo
, produisant ainsi un rapport d'analyse du binaire 64 bits foo
lorsqu'il est exécuté sur un processeur Haswell, et un graphique des dépendances d'instructions visualisables avec Graphviz.
Le rapport est imprimé sur la sortie standard (bien qu'il puisse être dirigé vers un fichier avec un -o
commutateur). Le rapport fourni pour l'extrait ci-dessus est le suivant:
Intel(R) Architecture Code Analyzer Version - 2.1
Analyzed File - ../../../tests_fma
Binary Format - 64Bit
Architecture - HSW
Analysis Type - Throughput
Throughput Analysis Report
--------------------------
Block Throughput: 1.55 Cycles Throughput Bottleneck: FrontEnd, PORT2_AGU, PORT3_AGU
Port Binding In Cycles Per Iteration:
---------------------------------------------------------------------------------------
| Port | 0 - DV | 1 | 2 - D | 3 - D | 4 | 5 | 6 | 7 |
---------------------------------------------------------------------------------------
| Cycles | 0.5 0.0 | 0.5 | 1.5 1.0 | 1.5 1.0 | 1.0 | 0.0 | 1.0 | 0.0 |
---------------------------------------------------------------------------------------
N - port number or number of cycles resource conflict caused delay, DV - Divider pipe (on port 0)
D - Data fetch pipe (on ports 2 and 3), CP - on a critical path
F - Macro Fusion with the previous instruction occurred
* - instruction micro-ops not bound to a port
^ - Micro Fusion happened
# - ESP Tracking sync uop was issued
@ - SSE instruction followed an AVX256 instruction, dozens of cycles penalty is expected
! - instruction not supported, was not accounted in Analysis
| Num Of | Ports pressure in cycles | |
| Uops | 0 - DV | 1 | 2 - D | 3 - D | 4 | 5 | 6 | 7 | |
---------------------------------------------------------------------------------
| 1 | | | 1.0 1.0 | | | | | | CP | vmovaps ymm1, ymmword ptr [rdi+rax*1]
| 2 | 0.5 | 0.5 | | 1.0 1.0 | | | | | CP | vfmadd231ps ymm1, ymm2, ymmword ptr [rsi+rax*1]
| 2 | | | 0.5 | 0.5 | 1.0 | | | | CP | vmovaps ymmword ptr [rdx+rax*1], ymm1
| 1 | | | | | | | 1.0 | | | add rax, 0x20
| 0F | | | | | | | | | | jnz 0xffffffffffffffec
Total Num Of Uops: 6
L'outil souligne utilement qu'actuellement, le goulot d'étranglement est le frontend Haswell et l'AGU des ports 2 et 3. Cet exemple nous permet de diagnostiquer le problème car le magasin n'est pas traité par le port 7 et de prendre des mesures correctives.
IACA ne prend pas en charge certaines instructions, qui sont ignorées dans l'analyse. Il ne prend pas en charge les processeurs plus anciens que Nehalem et ne prend pas en charge les boucles non internes en mode débit (n'ayant aucune capacité de deviner quelle branche est prise à quelle fréquence et selon quel modèle).