Как запустить функцию x раз в разных кластерах в r?

#r #parallel-processing

#r #параллельная обработка

Вопрос:

У меня есть эта команда: replicate(10^4, binom_ttest(100, 0.5)) %>% {sum(.<0.05)}/20000

binom_ttest это созданная мной функция, которая возвращает 2x p.value 1 для теста binom и 1 для t-теста

Поскольку это очень длинный расчет, я хотел спросить, как я могу распределить его на 2 кластера? Я знаю, что есть возможность, parLapply но это не работает: parLapply(makeCluster(2), 1:10000, binom_ttest(100, 0.5))

Комментарии:

1. Какое сообщение об ошибке? Вы clusterExport выполнили свою функцию?

2. @AndreWildberg Да, я это сделал. Error in checkForRemoteErrors(val) : 2 nodes produced errors; first error: 'base::quote(c(0.0118179321289063, 0.00403591538162696))' is not function, sign oder symbol не уверен, что я перевел это на 100 процентов правильно, мой R не английский

3. Я не понимаю, как вы выполняете биномиальный тест (двоичная переменная) и t-тест (непрерывная переменная). Можете ли вы лучше объяснить свою функцию?

4. @RuiBarradas это функция: function(n, p) { x <- sample(0:1, n, replace = TRUE, prob = c(1-p, p)) xsum <- sum(x==1) p_binom <- binom.test(xsum, n, 0.5)[["p.value"]] p_ttest <- t.test(x, mu=0.5)[["p.value"]] c(p_binom, p_ttest) }

Ответ №1:

Пакет future.apply предоставляет future_replicate() , который является параллельной реализацией replicate() ;

 library(future.apply)
plan(multisession, workers = 2)

y <- future_replicate(10^4, binom_ttest(100, 0.5))
 

Это гарантирует, что используется правильная параллельная генерация случайных чисел (RNG), Что очень важно при выполнении тестов перестановки, начальной загрузки и т. Д.

Комментарии:

1. Это отличный пакет, спасибо за понимание, работает отлично

Ответ №2:

Вот способ.
Вы забыли экспортировать функцию рабочим, и для того, чтобы сделать код воспроизводимым, лучше установить псевдо-RNG.

 library(parallel)

binom_ttest <- function(n, p) {   
  x <- sample(0:1, n, replace = TRUE, prob = c(1-p, p))   
  xsum <- sum(x==1)    
  p_binom <- binom.test(xsum, n, 0.5)[["p.value"]]   
  p_ttest <- t.test(x, mu=0.5)[["p.value"]]   
  c(p_binom, p_ttest) 
}

cl <- makeCluster(2)
clusterExport(cl, "binom_ttest")
clusterSetRNGStream(cl = cl, 2021)
res <- parSapply(cl, 1:10000, FUN = function(i) binom_ttest(100, 0.5))
stopCluster(cl)

rowMeans(res < 0.05)
#[1] 0.0347 0.0571
 

Комментарии:

1. К вашему сведению, вам нужно использовать parallel::clusterSetRNGStream() , чтобы настроить параллельный RNG на параллельных рабочих.

2. @HenrikB Вы, конечно, правы, спасибо. Исправлено сейчас.

Ответ №3:

Вот пример тестового запуска parallel . Я бы рекомендовал попробовать пробный запуск с простой функцией, а затем расширить ее до вашего более сложного примера.

В качестве дополнительного примечания, каждый используемый вами набор данных должен быть доступен для всех кластеров и, следовательно, должен быть экспортирован, как simpl() в примере ниже.

 library(parallel)

cl <- makeCluster(getOption("cl.cores", 2))

cl
# socket cluster with 2 nodes on host ‘localhost’

simpl <- function(x)diag(x)

clusterExport(cl, varlist=("simpl"))

parLapply( cl, 1:5, function(x) simpl(x) )
#[[1]]
#     [,1]
#[1,]    1
#
#[[2]]
#     [,1] [,2]
#[1,]    1    0
#[2,]    0    1
#
#... etc
#
#[[5]]
#     [,1] [,2] [,3] [,4] [,5]
#[1,]    1    0    0    0    0
#[2,]    0    1    0    0    0
#[3,]    0    0    1    0    0
#[4,]    0    0    0    1    0
#[5,]    0    0    0    0    1

stopCluster(cl)
 

Комментарии:

1. ПРЕДУПРЕЖДЕНИЕ: всякий раз, когда задействованы случайные числа, вы должны убедиться, что используете параллельный RNG, чтобы получить статистические достоверные результаты. Смотрите ?parallel::clusterSetRNGStream , как это сделать.

2. @HenrikB Спасибо, это важное замечание. Я лучше включу более простой пример…