我发现了这个有趣且强大的工具,称为IACA(英特尔架构代码分析器),但我无法理解它。我可以用它做什么,它有什么限制,我可以如何:
- 用它来分析 C 或 C++ 中的代码?
- 用它来分析 x86 汇编器中的代码?
我发现了这个有趣且强大的工具,称为IACA(英特尔架构代码分析器),但我无法理解它。我可以用它做什么,它有什么限制,我可以如何:
2019-04:达到EOL。建议的替代方案:LLVM-MCA
2017-11 : 3.0版发布(最新于 2019-05-18)
2017-03 : 2.3版发布
IACA(英特尔架构代码分析器)是英特尔制造的(2019 年停产)免费软件、闭源静态分析工具,用于静态分析现代英特尔处理器执行时的指令调度。这允许它计算,对于给定的片段,
当假设最佳执行条件时(所有内存访问都命中 L1 缓存并且没有页面错误)。
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 的输入是您的代码的编译二进制文件,其中注入了两个标记:开始标记和结束标记。标记使代码无法运行,但允许工具快速找到相关的代码片段并对其进行分析。
您不需要在系统上运行二进制文件的能力;事实上,提供给 IACA 的二进制文件无论如何都无法运行,因为代码中存在注入的标记。IACA 只需要能够读取要分析的二进制文件。因此,可以使用 IACA 在 Pentium III 机器上使用 FMA 指令分析 Haswell 二进制文件。
在 C 和 C++ 中,可以使用 访问标记注入宏#include "iacaMarks.h"
,其中是子目录iacaMarks.h
中工具附带的标头。include/
然后在最里面的感兴趣循环或感兴趣的直线块周围插入标记,如下所示:
/* C or C++ usage of IACA */
while(cond){
IACA_START
/* Loop body */
/* ... */
}
IACA_END
然后重新构建应用程序,就像启用优化一样(对于 Visual Studio 等 IDE 的用户,在发布模式下)。输出是一个二进制文件,除了存在使应用程序不可运行的标记外,在所有方面都与 Release 版本相同。
IACA 依赖于编译器不会过度重新排序标记;因此,对于此类分析构建,如果它们重新排序标记以包括不在最内层循环内的无关代码或排除其中的代码,则可能需要禁用某些强大的优化。
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
在开始标记之前和jne
结束标记之后立即添加标签。然后我们重新构建软件,并因此调用 IACA(在 Linux 上,假定bin/
目录位于路径中,并且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。此示例允许我们将问题诊断为端口 7 未处理存储,并采取补救措施。
IACA 不支持某些指令,这些指令在分析中被忽略。它不支持比 Nehalem 更早的处理器,并且不支持吞吐量模式下的非最内层循环(无法猜测哪个分支被采用的频率和模式)。