2012-11-01 53 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