什么是IACA,我如何使用它?
我发现了一个叫IACA(英特尔架构代码分析器)的有趣而强大的工具,但是我很难理解它。 我该怎么做,它有什么限制,我怎么能:
- 用它来分析C或C ++中的代码?
- 用它来分析x86汇编中的代码?
2017-11 : 3.0版本发布(最新截至2017年11月3日)
2017-03 :版本2.3发布
这是什么:
IACA(英特尔架构代码分析器)是英特尔公司开发的一款免费的闭源静态分析工具,用于静态分析现代英特尔处理器执行的指令调度。 这使得它可以计算,对于给定的片段,
- 在吞吐量模式中 ,最大吞吐量( 该片段被假定为最内层循环的主体 )
- 在延迟模式下 ,从第一条指令到最后一条指令的最小延迟。
- 在跟踪模式下 ,通过stream水线阶段打印指令的进度。
当采取最佳的执行条件(所有的内存访问命中L1caching,并没有页面错误)。
IACA支持从版本2.3开始的Nehalem,Westmere,Sandy Bridge,Ivy Bridge,Haswell,Broadwell和Skylake处理器以及3.0版本的Haswell,Broadwell和Skylake的计算规则。
IACA是一个生成ASCII文本报告和Graphviz图表的命令行工具。 版本2.1及以下版本支持32位和64位Linux,Mac OS X和Windows以及32位和64位代码的分析; 版本2.2及以上仅支持64位操作系统和64位代码分析。
如何使用它:
IACA的input是你的代码的一个编译的二进制文件,其中已经注入了两个标记 :一个开始标记和一个结束标记 。 标记使代码不可运行,但允许工具快速find相关的代码段并分析它们。
您不需要在系统上运行二进制文件; 事实上,提供给IACA的二进制文件无法运行,因为代码中存在注入标记。 IACA只需要读取要分析的二进制文件的能力。 因此使用IACA可以分析在奔腾III机器上采用FMA指令的Haswell二进制。
C / C ++
在C和C ++中,可以使用#include "iacaMarks.h"
获得对标记注入macros的访问,其中iacaMarks.h
是include/
子目录中工具的头文件。
然后,将标记插入感兴趣的最内层循环或感兴趣的直线块中,如下所示:
/* C or C++ usage of IACA */ while(cond){ IACA_START /* Loop body */ /* ... */ } IACA_END
然后重新启动应用程序,否则会启用优化(在Visual Studio等IDE之类的用户的发行模式下)。 输出是一个二进制文件,除了存在使得应用程序不可运行的标记之外,在所有方面都与发布版本相同。
IACA依靠编译器不过分地重新排列标记; 因此,对于这样的分析,构build某些强大的优化可能需要被禁用,如果它们重新排列标记以包含不在最内层循环内的无关代码或排除其内的代码。
程序集(x86)
IACA的标记是在代码中的正确位置注入的魔法字节模式。 在C或C ++中使用iacaMarks.h
时,编译器会在正确的位置插入标头指定的魔术字节。 但是,在组装中,您必须手动插入这些标记。 因此,必须做到以下几点:
; 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 ++程序员来说,编译器实现相同的模式是至关重要的。
它输出的内容:
作为一个例子,让我们分析下面的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
我们在.L2
标签之前立即添加开始标记,紧接在结束标记之后。 然后,我们重build软件,然后调用IACA(在Linux上,假定bin/
目录在path中,而foo
是包含IACA标记的ELF64对象):
iaca.sh -64 -arch HSW -graph insndeps.dot foo
,因此在Haswell处理器上运行时生成64位二进制foo
的分析报告,以及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。 这个例子使我们能够诊断问题,因为店铺没有被Port 7处理,并采取补救措施。
限制:
IACA不支持某些在分析中被忽略的指令。 它不支持比Nehalem更早的处理器,并且不支持吞吐量模式下的非最内层循环(无法猜测使用哪个分支的频率和模式)。