基准测试 - 如何计算发送到 CPU 的指令数以查找消耗的 MIPS

Benchmarking - How to count number of instructions sent to CPU to find consumed MIPS

假设我有一个软件,想使用 black-box 方法研究它的行为。我有一个 3.0GHz CPU,带有 2 个插槽和 4 个内核。如您所知,为了找出每秒指令数 (IPS),我们必须使用以下公式:

IPS = sockets*(cores/sockets)*clock*(instructions/cycle)

起初,我想为我的特定算法找到每个周期的指令数。然后我意识到用block-box的方法来计算它几乎是不可能的,我需要对算法做深入的分析。

但是现在,我有两个问题:无论我的机器上 运行 是什么类型的软件及其 cpu 用法,有没有办法计算每秒发送到的指令数CPU(每秒百万条指令 (MIPS))?是否可以找到指令集的类型(添加、比较、输入、跳转等)?

如有任何脚本或工具推荐(任何语言),我们将不胜感激。

Linux 上的

perf stat --all-user ./my_program 将使用 CPU 性能计数器来记录它 运行 有多少用户-space 指令,以及有多少核心时钟周期花了。以及它使用了多少 CPU 时间,并将为您计算每个核心时钟周期的平均指令数,例如

3,496,129,612      instructions:u            #    2.61  insn per cycle

它为你计算IPC;这通常比每 的指令更有趣。 uops 每个时钟通常更有趣,但就您离最大化前端的接近程度而言。 您可以根据 instructionstask-clock 手动计算 MIPS。 对于大多数其他事件,perf 以每秒速率打印注释。

(如果你不使用 --all-user,你可以使用 perf stat -e task-clock:u,instructions:u ,...让这些特定事件仅在 user-space 中计数,而其他事件可以总是计数,包括内部中断处理程序和系统调用。)

但如果您确实想要跨内核的总 MIPS 或平均 MIPS,以及是否计算睡眠,请参阅 了解有关 instructions / task-clockinstructions / elapsed_time 的更多详细信息。


有关在静态可执行文件中的微型基准测试循环中使用它的示例输出,请参阅

How can I get real-time information at run-time

你的意思是从程序内部,只分析它的一部分吗?有一个 perf API,你可以在其中执行 perf_event_open 或其他操作。或者使用不同的库直接访问硬件性能计数器。

perf stat 非常适合对已隔离到独立程序中的循环进行微基准测试,该程序只是 运行 热循环一秒钟左右。

或者您可能有其他意思。 perf stat -I 1000 ... ./a.out 将每 1000 毫秒(1 秒)打印一次计数器值,以查看程序行为如何实时变化 以及您想要的任何时间 window(低至 10 毫秒)间隔)。

sudo perf top 是系统范围的,有点像 Unix top

还有 perf record --timestamp 记录每个事件样本的时间戳。 perf report -D 可能与此一起有用。看到http://www.brendangregg.com/perf.html,他提到了一些关于-T--timestamp)的事情。我还没有真正使用过这个;我主要隔离单个循环 我正在调整为静态可执行文件 我可以 运行 在 perf stat.


And is it possible to find the type of instruction set (add, compare, in, jump, etc)?

Intel x86 CPUs 至少有一个 b运行ch 指令的计数器,但其他类型没有区别,除了 FP 指令。这对于大多数具有性能计数器的架构来说可能很常见。

对于英特尔 CPUs,有 ocperf.pyperf 的包装器,带有更多微体系结构事件的符号名称。 (更新:plain perf 现在知道大多数 uarch 特定计数器的名称,因此您不再需要 ocperf.py。)

perf stat -e task_clock,cycles,instructions,fp_arith_inst_retired.128b_packed_single,fp_arith_inst_retired.scalar_double,uops_executed.x87 ./my_program

它不是为了告诉你什么指令是运行宁,你已经可以从跟踪执行中知道。大多数指令都是完全流水线的,所以有趣的是哪些端口的压力最大。例外是 divide/sqrt 单元:arith.divider_active 有一个计数器:“除法单元忙于执行除法或平方根运算时的循环数。考虑整数和浮点运算”。分频器没有完全流水线化,所以即使没有旧的 uops 准备好在端口 0 上执行,新的 divpssqrtps 也不能总是启动。 (http://agner.org/optimize/)

相关:linux perf: how to interpret and find hotspots 使用 perf 识别热点。特别是使用自上而下的分析,您可以 perf 对调用堆栈进行采样,以查看哪些函数进行了大量昂贵的子调用。 (我提到这个是为了防止你真正想知道,而不是指令组合。)

相关:

  • How do I determine the number of x86 machine instructions executed in a C program?

对于精确的动态指令计数,如果您使用的是 x86,则可以使用像 Intel PIN 这样的检测工具。 https://software.intel.com/en-us/articles/pin-a-dynamic-binary-instrumentation-tool.

perf statinstructions:u 硬件的计数甚至应该或多或少是准确的,并且实际上在执行相同工作的同一程序的 运行 之间非常可重复。

在最近的 Intel CPUs 上,硬件支持记录条件/间接 b运行ches 的路径,因此您可以准确地重建哪些指令 运行 的顺序,假设没有自修改代码,并且您仍然可以读取任何 JIT 缓冲区。 Intel PT.


抱歉,我不知道 AMD CPUs 上的等效项是什么。