2012-11-01 55 views
2

我正在研究Project Euler,并想知道是否可以使用PyPy加速我的解决方案。然而,我发现结果令人失望,因为计算需要更多时间。PyPy显示不准确的基准测试结果?

d:\projeuler>pypy problem204.py 
3462.08630405 mseconds 

d:\projeuler>python problem204.py 
1823.91602542 mseconds 

由于mseconds输出使用python的time模块计算,所以我跑再次使用内置基准命令。

d:\projeuler>pypy -mtimeit -s "import problem204" "problem204._main()" 
10 loops, best of 3: 465 msec per loop 

d:\projeuler>python -mtimeit -s "import problem204" "problem204._main()" 
10 loops, best of 3: 1.87 sec per loop 

PyPy报告说花了大约半秒才能完成运行。但是,我尝试过多次运行pypy problem204,输出甚至从未接近基准测试.5秒。与pypy不同,python的mtimeit结果与输出一致。 Pypy给我不准确的基准,还是有一些我不明白的魔法?

回答

5

注意timeit

  1. 运行语句多次(在你的案件10),和
  2. 确实是多次(3默认情况下),并给出了最低的那个,原因outlined in the documentation

这取决于你的代码,但是完全有可能是因为这个令人困惑的结果而引起JIT编译器。每次启动新的pypy进程时,都会发生JIT预热开销,但在timeit基准测试期间只会发生一次(因为该进程在同一进程中多次运行_main)。而且,如果代码的某些部分运行得太频繁,以至于在运行一次而不是编译时,只有在运行时(例如三次),后续运行也会更快,这进一步消除了第一次运行的最佳结果(即一次运行pypy problem204.py一次)。

timeit结果是正确的,因为它(大致)相匹配的代码将如何快速在最好的情况下 - 暖机的JIT编译器,很少失去了CPU到其他程序等 你的问题是,你想了解不同的时间 - 包括JIT热身时间。

+1

+1。如果你需要比较像web应用程序那样无限期运行的程序的子程序的速度,以及像这样运行一次的程序的命令行“time”包装器(不是python模块),我会使用'timeit' 。 –

+0

@AndrewGorcester同意,尽管在某些平台上“时间”令人遗憾地不可用(*咕噜* Windows *咕* *)。 Powershell显然有一个相同的,但我还没有弄清楚它是如何工作的。 – delnan

+1

请注意,timeit只做更少的事情(如在CPython中禁用GC)。此外,由于在多篇论文中列出的原因,最小值是不正确的(例如你有一个gc每3个循环收集一次,然后最小值会跳过硬的)。 PyPy没有修改timeit,但是对于带JIT编译器的解释器来说,它更没有意义。 – fijal