Ви вже отримали відповідь про те, як використовувати більше одного ядра, але справжня проблема полягає в тому, як ви написали свої петлі. Ніколи не розширюйте вектор / об'єкт результату при кожній ітерації циклу . Якщо ви це зробите, ви змусите R скопіювати вектор / об'єкт результату та продовжити його, який потребує часу. Натомість попередньо виділіть достатньо місця для зберігання, перш ніж запускати цикл і заповнювати його, продовжуючи. Ось приклад:
set.seed(1)
p1 <- matrix(rnorm(10000), ncol=100)
system.time({
p1max <- p1mean <- p1sum <- numeric(length = 100)
for(i in seq_along(p1max)){
p1max[i] <- max(p1[i,])
p1mean[i] <- mean(p1[i,])
p1sum[i ]<- sum(p1[i,])
}
})
user system elapsed
0.005 0.000 0.005
Або ви можете зробити це за допомогою apply()
:
system.time({
p1max2 <- apply(p1, 1, max)
p1mean2 <- apply(p1, 1, mean)
p1sum2 <- apply(p1, 1, sum)
})
user system elapsed
0.007 0.000 0.006
Але зауважте, що це не швидше, ніж робити цикл правильно, а іноді повільніше.
Однак завжди слідкуйте за векторизованим кодом. Ви можете робити суми рядків і засобів, використовуючи rowSums()
і rowMeans()
які швидше, ніж цикл або apply
версії:
system.time({
p1max3 <- apply(p1, 1, max)
p1mean3 <- rowMeans(p1)
p1sum3 <- rowSums(p1)
})
user system elapsed
0.001 0.000 0.002
Якби я був людиною, що закладав гроші, у мене був би гроші на третій підхід, який я згадую про побиття foreach()
чи інші багатоядерні варіанти в тесті на швидкість на вашій матриці, оскільки їм доведеться значно прискорити справи, щоб виправдати накладні витрати, зроблені під час налаштування окремі процеси, які обробляються різними ядрами процесора.
Оновлення: Після коментаря від @shabbychef чи швидше зробити суми одноразово і повторно використовувати під час обчислення середнього?
system.time({
p1max4 <- apply(p1, 1, max)
p1sum4 <- rowSums(p1)
p1mean4 <- p1sum4 / ncol(p1)
})
user system elapsed
0.002 0.000 0.002
Не в цьому тестовому запуску, але це далеко не вичерпно ...