0Pricing
R Academy · Lekcja

Benchmarking za pomocą microbenchmark

Porównuj statystycznie wiele implementacji za pomocą microbenchmark().

Benchmarking za pomocą microbenchmark to bezpłatna lekcja R Academy na CoddyKit. To lekcja 4 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej R Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs R Academy zawiera 4 lekcji w sumie.

Dlaczego microbenchmark?

system.time() ma rozdzielczość milisekundową i jest niewiarygodny w przypadku szybkich operacji. Pakiet microbenchmark wykonuje wyrażenia setki razy, uwzględnia rozgrzewkę i raportuje statystyki z rozdzielczością nanosekundową — dlatego jest właściwym narzędziem do porównywania podobnych implementacji.

Podstawowe użycie microbenchmark

Do microbenchmark() należy przekazać nazwane wyrażenia. Nazwa każdego argumentu stanie się etykietą w danych wyjściowych. Argument times określa, ile razy każde wyrażenie zostanie obliczone.

# library(microbenchmark)
# x <- 1:10000
#
# microbenchmark(
#   loop = {
#     s <- 0
#     for (v in x) s <- s + v
#   },
#   vectorized = sum(x),
#   times = 200L
# )

Wybór argumentu times

Większa liczba powtórzeń zapewnia stabilniejsze oszacowania, ale wydłuża działanie. Ogólne wskazówki:

  • Szybkie wyrażenia (mikrosekundy): times = 1000L lub więcej
  • Umiarkowanie szybkie (milisekundy): times = 100L
  • Wolne (sekundy): times = 10L lub mniej

Wartością domyślną jest times = 100L, co stanowi dobry punkt wyjścia.

# 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
# )

Określanie argumentu unit

Argument unit służy do wyświetlania wyników w wygodnej skali:

  • 'ns' — nanosekundy (dla bardzo szybkich operacji)
  • 'us' — mikrosekundy
  • 'ms' — milisekundy
  • 's' — sekundy
  • 'relative' — stosunek do najszybszego wyrażenia
# library(microbenchmark)
# x <- runif(1000)
#
# microbenchmark(
#   sapply_sqrt = sapply(x, sqrt),
#   vectorized  = sqrt(x),
#   times = 500L,
#   unit = 'us'   # display in microseconds
# )

Interpretacja podsumowania wyników

microbenchmark wyświetla tabelę podsumowania z następującymi kolumnami:

  • min — czas najkrótszego pojedynczego uruchomienia
  • lq / mean / median / uq — kwartyl dolny, średnia, mediana, kwartyl górny
  • max — czas najdłuższego pojedynczego uruchomienia
  • neval — liczba obliczeń

Jako główną miarę porównawczą należy stosować median — jest odporna na sporadyczne pauzy GC, które zawyżają wartości max i 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() dla obiektu microbenchmark

Wywołanie summary(mb) dla zapisanego wyniku microbenchmark zwraca ramkę danych, którą można analizować programowo. W wywołaniu podsumowania można również zmienić unit.

# 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() do porównania wizualnego

autoplot(mb) używa ggplot2 do narysowania wykresu skrzypcowego lub pudełkowego rozkładów czasów dla poszczególnych wyrażeń. Ułatwia to dostrzeżenie nie tylko różnic median, lecz także zmienności i nakładania się wyników alternatywnych implementacji.

# 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 chart

Porównanie pętli, vapply i sapply

Klasyczny benchmark polega na zastosowaniu funkcji do poszczególnych elementów za pomocą pętli for, sapply() lub vapply(). vapply() jest szybsza niż sapply(), ponieważ wcześniej alokuje wektor wynikowy. Obie funkcje są wolniejsze niż w pełni zwektoryzowany kod.

# 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)

Najpierw sprawdzenie poprawności

Przed wykonaniem benchmarku należy sprawdzić, czy wszystkie wyrażenia zwracają identyczne wyniki. Szybsza, ale niepoprawna implementacja jest bezużyteczna. Do porównania wyników należy użyć identical() lub all.equal().

# 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
')

Benchmarkowanie z argumentem setup

Argument setup służy do jednokrotnego wykonania kodu przed mierzonymi wyrażeniami. Dzięki temu czas tworzenia danych nie zostanie uwzględniony w benchmarku, jeśli samo tworzenie danych nie jest przedmiotem pomiaru.

# 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_order

Raportowanie benchmarków w analizie

Udostępniając wyniki benchmarku, należy zawsze podać:

  • Wersję R i platformę
  • Wersje pakietów
  • Użytą wartość times
  • Rozmiar testowanego zbioru danych

Czasy wykonania nie są przenośne między komputerami — podczas porównywania implementacji należy raportować stosunki, a nie wartości bezwzględne.

cat('R version    :', R.version$version.string, '
')
cat('Platform     :', R.version$platform, '
')
cat('Logical cores:', parallel::detectCores(), '
')

Szybkie sprawdzenie: miara microbenchmark

Jóra statystyka podsumowania z wyników microbenchmark jest najbardziej wiarygodna przy porównywaniu dwóch implementacji?

Powtórzenie: microbenchmark

microbenchmark to standardowe narzędzie do rygorystycznego mikrobenchmarkowania w R:

  • Należy przekazywać nazwane wyrażenia i ustawiać times, aby kontrolować liczbę powtórzeń
  • Należy używać unit = 'us' lub 'ms', aby uzyskać czytelne wyniki
  • Należy porównywać mediany — są odporne na wartości odstające związane z GC
  • Należy używać autoplot() do wizualizacji rozkładów czasów
  • Przed benchmarkiem należy sprawdzić poprawność za pomocą all.equal()

Często zadawane pytania

Czy lekcja „Benchmarking za pomocą microbenchmark” jest bezpłatna?

Tak — pełny tekst „Benchmarking za pomocą microbenchmark” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu R Academy, przejdź na CoddyKit PRO. Kurs R Academy zawiera 4 lekcji w sumie.

Co nauczysz się w „Benchmarking za pomocą microbenchmark”?

Porównuj statystycznie wiele implementacji za pomocą microbenchmark(). Ćwiczysz R Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.

Czy potrzebuję doświadczenia, aby zacząć R Academy?

Nie wymagamy żadnego doświadczenia. R Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 4 z 4.

Ile czasu zajmuje lekcja „Benchmarking za pomocą microbenchmark”?

Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.

Czy mogę pisać i uruchamiać kod w tej lekcji R Academy?

Tak. Każda lekcja R Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.

Wszystkie lekcje w tym kursie

  1. system.time() i proc.time()
  2. Profilowanie kodu za pomocą Rprof i profvis
  3. Wektoryzacja na potrzeby wydajności
  4. Benchmarking za pomocą microbenchmark
← Powrót do R Academy