【问题标题】:Benchmarking - How to count number of instructions sent to CPU to find consumed MIPS基准测试 - 如何计算发送到 CPU 的指令数以查找消耗的 MIPS
【发布时间】:2018-10-05 18:54:39
【问题描述】:

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

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

起初,我想为我的特定算法找到每个周期的指令数。然后我意识到使用块盒方法几乎不可能计算它,我需要对算法进行深入分析。

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

任何脚本或工具推荐都将不胜感激(使用任何语言)。

【问题讨论】:

  • perf stat ./my_program 在 Linux 上将使用 CPU 性能计数器来记录它运行了多少指令,以及它花费了多少核心时钟周期。 (以及它使用了多少 CPU 时间,因此您可以获得 MIPS)。
  • @PeterCordes 完美!非常感谢。如何在运行时获取实时信息?
  • 你的意思是从程序内部,只分析它的一部分?有一个perf API,您可以在其中执行perf_event_open 或其他操作。或者使用不同的库直接访问硬件性能计数器。通常我通过将热循环放在一个运行大量迭代的程序中来对我正在调整的代码进行微基准测试,所以我通常不这样做。
  • re: 指令类型:Intel CPU 至少有一个分支指令计数器,但除 FP 指令外,其他类型没有区别。例如使用ocperf.py,您可以使用ocperf.py stat -e task_clock,cycles,instructions,fp_arith_inst_retired.128b_packed_single,fp_arith_inst_retired.scalar_double,uops_executed.x87 ./my_program 对于精确的动态指令计数,如果您使用的是 x86,则可以使用英特尔 PIN 之类的检测工具。 software.intel.com/en-us/articles/….

标签: performance assembly profiling cpu benchmarking


【解决方案1】:

Linux 上的perf stat --all-user ./my_program 将使用 CPU 性能计数器来记录它运行了多少用户空间指令,以及它花费了多少核心时钟周期。以及它使用了多少 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, ... 让那些特定的事件只在用户空间计数,而其他事件可以一直计数,包括内部中断处理程序和系统调用.)

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


有关在静态可执行文件中的微型微基准循环中使用它的示例输出,请参阅Can x86's MOV really be "free"? Why can't I reproduce this at all?

如何在运行时获取实时信息

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

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

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

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

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


是否可以找到指令集的类型(添加、比较、输入、跳转等)?

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

对于 Intel CPU,有 ocperf.py,它是 perf 的包装器,带有用于更多微架构事件的符号名称。 (更新: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

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

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

相关:


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

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

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


抱歉,我不知道 AMD CPU 上的等价物是什么。

【讨论】:

  • 非常感谢您的帮助。这些信息真的很有帮助。我的目的是使用黑盒方法对应用程序进行基准测试,因此我不能从应用程序本身内部使用 API。再次感谢。
  • @MichelGokan:我忘了提到perf stat -I 以获得“实时”更新;更新了我的答案。
  • perf stat ./my_program 没有返回计算出的MIPS 请参见示例输出(gist.github.com/avatar-lavventura/…)。为了计算MIPS,我应该遵循instructions/seconds_time_elapsed。 @PeterCordes
  • @alper:是的。对于大多数计数器perf 为您计算每秒,但对于指令,它计算每个时钟的平均指令,而不是秒。无论如何,这通常更有趣。
猜你喜欢
  • 2016-12-25
  • 1970-01-01
  • 2011-11-01
  • 1970-01-01
  • 2012-06-08
  • 2017-01-09
  • 2015-08-25
  • 1970-01-01
  • 2011-01-08
相关资源
最近更新 更多