是否有一个标准的常量*nix基准,如果没有,如何制作一个“bogobench”



普通单线程*nix程序可以使用time等utils进行基准测试,即:

# how long does `seq` take to count to 100,000,000
/usr/bin/time seq 100000000 > /dev/null

输出:

1.16user 0.06system 0:01.23elapsed 100%CPU (0avgtext+0avgdata 1944maxresident)k
0inputs+0outputs (0major+80minor)pagefaults 0swaps

…但是返回的数字总是依赖于系统的,这在某种意义上也衡量了用户的硬件。

是否存在一些非相对基准测试方法或命令行util,它们在任何系统(或至少相当大的系统子集)上返回大约相同的虚拟计时数字?就像grep -m1 bogo /proc/cpuinfo返回一个大致近似但稳定的单位一样,这样的基准也应该返回一个类似的持续时间单位。

假设对普通命令进行基准测试,我们有一个神奇的uti_ bogobench(其中"bogo"是一个形容词,表示"某种伪状态",但不一定与BogoMIPs具有相同的算法):

bogobench foo bar.data

我们在两个物理上独立的系统上运行:

  1. a 1996 奔腾II
  2. a 2015 Xeon

期望的输出是这样的:

21 bogo-seconds

所以bogobench在两种情况下应该返回相同的数字,即使它在第二个系统上可能会在更短的时间内完成。


qemu这样的硬件模拟器可能是一种方法,但不一定是唯一的方法:

  1. 将基准测试代码插入包装器脚本bogo.sh
  2. bogo.sh复制到可引导的Linux磁盘映像bootimage。iso,在bogo.sh自动运行然后立即关闭模拟器的目录中。在此期间,它输出某种形式的计时数据以解析为bogo-seconds
  3. 运行bootimage。iso使用qemu的一个更小的-machine选项:

    qemu-system-i386 -machine type=isapc bootimage.iso
    

但是我不确定如何使qemu使用虚拟时钟,而不是主机CPU的时钟,并且qemu本身似乎是一个看似简单的任务的沉重工具。(对于这样的任务,MAMEMESS将是比qemu更通用的模拟器-但我不擅长MAME,尽管MAME目前有一些80486 PC仿真的容量。)

我们有时会在网上比较和对比在机器X和在机器Y上进行的基于时间的基准测试。然而,我希望用户XY能够在虚拟机器Z上进行基准测试,如果需要,可以模拟XY(就像MAME),除非不考虑XY的实际运行时间,(不像MAME,模拟通常是可玩的)。通过这种方式,用户可以报告程序在有趣的情况下的执行情况,而程序员不必担心结果会受到用户硬件特性的影响,例如CPU怪癖、后台进程占用资源等。 实际上,即使在用户的自己的硬件上,基于time的基准测试也可能是不可靠的,因为用户经常不能确定某些后台进程(或bug,或硬件错误,如坏扇区或病毒)可能不会降低某些方面的性能。然而,更虚拟的基准应该不太容易受到这种影响。

我认为实现这一点的唯一相同方法是使用某种硬件设计的周期精确模拟器。

我知道,没有针对现代x86硬件的公开的周期精确模拟器存在,因为它非常复杂,尽管有很多关于x86微架构内部的东西(Agner Fog的东西,Intel和AMD自己的优化指南,以及x86标签wiki中的其他东西),足够的行为仍然是一个充满cpu设计商业秘密的黑盒子,它最多可能模拟类似的东西。(例如,分支预测绝对是最秘密但非常重要的部分之一)。

虽然应该有可能接近模拟英特尔Sandybridge或Haswell的实际管道和无序核心/ROB/RS(比实时慢得多),但据我所知没有人这样做过。


但是其他硬件设计的周期精确模拟器确实存在: Donald Knuth的MMIX架构是一个干净的RISC设计,实际上可以在硅上构建,但目前只存在于纸上。

从该链接:

特别有趣的是MMMIX元模拟器,它能够对复杂的管道进行动态调度,允许使用任意数量的功能单元和多种缓存和分支预测等进行标量执行,包括硬中断和软中断的详细实现。

因此,您可以将其用作每个人运行基准测试的参考机器,并且每个人都可以获得可比较的结果,这些结果将告诉您在MMIX上运行的速度有多快(在使用gcc编译MMIX之后)。但不是它在x86上运行的速度有多快(可能也用gcc编译),即使两个程序以不同的方式完成相同的工作,也可能存在显著的差异。


对于编程谜题和代码高尔夫网站上的[fastest-code]挑战,@orlp创建了带有打印计时结果的模拟器的高尔夫架构,正是为了这个目的而设计的。这是一个玩具架构,比如通过存储到0xffffffffffffffff来打印到标准输出,所以它不一定会告诉你在任何实际硬件上运行的速度。

GOLF没有一个完整的C实现,所以你只能用手写的asm来使用它。这与MMIX有很大的不同,MMIX是优化编译器的目标。

一种可以(也许?)随着时间的推移扩展到更精确的实用方法是使用现有的工具来测量一些硬件不变性能指标,然后应用一个公式来得出您的bogoseconds分数。

不幸的是,大多数容易测量的硬件指标都是不是不变的——相反,它们取决于硬件。然而,一个显然应该保持不变的是"指令退役"。如果代码每次运行时都采用相同的代码路径,则所有硬件上的指令退役计数应该相同1

然后你应用某种名义时钟速度(假设1 GHz)和名义CPI(假设1.0)来获得你的bogoseconds -如果你测量15e9个指令,你输出的结果15 bogoseconds

这里的主要缺陷是名义CPI可能与实际CPI相差甚远!虽然大多数程序徘徊在1 CPI附近,但很容易找到它们可以接近0.25或宽度的倒数的例子,或者如果有许多冗长的停顿,则可以达到10或更多。当然,这种极端的程序可能是您想要进行基准测试的——即使不是这样,如果您使用基准测试来评估代码更改,它也会忽略CPI中的任何改进或回归,而只关注指令计数。

尽管如此,它还是满足了您的需求,因为它有效地模拟了一台每周期只执行一条指令的机器,也许这是一种合理的全局性方法。使用perf stat -e instructions这样的工具很容易实现(就像一行代码一样简单)。

为了弥补漏洞,你可以尝试使公式更好——假设你可以添加一个缓存缺失的因素来解释大量的停滞来源。不幸的是,您将如何以硬件不变的方式度量缓存缺失?性能计数器没有帮助——它们依赖于本地缓存的行为和大小。那么,您可以使用cachegrind以与机器无关的方式模拟缓存。事实证明,cachegrind甚至涵盖了分支预测。因此,也许您可以将指令计数、缓存丢失和分支丢失数字插入到一个更好的公式中(例如,使用典型的L2、L3、RAM延迟和分支丢失的典型成本)。

我想这就是这个简单的方法所能带给你的。在此之后,您不妨拆分任何现有的x862模拟器,并在其中添加简单的机器模型。你不需要精确的循环,只要选择一个标称的宽度和模型。可能无论底层模拟cachegrind是什么,都可能是一个很好的匹配,并且您已经免费获得了缓存和分支预测建模。


1当然,这并不排除指令计数机制中的错误或不准确。

2你没有标记你的问题x86 -但我要假设这是你的目标,因为你只提到英特尔芯片。

相关内容

  • 没有找到相关文章

最新更新