2012-04-28 15 views
6

Sono sempre stato disturbato un po 'dalla mancanza di accuratezza che vedo il benchmark con system.time e rbenchmark (nel senso che la precisione dei tempi potrebbe mancare) e ho visto Hadley fare riferimento al pacchetto microbenchmark di recente. Così ho deciso di dargli un vortice come visto di seguito. Ho snocciolato lo mean contro f <- function(x) {sum(x)/length(x)} e atteso mean per fare meglio di f ma i risultati, così come li ho capiti, non indicano che questo è vero.risultati imprevisti: microbenchmark

  1. Sono frainteso i risultati?
  2. È effettivamente più veloce della media?
  3. Il microbenchmark è ancora in fase beta e deve essere stirato fuori?

Sto eseguendo R2.15 su una macchina di successo 7 (come microbenchmark fa orari in modo diverso a seconda del sistema operativo).

I risultati

Unit: microseconds 
    expr min  lq median  uq max 
1 f(x) 19.130 20.529 20.529 20.996 286.00 
2 mean(x) 28.927 29.860 30.327 30.327 672.31 

Il Codice

library(microbenchmark) 

x <- 1:10000 
f <- function(x) {sum(x)/length(x)} 
mean(x) 

res <- microbenchmark(
    mean(x), 
    f(x), 
times=1000L) 

print(res) 
boxplot(res) 
+0

Mi piace 'microbenchmark'. Se stai facendo più di uno o due risultati, il plotting può essere di grande aiuto, ma l'output di default è un po 'brutto. Ho scritto una funzione autoplot per ggplot2 che potrebbe apparire in una di queste versioni (controlla github nel frattempo). Esempi: http://stackoverflow.com/a/6919493/636656 –

+0

Questo potrebbe spiegarlo http://radfordneal.wordpress.com/2014/02/02/inaccurate-results-from-microbenchmark/ – Momo

+0

Probabilmente non come tutte le statistiche poiché 'f' era più basso e uno scatterplot lo indicava. Joran ha inchiodato questo. –

risposta

8

potrei sbagliarmi, ma questo non sembra così sorprendente per me. Prima di mean.default è possibile chiamare .Internal(mean(x)) deve controllare 3 if istruzioni, calcolare la lunghezza di x e quindi controllare un'altra istruzione if. E la differenza in tempi è abbastanza piccola.

Calling .Internal(mean(x) è direttamente leggermente ancora più veloce:

library(microbenchmark) 

x <- 1:10000 
f1 <- function(x) {sum(x)/length(x)} 
f2 <- function(x) {.Internal(mean(x))} 

res <- microbenchmark(
    mean(x), 
    f1(x), 
    f2(x), 
times=1000L) 

print(res) 

Unit: microseconds 
    expr min  lq median  uq  max 
1 f1(x) 32.195 32.4605 32.8850 33.4645 106.997 
2 f2(x) 21.840 22.0580 22.2015 22.6270 55.316 
3 mean(x) 35.393 35.9840 36.1860 36.4420 91.203 
+0

Grazie. Ho fatto un'ipotesi e non l'ho controllato. Una migliore verifica del microbenchmarking sarebbe 'sum' contro una versione' Reduce': 'sum2 <- function (x) Reduce (" + ", x)' che produce i risultati attesi. Penso che mi piacerà 'microbenchmark' –

+1

Ho appena finito di leggere questo in letture non correlate. Apparentemente significa è un po 'famoso: http: //lookingatdata.blogspot.se/2011/04/speeding-up-r-computations.html –

2

penso che troverete che se si imbatterà la dimensione di X di un fattore 10 vedrete risultati più coerenti. Ad essere onesti, sarei sorpreso se riuscissi davvero a ottenere un'accuratezza dei tempi di micro-secondi su un computer con un sistema operativo multitasking.

Si potrebbe anche prendere in considerazione:

  • stai eseguendo su un computer portatile o di una macchina che ha il ridimensionamento automatico della frequenza della CPU?
  • Riscaldamento?
  • Appuntare il processo su un nucleo.
+0

Parte della bellezza di 'microbenchmark' è che esegue le cose un sacco di volte in modo da poter vedere come variano i risultati, quindi immagino che ciò che è in esecuzione sullo sfondo non ha alcun effetto sui risultati in attesa. –

+0

@ gsk3 dai un'occhiata ai tempi di output e vedrai una coda lunga, quindi qualcosa come ... hist (res [res $ expr == 'f (x)', 'time']/length (x), pause = 90) – Sean

+0

Certo, ma la mediana è probabilmente una stima abbastanza buona, no? –

Problemi correlati