尝试微基准测试结果不一致[已关闭]

问题描述 投票:0回答:3

我一直在尝试对 Lua 代码进行一些微基准测试,但遇到了一个非常烦人的问题:我似乎无法获得一致的结果。

示例:这是一个非常简单的 Lua 程序,应该对简单的斐波那契函数进行计时:

function pfibs(n)
  if n ~= math.floor(n) then return 0
  elseif n < 0 then return pfibs(n + 2) - pfibs(n + 1)
  elseif n < 2 then return n
  else return pfibs(n - 1) + pfibs(n - 2)
  end
end
t = os.clock()
pfibs(30)
t = os.clock() - t
print("time: "..t)

当我尝试连续运行几次时,会发生这样的事情:

$ lua fib.lua
time: 1.265
$ lua fib.lua
time: 1.281
$ lua fib.lua
time: 1.343
$ lua fib.lua
time: 1.437
$ lua fib.lua
time: 1.562
$ lua fib.lua
time: 1.578
$ lua fib.lua
time: 1.64
$ lua fib.lua
time: 1.703
$ lua fib.lua
time: 1.75
$ lua fib.lua
time: 1.797
$ lua fib.lua
time: 1.796
$ lua fib.lua
time: 1.812
$ lua fib.lua
time: 1.89

(这只是一个例子,为简洁起见而进行了剪裁,但代表了我所看到的那种减速曲线)

开始时间约为 1.1 秒,最终远高于 2 秒。我所做的就是坐在这里反复按上回车键。如果我将测试包装在对

time
的调用中而不是使用 Lua 时钟,或者如果我让它循环几次以多花几秒钟,也会发生同样的事情;它似乎成比例地减慢。如果我离开一段时间,有时时间会倒退。有时不会(可能是因为我不知道要离开多久)。

这是在 Windows+MSYS 上。在 Ubuntu(同一台机器)上尝试此操作会导致不同的模式,但结果仍然非常不一致且无法使用(例如,测试需要 2 秒,然后 3.5 秒,然后 4 秒,然后 2.5 秒......)。在这两种情况下,任务管理器/top 都表明后台没有任何占用 CPU 的情况。 CPU 速度切换已禁用。

我做错了什么?我的机器很旧,但它不可能坏掉(如果是机器的故障,而且每个程序每秒都慢得多,我肯定会注意到它无法使用......)。


我实际上想做的事情:

我想要做的是了解解释器的实现,从普通 Lua 开始,然后对其进行调整,看看变化对解释器性能有何影响。正如你所看到的,我还没有通过“建立控制”,所以我实际上还没有做任何事情 - 由于基准方差与上述一样高,我所做的任何更改都将完全丢失在噪音。我选择 Lua 是因为虽然它是一个现实世界的程序,但它也很小并且易于阅读和修改。如果有更好的基础解释器可以执行此操作,或者有确定的最佳方法来对解释器性能进行基准测试,请随时在答案中添加相关建议。

编辑:

添加
C

标签,因为使用传统 C 计时实用程序的 C 程序中也会发生同样的事情,例如: #include <time.h> #include <stdio.h> int fib(int n) { return n > 2 ? fib(n - 1) + fib(n - 2) : n; } int main(void) { clock_t t1, t2; const int ITNS = 30; for (int i = 0; i < ITNS; i ++) { t1 = clock(); fib(38); t2 = clock(); printf("time: %d\n", (int)((t2 - t1) / (CLOCKS_PER_SEC / 1000))); } return 0; }


...打印以下内容:

time: 687
time: 688
time: 687
time: 688
time: 671
time: 688
time: 687
time: 688
time: 672
time: 687
time: 688
time: 687
time: 672
time: 688
time: 687
time: 688
time: 672
time: 796
time: 766
time: 719
time: 969
time: 1000
time: 1015
time: 1000
time: 1016
time: 1000
time: 1000
time: 1015
time: 1000
time: 1000

这表明效果不限于单独运行。我想这意味着机器或操作系统有问题。


你的程序在我的 Xeon E7-4850 机器上似乎非常稳定

c lua benchmarking microbenchmark
3个回答
3
投票

但是,我建议您在运行基准测试时检查是否启用了

cpu-Frequency-scaling
 或类似 
turbo boost

的功能。我们之前也遇到过类似的问题,但是当我们关闭 cpu 频率缩放时,基准测试变得稳定。在 Linux 上,您可以使用 cpufrequtils 将其关闭。 另外,如果你使用的是 AMD 机器,我建议直接换成 intel 机器,因为即使 cpu 频率是固定的,lua 程序的性能对于我们的 Opteron 8431 来说仍然不稳定。所以这个问题可能取决于硬件平台,但不是 Lua 解释器本身。

编辑:

我认为最好在每次迭代后读取并打印当前的cpu频率(来自/proc/cpuinfo或/dev/cpu/#/msr)以确保频率稳定。 C 程序的结果有两个明显的稳定阶段。看起来 run19 后发生了一些事情,CPU 频率降低了。

enter image description here不确定这在技术上在多大程度上是一个“解决方案”,但是:


0
投票

使用CPU-Z,我注意到温度似乎也在突然下降的同时飙升。它仅从 60 度跃升至 72 度(在

据称可达 100 度的 CPU 上

),但相关性确实存在。当频率锁定为低时,这种情况就不会再发生,减速也不会发生。

我认为这个问题可以归结为“我的计算机又旧又不可靠”,并且应该关闭该问题,因为它显然根本不是一个真正的一般编程问题。 谢谢你的帮助。

基于

rdtsc

-1
投票
您可以按照以下方式使用重新定义的

os.clock

 函数在 LuaJIT 中尝试基准测试
(只需设置
CPU_speed
 常量即可显示合理的时间值):

-- New os.clock() implementation based on rdtsc instruction, LuaJIT required do local CPU_speed = 3.0 -- Your CPU TSC speed in GHz (may differ from CPU core speed) local rdtsc = require'ffi'.cast( '__cdecl uint64_t(*)()', '\x0F\x31\xC3' -- rdtsc, ret ) -- This trick may not work on modern 64-bit OS local rdtsc0 = rdtsc() os.clock = function() return tonumber(rdtsc() - rdtsc0)/(CPU_speed * 10^9) end end
    

© www.soinside.com 2019 - 2024. All rights reserved.