Бенчмаркинг с помощью microbenchmark
Статистически сравнивайте несколько реализаций с помощью microbenchmark()
«Бенчмаркинг с помощью microbenchmark» — бесплатный урок R Academy на CoddyKit. Это урок 4 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения R Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс R Academy содержит 4 уроков всего.
Зачем нужен microbenchmark?
Функция system.time() измеряет время с точностью до миллисекунд и ненадёжна для быстрых операций. Пакет microbenchmark выполняет выражения сотни раз, учитывает прогрев и сообщает статистику с точностью до наносекунд — поэтому он подходит для сравнения похожих реализаций.
Основы использования microbenchmark
Передайте именованные выражения в microbenchmark(). Имя каждого аргумента станет меткой в выводе. Аргумент times задаёт, сколько раз вычисляется каждое выражение.
# library(microbenchmark)
# x <- 1:10000
#
# microbenchmark(
# loop = {
# s <- 0
# for (v in x) s <- s + v
# },
# vectorized = sum(x),
# times = 200L
# )Выбор аргумента times
Большее число повторений даёт более стабильные оценки, но увеличивает время выполнения. Общие рекомендации:
- Быстрые выражения (микросекунды):
times = 1000Lили больше - Умеренно быстрые (миллисекунды):
times = 100L - Медленные (секунды):
times = 10Lили меньше
По умолчанию используется times = 100L — это хорошая отправная точка.
# 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
# )Задание аргумента unit
Используйте аргумент unit, чтобы отображать результаты в удобном масштабе:
'ns'— наносекунды (для очень быстрых операций)'us'— микросекунды'ms'— миллисекунды's'— секунды'relative'— отношение ко времени самого быстрого выражения
# library(microbenchmark)
# x <- runif(1000)
#
# microbenchmark(
# sapply_sqrt = sapply(x, sqrt),
# vectorized = sqrt(x),
# times = 500L,
# unit = 'us' # display in microseconds
# )Интерпретация сводного вывода
microbenchmark выводит сводную таблицу со следующими столбцами:
- min — самый быстрый отдельный запуск
- lq / mean / median / uq — нижний квартиль, среднее, медиана, верхний квартиль
- max — самый медленный отдельный запуск
- neval — число вычислений
Используйте median как основной показатель для сравнения: он устойчив к случайным паузам сборщика мусора, которые завышают max и 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() для объекта microbenchmark
Вызов summary(mb) для сохранённого результата microbenchmark возвращает таблицу данных, которую можно программно анализировать. В вызове сводки также можно изменить 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() для визуального сравнения
autoplot(mb) использует ggplot2, чтобы построить скрипичный или коробчатый график распределений времени выполнения для разных выражений. Так легко увидеть не только различия медиан, но и разброс, а также перекрытие результатов альтернативных вариантов.
# 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Сравнение цикла, vapply и sapply
Классический пример для сравнения: поэлементное применение функции с помощью цикла for, sapply() или vapply(). vapply() быстрее sapply(), потому что заранее выделяет память под вектор результата. Оба варианта медленнее полностью векторизованного кода.
# 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)Сначала проверьте корректность
Перед измерением производительности убедитесь, что все выражения возвращают одинаковые результаты. Быстрая, но некорректная реализация бесполезна. Для сравнения результатов используйте identical() или 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
')Измерение с аргументом setup
Используйте аргумент setup, чтобы выполнить код один раз перед измеряемыми выражениями. Это позволяет не включать время создания данных в измерение, если создание данных не является предметом сравнения.
# 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Представление результатов измерений в анализе
При публикации результатов измерений всегда указывайте:
- версию R и платформу
- версии пакетов
- использованное значение
times - размер набора данных, на котором проводилось измерение
Время выполнения нельзя напрямую переносить с одной машины на другую — при сравнении реализаций сообщайте относительные соотношения, а не абсолютные значения.
cat('R version :', R.version$version.string, '
')
cat('Platform :', R.version$platform, '
')
cat('Logical cores:', parallel::detectCores(), '
')Быстрая проверка: показатель microbenchmark
Какая сводная статистика из вывода microbenchmark наиболее надёжна при сравнении двух реализаций?
Повторение: microbenchmark
microbenchmark — стандартный инструмент для строгого измерения производительности небольших фрагментов кода в R:
- Передавайте именованные выражения и задавайте
times, чтобы управлять числом повторений - Используйте
unit = 'us'или'ms'для удобного чтения результатов - Сравнивайте медианы — они устойчивы к выбросам, вызванным сборкой мусора
- Используйте
autoplot()для визуализации распределений времени выполнения - Перед измерением проверяйте корректность с помощью
all.equal()
Часто задаваемые вопросы
Урок «Бенчмаркинг с помощью microbenchmark» бесплатный?
Да — полный текст урока «Бенчмаркинг с помощью microbenchmark» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс R Academy, подпишись на CoddyKit PRO. Курс R Academy содержит 4 уроков всего.
Чему я научусь в уроке «Бенчмаркинг с помощью microbenchmark»?
Статистически сравнивайте несколько реализаций с помощью microbenchmark() Ты практикуешь R Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать R Academy?
Предыдущий опыт не требуется. R Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 4 из 4.
Сколько времени занимает урок «Бенчмаркинг с помощью microbenchmark»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке R Academy?
Да. Каждый урок R Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- system.time() и proc.time()
- Профилирование кода с помощью Rprof и profvis
- Векторизация для ускорения
- Бенчмаркинг с помощью microbenchmark