Benchmark con microbenchmark
Confronti statisticamente più implementazioni con microbenchmark()
Benchmark con microbenchmark è una lezione R Academy gratuita su CoddyKit. Questa è la lezione 4 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento R Academy, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso R Academy include 4 lezioni in totale.
Perché usare microbenchmark?
system.time() ha una risoluzione al millisecondo e non è affidabile per le operazioni rapide. Il pacchetto microbenchmark esegue le espressioni centinaia di volte, gestisce il riscaldamento e restituisce statistiche con risoluzione al nanosecondo: è quindi lo strumento adatto per confrontare implementazioni simili.
Uso di base di microbenchmark
Passi espressioni con nome a microbenchmark(). Il nome di ogni argomento diventa l'etichetta nell'output. L'argomento times controlla quante volte viene valutata ciascuna espressione.
# library(microbenchmark)
# x <- 1:10000
#
# microbenchmark(
# loop = {
# s <- 0
# for (v in x) s <- s + v
# },
# vectorized = sum(x),
# times = 200L
# )Scelta dell'argomento times
Un numero maggiore di ripetizioni produce stime più stabili, ma richiede più tempo. Indicazioni generali:
- Espressioni rapide (microsecondi):
times = 1000Lo più - Espressioni moderate (millisecondi):
times = 100L - Espressioni lente (secondi):
times = 10Lo meno
Il valore predefinito è times = 100L, un buon punto di partenza.
# library(microbenchmark)
# microbenchmark(
# fast_op = sqrt(2),
# times = 10000L # many reps for a nanosecond-scale operation
# )
# microbenchmark(
# slow_op = sort(rnorm(1e6)),
# times = 10L # fewer reps for second-scale operation
# )Specifica dell'argomento unit
Usi l'argomento unit per visualizzare i risultati su una scala comoda:
'ns'— nanosecondi (per operazioni molto rapide)'us'— microsecondi'ms'— millisecondi's'— secondi'relative'— rapporto rispetto all'espressione più veloce
# library(microbenchmark)
# x <- runif(1000)
#
# microbenchmark(
# sapply_sqrt = sapply(x, sqrt),
# vectorized = sqrt(x),
# times = 500L,
# unit = 'us' # display in microseconds
# )Interpretazione dell'output di riepilogo
microbenchmark stampa una tabella di riepilogo con queste colonne:
- min — singola esecuzione più veloce
- lq / mean / median / uq — quartile inferiore, media, mediana, quartile superiore
- max — singola esecuzione più lenta
- neval — numero di valutazioni
Usi median come metrica principale per il confronto: è robusta rispetto alle pause occasionali del GC, che fanno aumentare max e mean.
# Example summary output (unit: microseconds):
#
# expr min lq mean median uq max neval
# loop 1203.1 1245.3 1301.7 1262.4 1310.1 2100.8 100
# vectorized 2.1 2.3 2.9 2.4 2.6 18.3 100
#
# => vectorized is ~525x faster at median
cat('Always compare medians, not means, for microbenchmark results
')summary() su un oggetto microbenchmark
Chiamare summary(mb) su un risultato microbenchmark memorizzato restituisce un data frame che può essere analizzato programmaticamente. Può anche modificare unit nella chiamata a summary.
# library(microbenchmark)
# x <- rnorm(5000)
# mb <- microbenchmark(
# vapply_abs = vapply(x, abs, numeric(1)),
# base_abs = abs(x),
# times = 200L
# )
# s <- summary(mb, unit = 'ms')
# print(s[, c('expr', 'min', 'median', 'max')])autoplot() per il confronto visivo
autoplot(mb) usa ggplot2 per disegnare un violin plot o un box plot delle distribuzioni dei tempi tra le espressioni. In questo modo è facile osservare non solo le differenze tra le mediane, ma anche la variabilità e la sovrapposizione tra le alternative.
# library(microbenchmark)
# library(ggplot2)
#
# x <- 1:50000
# mb <- microbenchmark(
# loop = { s <- 0; for (v in x) s <- s + v },
# vapply = vapply(x, identity, numeric(1)),
# vec = sum(x),
# times = 100L
# )
# autoplot(mb) # opens ggplot2 violin chartConfronto tra ciclo, vapply e sapply
Un benchmark classico consiste nell'applicare una funzione elemento per elemento usando un ciclo for, sapply() o vapply(). vapply() è più veloce di sapply() perché prealloca il vettore dei risultati. Entrambe sono più lente del codice completamente vettorializzato.
# library(microbenchmark)
# x <- runif(5000, 1, 100)
#
# mb <- microbenchmark(
# for_loop = {
# r <- numeric(length(x))
# for (i in seq_along(x)) r[i] <- log(x[i])
# },
# sapply_log = sapply(x, log),
# vapply_log = vapply(x, log, numeric(1)),
# vec_log = log(x),
# times = 200L, unit = 'us'
# )
# print(mb)Verifica preliminare della correttezza
Prima di eseguire il benchmark, verifichi che tutte le espressioni restituiscano risultati identici. Un'implementazione più veloce ma errata è inutile. Usi identical() o all.equal() per confrontare gli output.
# x <- runif(1000)
# r1 <- sapply(x, sqrt)
# r2 <- sqrt(x)
# r3 <- vapply(x, sqrt, numeric(1))
#
# stopifnot(isTRUE(all.equal(r1, r2)))
# stopifnot(isTRUE(all.equal(r1, r3)))
# cat('All three produce identical results -- safe to benchmark
')
cat('Always verify correctness before comparing speed
')Benchmark con l'argomento setup
Usi l'argomento setup per eseguire il codice una volta prima delle espressioni cronometrare. In questo modo evita di includere nel benchmark il tempo di creazione dei dati, quando la creazione dei dati non è ciò che sta misurando.
# library(microbenchmark)
#
# microbenchmark(
# sort_base = sort(x),
# sort_order = x[order(x)],
# setup = { x <- rnorm(10000) },
# times = 100L
# )
# Each iteration refreshes x via setup, then times sort_base and sort_orderCome riportare i benchmark nell'analisi
Quando condivide i risultati di un benchmark, riporti sempre:
- La versione e la piattaforma R
- Le versioni dei pacchetti
- Il valore di
timesutilizzato - La dimensione dei dati sottoposti a benchmark
I tempi non sono trasferibili da una macchina all'altra: quando confronta le implementazioni, riporti i rapporti anziché i valori assoluti.
cat('R version :', R.version$version.string, '
')
cat('Platform :', R.version$platform, '
')
cat('Logical cores:', parallel::detectCores(), '
')Controllo rapido: metrica di microbenchmark
Quale statistica di riepilogo dell'output di microbenchmark è più affidabile per confrontare due implementazioni?
Riepilogo di microbenchmark
microbenchmark è lo strumento standard per eseguire micro-benchmark rigorosi in R:
- Passi espressioni con nome e imposti
timesper controllare le ripetizioni - Usi
unit = 'us'o'ms'per un output leggibile - Confronti le mediane: sono robuste rispetto ai valori anomali dovuti al GC
- Usi
autoplot()per visualizzare le distribuzioni dei tempi - Verifichi la correttezza con
all.equal()prima del benchmark
Domande Frequenti
La lezione «Benchmark con microbenchmark» è gratuita?
Sì — il testo completo di «Benchmark con microbenchmark» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso R Academy, passa a CoddyKit PRO. Il corso R Academy include 4 lezioni in totale.
Cosa imparerò in «Benchmark con microbenchmark»?
Confronti statisticamente più implementazioni con microbenchmark() Eserciti R Academy con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.
Ho bisogno di esperienza per iniziare R Academy?
Non è richiesta alcuna esperienza precedente. R Academy su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 4 di 4.
Quanto tempo richiede la lezione «Benchmark con microbenchmark»?
La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.
Posso scrivere ed eseguire codice in questa lezione R Academy?
Sì. Ogni lezione R Academy include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.
Tutte le lezioni di questo corso
- system.time() e proc.time()
- Profilazione del codice con Rprof e profvis
- Vettorizzazione per aumentare la velocità
- Benchmark con microbenchmark