Вычисление среднего значения в цикле снижает производительность - PullRequest
0 голосов
/ 21 февраля 2019

Рассмотрим первый пример: он вычисляет среднее значение в цикле.

st <- Sys.time() #Starting Time 
set.seed(123456789)
vara <- c()
sda <- c()
mvara <- c() #store mean
msda <- c() #store mean of standard deviation

K <- 100000

for(i in 1:K) {
  a <- rnorm(30)
  vara[i] <- var(a)
  sda[i] <- sd(a)
  mvara[i] <- mean(mvara)
  msda[i] <- mean(msda)
}

et <- Sys.time()

et-st  #time taken by code (approx more than one minute)

Рассмотрим тот же код, за исключением того, что то же среднее значение вычисляется вне цикла.

st <- Sys.time() #Starting Time 
set.seed(123456789)
vara <- c()
sda <- c()

K <- 100000

for(i in 1:K) {
  a <- rnorm(30)
  vara[i] <- var(a)
  sda[i] <- sd(a)
}

mvara <- cumsum(vara)/ (1:K)
msd <- cumsum(sda)/ (1:K)
et <- Sys.time()  #less than 5 seconds

Я просто хотел знать, почему так много различий в производительности обоих кодов?Где следует соблюдать осторожность при использовании петли?

1 Ответ

0 голосов
/ 21 февраля 2019

R быстрее, когда вы используете его внутренний оптимизированный код для выполнения циклов.Мое понимание причин этого плохое (в ветке комментария выше есть объяснения от более знающих людей), но я считаю, что некоторые из них связаны с предварительным распределением памяти, а некоторые - с тем, как она превращает проблему в болееэффективные куски.

Ваш код "вне цикла" можно было бы сделать еще примерно в 20 раз быстрее (в моей системе он пошел с 7,17 до 0,43 с), сначала создав все ваши случайные числа, а затем решив всю таблицусразу, вместо того, чтобы переключаться между этими двумя задачами в цикле.И это использует dplyr;Я предполагаю, что решение data.table может быть еще в 5-10 раз быстрее, особенно с учетом большого количества групп.

library(dplyr)
set.seed(123456789)
K <- 100000
n <- 30
a_df <- data.frame(trial = rep(1:K, each = 30),
                   val   = rnorm(K*n))

results <- a_df %>%
  group_by(trial) %>%
  summarize(vara = var(val),
            sda  = sd(val)) %>%
  mutate(mvara = cumsum(vara) / trial,
         msd   = cumsum(sda)  / trial)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...