Что-то не так с моей функцией-оберткой system.time? - PullRequest
4 голосов
/ 28 февраля 2011

РЕДАКТИРОВАТЬ: Обновлено благодаря прекрасному ответу @ daroczig ниже.Тем не менее, тест 2 по-прежнему кажется, что он длится дольше, чем тест 1, и это то, что мне интересно.

ОБНОВЛЕНИЕ: При втором чтении ответ @ daroczig объясняет мою путаницупроблема была в том, что я неправильно продумал строку кода system.time (expr).

Я хотел сделать версию функции system.time, которая была бы более информативной дляЯ с точки зрения понимания колебаний времени между циклами:

system.time.summary <- function(N, expr) {
  t.mat <- replicate(N, system.time(expr))
  as.data.frame(apply(t.mat[1:3,], 1, summary))
}

Однако проблема в том, что в автономном коде ниже, test.2 чувствует , как будто это занимает больше временисделать, чем test.1 (и я проверил их несколько раз для проверки), даже несмотря на то, что код практически одинаков (test.1 использует функцию-обертку, тогда как test.2 - это просто необработанный код)

# set up number of runs
N <- 100

# test 1
system.time.summary(N, (1:1e8)^2 + 1)

        user.self sys.self elapsed
Min.        0.000    0.000   0.000
1st Qu.     0.000    0.000   0.000
Median      0.000    0.000   0.000
Mean        0.058    0.031   0.089
3rd Qu.     0.000    0.000   0.000
Max.        0.580    0.310   0.890

# test 2
t.mat = replicate(N, system.time((1:1e8)^2 + 1))
as.data.frame(apply(t.mat[1:3,], 1, summary))

        user.self sys.self elapsed
Min.        0.630    0.120   0.860
1st Qu.     0.665    0.170   0.880
Median      0.695    0.195   0.880
Mean        0.692    0.196   0.882
3rd Qu.     0.715    0.225   0.890
Max.        0.760    0.260   0.900

Надеюсь, я объяснил, что все в порядке!Может быть, сейчас утро понедельника, но меня это смущает ...

Моя система:

# Windows Server 2008 R2
> sessionInfo()
R version 2.12.0 (2010-10-15)
Platform: x86_64-pc-mingw32/x64 (64-bit)

Ответы [ 2 ]

7 голосов
/ 28 февраля 2011

Вы запускаете system.time(system.time()) в первом тесте, а также имеете system.time(1:1e8)^2 + 1) в качестве выражения в функции, что не очень хорошая идея, см .:

> expr <- system.time((1:1e8)^2 + 1)
> system.time(expr)
   user  system elapsed 
      0       0       0 

Но в любом случае: используйте для этих целей пакет microbenmark от CRAN, вы не пожалеете. Настройте свои различные функции, и вы можете легко развернуть свои моделирования с 100, 1000 или любых прогонов. Вы можете получить аккуратную сводку и блокпосты в конце бенчмаркинга.

Например:

> test1 <- function() (1:1e8)^2 + 1
> (results <- microbenchmark(test1(), times=10))
Unit: nanoeconds
               min         lq     median         uq        max
test1() 3565386356 3703142531 3856450582 3931033077 3986309085
> boxplot(results)

enter image description here

2 голосов
/ 28 февраля 2011

Как сказал Дароциг, у вас есть дополнительное системное время. Но есть кое-что еще:

Если вы добавите browser() в свою функцию, вы увидите, что произойдет. Фактически, выражение, которое вы делаете, оценивается только один раз и затем сохраняется в памяти. Вот как R оптимизирует внутренне. Так что если вы делаете:

system.time.summary(N,(1:1e8)^2 +1)

t.mat внутренне:

           [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
user.self  0.61    0    0    0    0    0    0    0    0     0
sys.self   0.36    0    0    0    0    0    0    0    0     0
elapsed    0.97    0    0    0    0    0    0    0    0     0
user.child   NA   NA   NA   NA   NA   NA   NA   NA   NA    NA
sys.child    NA   NA   NA   NA   NA   NA   NA   NA   NA    NA

и expr:

Browse[2]> str(expr)
 num [1:100000000] 2 5 10 17 26 37 50 65 82 101 ...

Это немного сложно изменить, поскольку R будет оценивать любое статическое выражение только один раз, а затем извлекать результат еще 99 раз из памяти. Если вы хотите, чтобы этого не происходило, вы должны явно передать выражение и добавить функцию eval(). :

system.time.summary <- function(N, expr) {
  t.mat <- replicate(N, system.time(eval(expr)))
  as.data.frame(apply(t.mat[1:3,], 1, summary))
}

system.time.summary(N, expression((1:1e8)^2 + 1))

Теперь expr вычисляется каждый раз и остается выражением в функции:

Browse[2]> expr
expression((1:1e+08)^2 + 1)

Это дает вам правильное время.

        user.self sys.self elapsed
Min.       0.6400   0.2000   0.970
1st Qu.    0.6850   0.2375   0.980
Median     0.7150   0.2700   0.985
Mean       0.7130   0.2700   0.985
3rd Qu.    0.7425   0.2975   0.990
Max.       0.7800   0.3500   1.000
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...