Использование нескольких ядер для параллельной выборки из латинского гиперкуба

Я собираюсь извлечь репрезентативные выборки из совокупностей (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!

Другие вопросы по тегам