У меня много строк, и в каждой строке я вычисляю uniroot нелинейной функции. У меня есть четырехъядерный компьютер с Ubuntu, который уже два дня не останавливает мой код. Не удивительно, я ищу способы ускорить процесс; -)
После некоторых исследований я заметил, что в настоящее время используется только одно ядро, и нужно делать распараллеливание. Углубившись вглубь, я пришел к выводу (может быть, неправильно?), Что пакет foreach
на самом деле не предназначен для моей проблемы, поскольку создается слишком много служебной информации (см., Например, SO ). Хорошая альтернатива, похоже, multicore
для машин Unix. В частности, функция pvec
представляется наиболее эффективной после того, как я проверил страницу справки.
Однако, если я правильно понимаю, эта функция принимает только один вектор и разбивает его соответственно. Мне нужна функция, которая может быть парализована, но принимает несколько векторов (или вместо data.frame
), как и функция mapply
. Есть что-нибудь, что я пропустил?
Вот небольшой пример того, что я хочу сделать: (Обратите внимание, что я привожу здесь пример plyr
, потому что он может быть альтернативой базовой функции mapply
и у него есть опция распараллеливания. медленнее в моей реализации и внутренне, он вызывает foreach
для распараллеливания, поэтому я думаю, что это не поможет. Это правильно?)
library(plyr)
library(foreach)
n <- 10000
df <- data.frame(P = rnorm(n, mean=100, sd=10),
B0 = rnorm(n, mean=40, sd=5),
CF1 = rnorm(n, mean=30, sd=10),
CF2 = rnorm(n, mean=30, sd=5),
CF3 = rnorm(n, mean=90, sd=8))
get_uniroot <- function(P, B0, CF1, CF2, CF3) {
uniroot(function(x) {-P + B0 + CF1/x + CF2/x^2 + CF3/x^3},
lower = 1,
upper = 10,
tol = 0.00001)$root
}
system.time(x1 <- mapply(get_uniroot, df$P, df$B0, df$CF1, df$CF2, df$CF3))
#user system elapsed
#0.91 0.00 0.90
system.time(x2 <- mdply(df, get_uniroot))
#user system elapsed
#5.85 0.00 5.85
system.time(x3 <- foreach(P=df$P, B0=df$B0, CF1=df$CF1, CF2=df$CF2, CF3=df$CF3, .combine = "c") %do% {
get_uniroot(P, B0, CF1, CF2, CF3)})
#user system elapsed
# 10.30 0.00 10.36
all.equal(x1, x2$V1) #TRUE
all.equal(x1, x3) #TRUE
Кроме того, я попытался реализовать функцию Райана Томпсона chunkapply по ссылке SO выше (избавился только от части doMC
, потому что я не смог ее установить. Однако его пример работает, даже после настройки его функции.),
но не заставил его работать. Однако, поскольку он использует foreach
, я подумал, что применимы те же самые аргументы, что и выше, поэтому я не слишком долго пробовал.
#chunkapply(get_uniroot, list(P=df$P, B0=df$B0, CF1=df$CF1, CF2=df$CF2, CF3=df$CF3))
#Error in { : task 1 failed - "invalid function value in 'zeroin'"
PS: я знаю, что я мог бы просто увеличить tol
, чтобы уменьшить количество шагов, необходимых для поиска uniroot. Однако я уже установил tol
как можно большим.