O que é a IACA e como eu a uso?

Eu encontrei esta ferramenta interessante e poderosa chamada IACA (o Intel Architecture Code Analyzer) , mas eu tenho dificuldade em entendê-lo. O que posso fazer com isso, quais são suas limitações e como posso:

  • Usá-lo para analisar o código em C ou C ++?
  • Usá-lo para analisar o código no montador x86?

    2017-11 : Versão 3.0 lançada (mais recente a partir de 2017-11-03)

    2017-03 : versão 2.3 lançada

    O que é isso:

    O IACA (o Intel Architecture Code Analyzer) é uma ferramenta de análise estática de software livre e de código fechado feita pela Intel para analisar estaticamente o agendamento de instruções quando executada pelos modernos processadores Intel. Isso permite calcular, para um determinado trecho,

    • No modo Throughput , o throughput máximo ( o snippet é considerado o corpo de um loop mais interno )
    • No modo de latência , a latência mínima da primeira instrução para a última.
    • No modo de rastreamento , imprime o progresso das instruções nos estágios do pipeline.

    ao assumir as condições de execução ideais (todos os accesss à memory atingem o cache L1 e não há falhas de página).

    O IACA suporta programação de computadores para os processadores Nehalem, Westmere, Sandy Bridge, Ivy Bridge, Haswell, Broadwell e Skylake a partir da versão 2.3 e Haswell, Broadwell e Skylake a partir da versão 3.0.

    O IACA é uma ferramenta de linha de comando que produz relatórios de texto ASCII e diagramas Graphviz. As versões 2.1 e inferiores suportavam Linux de 32 e 64 bits, Mac OS X e Windows e análise de código de 32 e 64 bits; A versão 2.2 e superior suporta apenas sistemas operacionais de 64 bits e análise de código de 64 bits.

    Como usá-lo:

    A input do IACA é um binário compilado do seu código, no qual foram injetados dois marcadores : um marcador inicial e um marcador final . Os marcadores tornam o código irrecuperável, mas permitem que a ferramenta localize rapidamente as partes relevantes do código e as analise.

    Você não precisa ter a capacidade de executar o binário no seu sistema; Na verdade, o binário fornecido ao IACA não pode ser executado de qualquer maneira por causa da presença dos marcadores injetados no código. O IACA requer apenas a capacidade de ler o binário a ser analisado. Assim, é possível, usando o IACA, analisar um binário Haswell usando instruções FMA em uma máquina Pentium III.

    C / C ++

    Em C e C ++, obtém-se access a macros de injeção de marcadores com #include "iacaMarks.h" , em que iacaMarks.h é um header fornecido com a ferramenta no subdiretório include/ .

    Em seguida, insere os marcadores em volta do loop de interesse mais interno , ou o pedaço de linha reta de interesse, da seguinte maneira:

     /* C or C++ usage of IACA */ while(cond){ IACA_START /* Loop body */ /* ... */ } IACA_END 

    O aplicativo, em seguida, é recriado como de outra forma com otimizações habilitadas (no modo de versão para usuários de IDEs como o Visual Studio). A saída é um binário que é idêntico em todos os aspectos à compilation Release, exceto com a presença das marcas, o que torna a aplicação não executável.

    A IACA depende do compilador não reordenar as marcas excessivamente; Dessa forma, para tais análises são criadas certas otimizações poderosas que precisam ser desabilitadas se elas reordenarem as marcas para include código estranho não dentro do loop mais interno ou excluir o código dentro dele.

    Montagem (x86)

    Os marcadores da IACA são padrões de bytes mágicos injetados no local correto dentro do código. Ao usar iacaMarks.h em C ou C ++, o compilador manipula inserindo os bytes mágicos especificados pelo header no local correto. Na assembly, no entanto, você deve inserir manualmente essas marcas. Assim, deve-se fazer o seguinte:

      ; 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 

    É crítico para os programadores C / C ++ que o compilador atinja esse mesmo padrão.

    O que gera:

    Como exemplo, vamos analisar o seguinte exemplo de montador na arquitetura 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 

    Adicionamos imediatamente antes do marcador .L2 o marcador inicial e imediatamente após o marcador final. Em seguida, reconstruímos o software e invocamos o IACA (no Linux, pressupõe-se que o bin/ directory esteja no caminho e foo seja um object ELF64 contendo as marcas do IACA):

     iaca.sh -64 -arch HSW -graph insndeps.dot foo 

    , produzindo assim um relatório de análise do binário foo 64 bits quando executado em um processador Haswell, e um gráfico das dependencies de instrução visíveis com o Graphviz.

    O relatório é impresso na saída padrão (embora possa ser direcionado para um arquivo com uma opção -o ). O relatório fornecido para o snippet acima é:

     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 

    A ferramenta destaca que, atualmente, o gargalo é o frontend Haswell e a AGU das Portas 2 e 3. Este exemplo nos permite diagnosticar o problema, pois a loja não está sendo processada pela Porta 7 e toma medidas corretivas.

    Limitações:

    O IACA não suporta algumas poucas instruções, que são ignoradas na análise. Ele não suporta processadores mais antigos que o Nehalem e não suporta loops não-mais internos no modo de rendimento (não tendo capacidade de adivinhar qual ramificação é tomada com que frequência e em qual padrão).