Изменения

Перейти к: навигация, поиск

R:Измерение времени выполнения выражений

12 байтов убрано, 14:24, 19 февраля 2014
м
Нет описания правки
Для примера возьмём несколько способов расчёта среднего арифметического для сгенерированного массива данных.
{{r-code|code=<nowiki>> x <- replicate(10, rnorm(10^6L))
</nowiki>
}}
Использованные нами способы - функции векторизованных вычислений (<code>apply()</code>, <code>vapply()</code>), стандартный цикл и специальная функция вычисления средних по столбцам <code>ColMeans()</code>. Представим эти способы в виде самостоятельных функций для удобства их вызова при работе с <code>benchmark()</code>:
{{r-code|code=<nowiki>colMeansApply <- function(x) {
apply(x, 2, mean)
}
Убедимся, что функции возвращают одинаковый результат. Сделать это можно с помощью функций <code>identical()</code> или <code>all.equal()</code>:
{{r-code|code=<nowiki>> identical(colMeansApply(x), colMeansVapply(x), colMeansLoop(x), colMeansLoopVec(x), colMeans(x))
[1] TRUE
</nowiki>
Теперь, подключив пакет rbenchmark, мы можем сравнить время работы каждого из выбранных нами способов вычисления средних по столбцам:
{{r-code|code=<nowiki>> library(rbenchmark)
> benchmark(colMeansApply(x), colMeansVapply(x), colMeansLoop(x),
+ colMeansLoopVec(x), colMeans(x), replications = 100)
Для более удобного просмотра можно отфильтровать вывод функции <code>benchmark()</code> с помощью аргумента <code>columns</code>. Также может быть полезен аргумент <code>order</code>, позволяющий отсортировать вывод по любому из столбцов. Для примера зададим набор показателей, которые мы хотим включить в таблицу (в данном случае это «test», «replications», «elapsed», «relative»), и отсортируем выдачу по столбцу «elapsed» по возрастанию значений:
{{r-code|code=<nowiki>> benchmark(colMeansApply(x), colMeansVapply(x), colMeansLoop(x), colMeansLoopVec(x), colMeans(x),
+ replications = 100, order = "relative",
+ columns = c("test", "replications", "elapsed", "relative"))
Чтобы не указывать нужные столбцы каждый раз, когда используется функция <code>benchmark()</code>, можно закрепить заданный формат выдачи результатов (далее используется именно такой формат вывода, с сортировкой по столбцу «relative»). Для этого следует воспользоваться функцией <code>formals()</code>:
{{r-code|code=<nowiki>> formals(benchmark)$columns <- c("test", "replications", "elapsed", "relative")
> formals(benchmark)$order <- "relative"
</nowiki>
В таблице ниже представлено время выполнения пяти функций вычисления среднего значения из предыдущего примера, полученное с помощью функции <code>microbenchmark()</code>:
{{r-code|code=<nowiki>> res <- microbenchmark(colMeansApply(x), colMeansVapply(x), colMeansLoop(x),
+ colMeansLoopVec(x), colMeans(x), times = 100)
> print(res, unit = "ms", order = "median")
Вся полученная информация о попытках применения функций вычисления средних записана в отдельную переменную <code>res</code>. С помощью функции <code>str()</code> можно увидеть структуру переменной:
{{r-code|code=<nowiki>> str(res)
Classes ‘microbenchmark’ and 'data.frame': 500 obs. of 2 variables:
$ expr: Factor w/ 5 levels "colMeansApply(x)",..: 4 2 1 1 1 3 3 5 5 1 ...
Переменная <code>res</code>, как можно увидеть в выводе функции <code>str()</code>, представляет собой список (list) и включает в себя две переменные: <code>expr</code> (выражение) и <code>time</code> (время выполнения). На основе этой информации и рассчитываются описательные статистики, приведённые в примере применения функции <code>microbenchmark()</code>. Наличие исходных данных о каждой попытке позволяет самостоятельно выбирать, рассчитывать и сравнивать предпочтитаемые показатели. Например, расчет медианного времени выполнения попытки и общего времени выполнения всех попыток для каждого выражения выглядит следующим образом:
{{r-code|code=<nowiki>> aggregate(time ~ expr, data = res, function(x) median(x) * 10^-6L)
expr time
1 colMeansApply(x) 132.24
Помимо настройки формата вывода, выбора показателей, наличие информации о времени выполнения выражения в каждой попытке позволяет визуализировать результаты оценки времени выполнения выражения. Например, с помощью функции <code>autoplot()</code> из пакета <code>ggplot2</code>, можно получить следующий график:
{{r-code|code=<nowiki>> library(ggplot2)
> autoplot(res)
</nowiki>
Ещё один довольно интересный способ графического представления результатов измерения скорости выполнения кода с помощью функции <code>qplot()</code> представлен ниже:
{{r-code|code=<nowiki>> qplot(y = time, data = res, colour = expr)
</nowiki>
}}
Так же можно, если возникнет необходимость, оценить статистическую значимость различий во времени выполнения выражений. Благодаря тому, что в переменной <code>res</code> хранятся данные о времени выполнения каждой попытки из заданного числа, становится возможным использование статистических критериев. Выбор критерия - на усмотрение аналитика, в примере ниже использовался параметрический критерий сравнения групп t-Стьюдента с поправкой уровня статистической значимости Холма для множественных сравнений:
{{r-code|code=<nowiki>> pairwise.t.test(res$time, res$expr)
Pairwise comparisons using t tests with pooled SD

Навигация