2011-02-28 36 views
4

編輯:更新感謝@ daroczig下面的可愛答案。然而,測試2仍然覺得比測試1需要更長的時間,這是我想知道的。我的system.time包裝函數有問題嗎?

更新:在二讀時,@ daroczig的答案確實解釋了我的困惑 - 問題是由於我沒有正確地思考system.time(expr)代碼行。

我想作一個版本的system.time功能這將是對自己更豐富一點在理解方面運行到運行時間的波動:

system.time.summary <- function(N, expr) { 
    t.mat <- replicate(N, system.time(expr)) 
    as.data.frame(apply(t.mat[1:3,], 1, summary)) 
} 

然而問題是,在自我包含的代碼如下,test.2感覺喜歡它比test.1需要更長的時間(並且我已經運行了幾次來檢查),即使代碼幾乎完全相同(test.1使用包裝函數,而test.2只是原始代碼)

# set up number of runs 
N <- 100 

# test 1 
system.time.summary(N, (1:1e8)^2 + 1) 

     user.self sys.self elapsed 
Min.  0.000 0.000 0.000 
1st Qu.  0.000 0.000 0.000 
Median  0.000 0.000 0.000 
Mean  0.058 0.031 0.089 
3rd Qu.  0.000 0.000 0.000 
Max.  0.580 0.310 0.890 

# test 2 
t.mat = replicate(N, system.time((1:1e8)^2 + 1)) 
as.data.frame(apply(t.mat[1:3,], 1, summary)) 

     user.self sys.self elapsed 
Min.  0.630 0.120 0.860 
1st Qu.  0.665 0.170 0.880 
Median  0.695 0.195 0.880 
Mean  0.692 0.196 0.882 
3rd Qu.  0.715 0.225 0.890 
Max.  0.760 0.260 0.900 

我希望我解釋一下OK!這可能是因爲它是目前星期一早上,但這是混淆了我...

我的系統:

# Windows Server 2008 R2 
> sessionInfo() 
R version 2.12.0 (2010-10-15) 
Platform: x86_64-pc-mingw32/x64 (64-bit) 

回答

2

正如daroczig說,你有一個額外system.time。但還有其他的東西:

如果你把browser()放在你的函數中,你會看到會發生什麼。事實上,你所做的表達只被評估一次,然後保存在記憶中。這是R如何在內部進行優化。所以,如果你這樣做:

system.time.summary(N,(1:1e8)^2 +1) 

t.mat內部是:

和expr是:

Browse[2]> str(expr) 
num [1:100000000] 2 5 10 17 26 37 50 65 82 101 ... 

這是一個有點難以改變這一點,因爲R將評估任何靜態表達式只有一次,然後從內存中再次檢索結果99次。如果您不希望發生這種情況,則必須明確傳遞一個表達式,並添加eval()函數。:

system.time.summary <- function(N, expr) { 
    t.mat <- replicate(N, system.time(eval(expr))) 
    as.data.frame(apply(t.mat[1:3,], 1, summary)) 
} 

system.time.summary(N, expression((1:1e8)^2 + 1)) 

現在EXPR被評估每一次,並保持在函數的表達式:

Browse[2]> expr 
expression((1:1e+08)^2 + 1) 

這給你正確的時機。

 user.self sys.self elapsed 
Min.  0.6400 0.2000 0.970 
1st Qu. 0.6850 0.2375 0.980 
Median  0.7150 0.2700 0.985 
Mean  0.7130 0.2700 0.985 
3rd Qu. 0.7425 0.2975 0.990 
Max.  0.7800 0.3500 1.000 
+0

掛起,你的意思是說我基本上可以在R裏面調試嗎?我不知道!有多少R在那裏,我不知道... – 2011-02-28 14:08:54

+3

@Tony:如果你不知道,那麼現在是時候看看:?traceback,?debug,?debugonce,?瀏覽器和http ://stackoverflow.com/questions/1882734/what-is-your-favorite-r-debugging-trick(加上你在網站上使用'[r] debug'作爲搜索條件找到的所有其他人)享受:-) – 2011-02-28 14:11:46

+0

爲伴侶歡呼,看起來像我將不得不抽時間閱讀所有這些非常有趣和非常有用的功能,我從未聽說過! :) – 2011-02-28 14:27:01

7

您在拳頭測試運行system.time(system.time()),並且還具有system.time(1:1e8)^2 + 1)作爲函數的表達式這不是一個好主意,請參見:

​​

但不管怎麼說:使用來自CRAN的microbenchmark包這樣的目的,你不會後悔。設置你獨特的功能,你可以輕鬆地推出你的模擬100,1000或任何運行。在基準測試結束時,您可以獲得簡潔的總結和箱櫃圖。

例如:

> test1 <- function() (1:1e8)^2 + 1 
> (results <- microbenchmark(test1(), times=10)) 
Unit: nanoeconds 
       min   lq  median   uq  max 
test1() 3565386356 3703142531 3856450582 3931033077 3986309085 
> boxplot(results) 

enter image description here

+1

我的天啊,我不知道有一個microbenchmark包,謝謝!你在第一次測試中對system.time(system.time())是非常正確的,但即使我刪除了它,測試2仍然感覺比測試1更長。 – 2011-02-28 13:35:48

+0

重新閱讀你的答案,我相信它確實回答了我的問題因爲我沒有正確地考慮system.time(expr)代碼行。接受答覆,非常感謝您的時間和幫助。 – 2011-02-28 13:51:27

+2

在你的函數中,expr只能得到一次評估,在函數之外,表達式被評估n次。 – hadley 2011-02-28 13:53:02