#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 Спасибо, это важное замечание. Я лучше включу более простой пример…