BenchmaRking

измерение времени исполнения

Антон Антонов
@tonytonov

"R is sooooo slow"

Интерпретатор

Парсер

Множественный look-up переменных

Вложенные окружения

(это клише)

may be

Следовательно

рано или поздно*

встанет вопрос производительности

*раньше, чем вы думаете

Что делать?

  1. Профилировать: искать bottleneck
  2. Оптимизировать
  3. Если всё ещё недостаточно быстро, GOTO 1

1. ∩ 2. 

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

\subset
\subset

microbenchmark

library(microbenchmark)

microbenchmark(..., list = NULL, 
               times = 100L, unit, check = NULL,
               control = list())

Больше ничего знать не нужно!

build <- function(n) {
  m <- matrix(0, n, n)
  for (i in 1:n)
    for (j in 1:n) 
      m[i, j] <- min(i + j - 1,
                     2*n - i - j + 1)
  m
}

build(5)
1 2 3 4 5
2 3 4 5 4
3 4 5 4 3
4 5 4 3 2
5 4 3 2 1
microbenchmark(build(100))
#Unit: milliseconds
#       expr      min       lq     mean   
# build(100) 20.25227 21.64457 22.61785 
#
# median       uq      max neval
# 22.04771 22.72247 54.94286   100

22 миллисекунды на матрицу 100x100

медленно

очень

library(Rcpp)
cppFunction("NumericMatrix build_cpp(const int n) {
               NumericMatrix x(n, n);  
               for (int i=0; i<n; i++) 
                 for (int j=0; j<n; j++) 
                   x(i, j) = std::min(i + j + 1, 
                                      2*n - i - j - 1);
               return x;
             }")

m <- microbenchmark(build(100), build_cpp(100))
summary(m)[, c("expr", "median")]

#            expr    median
#1     build(100) 21853.425
#2 build_cpp(100)    36.786

(плюс время компиляции)

build_outer <- function(n) {
  outer(1:n, 1:n, function(i, j)
          pmin(i + j - 1, 2*n - i - j + 1))
}

m <- microbenchmark(build(100), 
                    build_outer(100), 
                    build_cpp(100))
summary(m)[, c("expr", "median")]

#              expr    median
#1       build(100) 22304.613
#2 build_outer(100)   205.700
#3   build_cpp(100)    34.534

Низкоуровневые функции + векторизация

benchr

install.packages("benchr")
library(benchr)
m2 <- benchmark(build(100), 
                build_outer(100), 
                build_cpp(100))
summary(m2)[, c("expr", "median", "relative")]

#Time units : microseconds 
#             expr  median relative
#       build(100) 21800.0   788.00
# build_outer(100)   194.0     7.01
#   build_cpp(100)    27.6     1.00

benchr

Это microbenchmark плюс:

  1. более точный таймер
  2. больше кастомизации
  3. ... и плюшки
plot(m2)
boxplot(m2, violin = TRUE)

Ссылки

Спасибо!

BenchmaRking

By Antonov Anton

BenchmaRking

The talk I gave at ITGM #9, St. Petersburg IT Global Meetup (03.12.2016).

  • 497