Использование нескольких ядер для параллельной выборки из латинского гиперкуба
Я собираюсь извлечь репрезентативные выборки из совокупностей (a,b,c,d,... см. Ниже), используя пакет "clhs" из R. Процесс выборки занимает очень много времени на моем (многоядерном) компьютере, поэтому я бы нравится запускать процедуры выборки параллельно (используя несколько процессорных ядер одновременно).
Вот некоторые из моих (примерных) фреймов данных ("совокупностей"), из которых я хочу извлечь образцы:
a <- as.data.frame(replicate(1000, rnorm(20)))
b <- as.data.frame(replicate(1000, rnorm(20)))
c <- as.data.frame(replicate(1000, rnorm(20)))
d <- as.data.frame(replicate(1000, rnorm(20)))
Код clhs, который я хочу запустить:
clh_a <- clhs(x=a, size=round(nrow(a)/5), iter=2000, simple=F)) # 20% of all samples should be selected
clh_b <- clhs(x=b, size=round(nrow(b)/5), iter=2000, simple=F))
так далее...
Как запустить этот процесс выборки параллельно? Или есть другой способ сделать это эффективным способом?
Приложение (большое спасибо "zipfzapf"):
Я пытался использовать "parLapply" - к сожалению, в конце R выдает сообщение об ошибке "Ошибка длины (x):" x "отсутствует", чего я, честно говоря, не понимаю... Любые идеи?
Мой код:
library("snow")
a <- as.data.frame(replicate(1000, rnorm(20)))
b <- as.data.frame(replicate(1000, rnorm(20)))
c <- as.data.frame(replicate(1000, rnorm(20)))
d <- as.data.frame(replicate(1000, rnorm(20)))
abcd <- list(a, b, c, d)
cl <- makeCluster(4)
results <- parLapply(cl,
X = abcd,
FUN = function(i) {
clhs(x = i, size = round(nrow(i) / 5), iter = 2000, simple = FALSE)
},
)
3 ответа
Это работает для меня (обратите внимание, я изменил количество итераций, чтобы заставить вещи двигаться в разумном темпе).
library(snowfall)
sfInit(parallel = TRUE, cpus = 4, type = "SOCK")
sfLibrary(clhs)
x <- sfLapply(abcd, fun = function(x) {
clhs(x = x, size=round(nrow(x)/5), iter = 200, simple =FALSE)
})
Length Class Mode
[1,] 5 cLHS_result list
[2,] 5 cLHS_result list
[3,] 5 cLHS_result list
[4,] 5 cLHS_result list
Функция mclapply
из (встроенного) пакета parallel
это многоядерная версия lapply
:
library(parallel)
# population samples
abcd <- list(a, b, c, d)
# multi-core version of 'lapply(abcd, [....])'
results <- parallel::mclapply(
X = abcd,
FUN = function(elem) {
clhs(x = elem, size = round(nrow(elem) / 5), iter = 2000, simple = FALSE))
},
mc.preschedule = FALSE,
mc.cores = 4L
)
Это даст вам список, где каждый элемент содержит результат соответствующего clhs
вызов.
Обратите внимание, что аргументы mc.preschedule
а также mc.cores
являются необязательными. настройка mc.preschedule
в FALSE
это хорошая идея, если каждый вызов функции FUN
может занять некоторое время (как в вашем случае).
Решение с использованием "снега" - просто добавив "clusterEvalQ(cl, library(clhs))", добились цели:
a <- as.data.frame(replicate(1000, rnorm(20)))
b <- as.data.frame(replicate(1000, rnorm(20)))
c <- as.data.frame(replicate(1000, rnorm(20)))
d <- as.data.frame(replicate(1000, rnorm(20)))
abcd <- list(a, b, c, d)
library("snow")
cl <- makeCluster(4)
clusterEvalQ(cl, library(clhs))
results <- parLapply(cl, abcd, fun = function(elem) {
clhs(x = elem, size = round(nrow(elem) / 2), iter = 50)
})
stopCluster(cl)
Еще раз большое спасибо zipfzapf & Roman Luštrik!