c++ - 什么是 IACA,我该如何使用它?

标签 c++ c performance assembly iaca

我发现了这个有趣而强大的工具,名为 IACA (the Intel Architecture Code Analyzer) ,但我很难理解它。我可以用它做什么,它的局限性是什么,我该如何:

  • 用它来分析 C 或 C++ 中的代码?
  • 用它来分析 x86 汇编器中的代码?
  • 最佳答案

    2019-04: Reached EOL. Suggested alternative: LLVM-MCA

    2017-11: Version 3.0 released (latest as of 2019-05-18)

    2017-03: Version 2.3 released


    这是什么:
    IACA (the Intel Architecture Code Analyzer)是一个 ( 2019: end-of-life ) 免费软件,由英特尔开发的闭源静态分析工具,用于静态分析现代英特尔处理器执行时的指令调度。这允许它计算,对于给定的片段,
  • 吞吐量模式 ,最大吞吐量(假定代码片段是最内层循环的主体)
  • 延迟模式 ,从第一条指令到最后一条指令的最小延迟。
  • 跟踪模式 , 打印指令通过其流水线阶段的进度。

  • 当假设最佳执行条件时(所有内存访问都命中 L1 缓存并且没有页面错误)。
    IACA 支持 Nehalem、Westmere、Sandy Bridge、Ivy Bridge、Haswell、Broadwell 和 Skylake 处理器(自 2.3 版起)和 Haswell、Broadwell 和 Skylake(自 3.0 版起)的计算调度。
    IACA 是一个命令行工具,可生成 ASCII 文本报告和 Graphviz 图。 2.1及以下版本支持32位和64位Linux、Mac OS X和Windows以及32位和64位代码分析; 2.2 及以上版本仅支持 64 位操作系统和 64 位代码分析。
    如何使用它:
    IACA 的输入是代码的编译二进制文件,其中注入(inject)了两个标记:开始标记和结束标记。标记使代码无法运行,但允许工具快速找到相关的代码片段并对其进行分析。
    您不需要能够在您的系统上运行二进制文件;事实上,由于代码中存在注入(inject)的标记,提供给 IACA 的二进制文件无论如何都无法运行。 IACA 只需要能够读取要分析的二进制文件。因此,可以使用 IACA 在 Pentium III 机器上使用 FMA 指令分析 Haswell 二进制文件。
    C/C++
    在 C 和 C++ 中,可以使用 #include "iacaMarks.h" 访问标记注入(inject)宏。 ,其中 iacaMarks.hinclude/ 中的工具随附的标题子目录。
    然后在 周围插入标记最里面感兴趣的循环,或感兴趣的直线块,如下:
    /* C or C++ usage of IACA */
    
    while(cond){
        IACA_START
        /* Loop body */
        /* ... */
    }
    IACA_END
    
    然后重新构建应用程序,因为它会在启用优化的情况下重建(对于 Visual Studio 等 IDE 的用户处于 Release模式)。输出是一个二进制文件,除了存在使应用程序不可运行的标记外,它在所有方面都与发布版本相同。
    IACA 依赖于编译器不会过度重新排序标记;因此,对于此类分析构建,如果某些强大的优化重新排序标记以包含不在最内层循环中的无关代码,或排除其中的代码,则可能需要禁用某些强大的优化。
    组装 (x86)
    IACA 的标记是在代码中正确位置注入(inject)的魔术字节模式。使用时 iacaMarks.h在 C 或 C++ 中,编译器处理在正确位置插入 header 指定的魔术字节。但是,在 assembly 中,您必须手动插入这些标记。因此,必须做到以下几点:
        ; 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
    
    对于 C/C++ 程序员来说,编译器实现相同的模式至关重要。
    它输出什么:
    作为一个例子,让我们分析 following assembler example on the Haswell architecture :
    .L2:
        vmovaps         ymm1, [rdi+rax] ;L2
        vfmadd231ps     ymm1, ymm2, [rsi+rax] ;L2
        vmovaps         [rdx+rax], ymm1 ; S1
        add             rax, 32         ; ADD
        jne             .L2             ; JMP
    
    我们在 .L2 之前添加标记开始标记并紧跟在 jne 之后结束标记。然后我们重建软件,并因此调用 IACA(在 Linux 上,假设 bin/ 目录在路径中,而 foo 是一个包含 IACA 标记的 ELF64 对象):
    iaca.sh -64 -arch HSW -graph insndeps.dot foo
    
    ,从而产生64位二进制foo的分析报告在 Haswell 处理器上运行时,以及可使用 Graphviz 查看的指令依赖关系图。
    报告被打印到标准输出(尽管它可能被定向到一个带有 -o 开关的文件)。为上述片段给出的报告是:
    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
    
    该工具有用地指出,目前,瓶颈是 Haswell 前端以及端口 2 和 3 的 AGU。此示例允许我们将问题诊断为端口 7 未处理存储,并采取补救措施。
    限制:
    IACA 不支持某些在分析中忽略的指令。它不支持比 Nehalem 更旧的处理器,也不支持吞吐量模式下的非最内层循环(无法猜测哪个分支被采用的频率和模式)。

    关于c++ - 什么是 IACA,我该如何使用它?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26021337/

    相关文章:

    c++ - 减少数以千计的编译器警告

    c++ - 使用 QtCreator 设置 GDB

    具有两个命名参数的 C 可变参数宏

    performance - Haskell:IORefs 的性能

    javascript - jQuery 效果运行流畅,但有时会变得不稳定 - 为什么?

    java - 只是设置一个值是否比检查存在性更快并且仅在不存在时设置 - 就像在这个 Android/Java 代码中一样?

    c++ - 子类化std::chrono::duration

    c++ - C++ 中的多重映射

    c - 如何使用 XLib 调整像素图的大小?

    c - 打开外部程序