R Language
Профилирование кода
Поиск…
Системное время
Системное время дает вам процессорное время, необходимое для выполнения выражения R, например:
system.time(print("hello world"))
# [1] "hello world"
# user system elapsed
# 0 0 0
Вы можете добавлять большие фрагменты кода с помощью брекетов:
system.time({
library(numbers)
Primes(1,10^5)
})
Или используйте его для тестирования функций:
fibb <- function (n) {
if (n < 3) {
return(c(0,1)[n])
} else {
return(fibb(n - 2) + fibb(n -1))
}
}
system.time(fibb(30))
proc.time ()
В своем простейшем случае proc.time()
дает общее время процессора в секундах для текущего процесса. Выполнение этого в консоли дает следующий тип вывода:
proc.time()
# user system elapsed
# 284.507 120.397 515029.305
Это особенно полезно для сопоставления определенных строк кода. Например:
t1 <- proc.time()
fibb <- function (n) {
if (n < 3) {
return(c(0,1)[n])
} else {
return(fibb(n - 2) + fibb(n -1))
}
}
print("Time one")
print(proc.time() - t1)
t2 <- proc.time()
fibb(30)
print("Time two")
print(proc.time() - t2)
Это дает следующий результат:
source('~/.active-rstudio-document')
# [1] "Time one"
# user system elapsed
# 0 0 0
# [1] "Time two"
# user system elapsed
# 1.534 0.012 1.572
system.time()
является оболочкой для proc.time()
которая возвращает прошедшее время для конкретной команды / выражения.
print(t1 <- system.time(replicate(1000,12^2)))
## user system elapsed
## 0.000 0.000 0.002
Обратите внимание, что возвращаемый объект класса proc.time
немного сложнее, чем кажется на поверхности:
str(t1)
## Class 'proc_time' Named num [1:5] 0 0 0.002 0 0
## ..- attr(*, "names")= chr [1:5] "user.self" "sys.self" "elapsed" "user.child" ...
Профилирование линии
Один пакет для профилирования линии - это lineprof, который написан и поддерживается Хэдли Викхэмом. Вот auto.arima
демонстрация того, как она работает с auto.arima
в пакете прогноза:
library(lineprof)
library(forecast)
l <- lineprof(auto.arima(AirPassengers))
shine(l)
Это обеспечит вам блестящее приложение, которое позволит вам глубже углубиться в каждый вызов функции. Это позволяет вам легко видеть, что заставляет ваш R-код замедляться. Скриншот блестящего приложения ниже:
Microbenchmark
Microbenchmark полезен для оценки времени, требуемого для других быстрых процедур. Например, рассмотрите оценку времени, затраченного на печать мира привет.
system.time(print("hello world"))
# [1] "hello world"
# user system elapsed
# 0 0 0
Это связано с тем, что system.time
по существу является оберточной функцией proc.time
, которая измеряется в секундах. Поскольку печать «hello world» занимает менее секунды, кажется, что занятое время меньше секунды, однако это неверно. Чтобы увидеть это, мы можем использовать микрообъект пакета:
library(microbenchmark)
microbenchmark(print("hello world"))
# Unit: microseconds
# expr min lq mean median uq max neval
# print("hello world") 26.336 29.984 44.11637 44.6835 45.415 158.824 100
Здесь мы видим, что после запуска print("hello world")
100 раз, среднее время было на самом деле 44 микросекунды. (Обратите внимание, что запуск этого кода будет печатать «hello world» 100 раз на консоль.)
Мы можем сравнить это с эквивалентной процедурой, cat("hello world\n")
, чтобы убедиться, что она быстрее, чем print("hello world")
:
microbenchmark(cat("hello world\n"))
# Unit: microseconds
# expr min lq mean median uq max neval
# cat("hello world\\n") 14.093 17.6975 23.73829 19.319 20.996 119.382 100
В этом случае cat()
почти в два раза быстрее, чем print()
.
В качестве альтернативы можно сравнить две процедуры в рамках одного и того же вызова microbenchmark
:
microbenchmark(print("hello world"), cat("hello world\n"))
# Unit: microseconds
# expr min lq mean median uq max neval
# print("hello world") 29.122 31.654 39.64255 34.5275 38.852 192.779 100
# cat("hello world\\n") 9.381 12.356 13.83820 12.9930 13.715 52.564 100
Бенчмаркинг с использованием microbenchmark
Вы можете использовать пакет microbenchmark
для проведения «точного времени оценки выражения» в миллисекундах.
В этом примере мы сравниваем скорости шести эквивалентных данных. data.table
выражения для обновления элементов в группе на основе определенного условия.
Более конкретно:
data.table
с тремя столбцами:id
,time
иstatus
. Для каждого идентификатора я хочу найти запись с максимальным временем - тогда, если для этой записи, если состояние истинно, я хочу установить значение false, если время составляет> 7
library(microbenchmark)
library(data.table)
set.seed(20160723)
dt <- data.table(id = c(rep(seq(1:10000), each = 10)),
time = c(rep(seq(1:10000), 10)),
status = c(sample(c(TRUE, FALSE), 10000*10, replace = TRUE)))
setkey(dt, id, time) ## create copies of the data so the 'updates-by-reference' don't affect other expressions
dt1 <- copy(dt)
dt2 <- copy(dt)
dt3 <- copy(dt)
dt4 <- copy(dt)
dt5 <- copy(dt)
dt6 <- copy(dt)
microbenchmark(
expression_1 = {
dt1[ dt1[order(time), .I[.N], by = id]$V1, status := status * time < 7 ]
},
expression_2 = {
dt2[,status := c(.SD[-.N, status], .SD[.N, status * time > 7]), by = id]
},
expression_3 = {
dt3[dt3[,.N, by = id][,cumsum(N)], status := status * time > 7]
},
expression_4 = {
y <- dt4[,.SD[.N],by=id]
dt4[y, status := status & time > 7]
},
expression_5 = {
y <- dt5[, .SD[.N, .(time, status)], by = id][time > 7 & status]
dt5[y, status := FALSE]
},
expression_6 = {
dt6[ dt6[, .I == .I[which.max(time)], by = id]$V1 & time > 7, status := FALSE]
},
times = 10L ## specify the number of times each expression is evaluated
)
# Unit: milliseconds
# expr min lq mean median uq max neval
# expression_1 11.646149 13.201670 16.808399 15.643384 18.78640 26.321346 10
# expression_2 8051.898126 8777.016935 9238.323459 8979.553856 9281.93377 12610.869058 10
# expression_3 3.208773 3.385841 4.207903 4.089515 4.70146 5.654702 10
# expression_4 15.758441 16.247833 20.677038 19.028982 21.04170 36.373153 10
# expression_5 7552.970295 8051.080753 8702.064620 8861.608629 9308.62842 9722.234921 10
# expression_6 18.403105 18.812785 22.427984 21.966764 24.66930 28.607064 10
Результат показывает, что в этом тесте expression_3
является самым быстрым.
Рекомендации
data.table - Добавление и изменение столбцов
data.table - специальные символы группировки в data.table