Почему сценарии, распараллеленные с помощью mclapply
, печатаются в кластере, а не в RStudio? Просто из любопытства спрашиваю.
mclapply(1:10, function(x) {
print("Hello!")
return(TRUE)
}, mc.cores = 2)
# Hello prints in slurm but not RStudio
Почему сценарии, распараллеленные с помощью mclapply
, печатаются в кластере, а не в RStudio? Просто из любопытства спрашиваю.
mclapply(1:10, function(x) {
print("Hello!")
return(TRUE)
}, mc.cores = 2)
# Hello prints in slurm but not RStudio
Ни одна из функций в «параллельном» пакете не гарантирует правильного отображения вывода, отправленного на стандартный вывод (stdout) или стандартную ошибку (stderr) на рабочих процессах. Это верно для всех типов подходов к распараллеливанию, например. разветвленная обработка (mclapply()
) или кластеры PSOCK (parLapply()
). Причина этого в том, что он никогда не был предназначен для последовательной передачи вывода.
Хороший тест — посмотреть, сможете ли вы захватить вывод через capture.output()
. Например, я получаю:
bfr <- utils::capture.output({
y <- lapply(1:3, FUN = print)
})
print(bfr)
## [1] "[1] 1" "[1] 2" "[1] 3"
как и ожидалось, но когда я пытаюсь:
bfr <- utils::capture.output({
y <- parallel::mclapply(1:3, FUN = print)
})
print(bfr)
## character(0)
вывод не захвачен. Интересно, что если я вызову его без захвата вывода в R 4.0.1 в Linux в терминале, я получу:
y <- parallel::mclapply(1:3, FUN = print)
[1] 1
[1] 3
[1] 2
Интересно, а?
Еще одно предложение, которое вы можете получить при использовании локальных кластеров PSOCK, — установить аргумент outfile = ""
при создании кластера. Действительно, когда вы попробуете это в Linux в терминале, это определенно сработает:
cl <- parallel::makeCluster(2L, outfile = "")
## starting worker pid=25259 on localhost:11167 at 17:50:03.974
## starting worker pid=25258 on localhost:11167 at 17:50:03.974
y <- parallel::parLapply(cl, 1:3, fun = print)
## [1] 1
## [1] 2
## [1] 3
Но и это дает ложные надежды. Оказывается, результат, который вы видите, появляется только потому, что его отображает терминал. Это может работать или не работать в консоли RStudio. Вы можете увидеть различное поведение в Linux, macOS и MS Windows. Наиболее важной частью понимания является то, что ваш сеанс R не вообще не видит этот вывод. Если мы попытаемся захватить его, мы получим:
bfr <- utils::capture.output({
y <- parallel::parLapply(cl, 1:3, fun = print)
})
## [1] 1
## [1] 2
## [1] 3
print(bfr)
## character(0)
Интересно, а? Но на самом деле это не удивительно, если вы понимаете внутренние детали «параллельного» пакета.
(Отказ от ответственности: я автор) Единственная известная мне параллельная структура, которая правильно передает стандартный вывод (например, cat()
, print()
,...) и условия сообщения (например, message()
) в основной сеанс R, - это будущее. Подробности можно прочитать в его 'Text и виньетка вывода сообщений, но вот пример, показывающий, что это работает:
future::plan("multicore", workers = 2) ## forked processing
bfr <- utils::capture.output({
y <- future.apply::future_lapply(1:3, FUN = print)
})
print(bfr)
[1] "[1] 1" "[1] 2" "[1] 3"
Он работает одинаково независимо от базовой структуры параллелизма, например. с местными работниками PSOCK:
future::plan("multisession", workers = 2) ## PSOCK cluster
bfr <- utils::capture.output({
y <- future.apply::future_lapply(1:3, FUN = print)
})
print(bfr)
[1] "[1] 1" "[1] 2" "[1] 3"
Это работает одинаково во всех операционных системах и средах, в которых вы запускаете R, включая консоль RStudio. Он также ведет себя одинаково независимо от того, какую будущую структуру уменьшения карты вы используете, например. (здесь) future.apply, furrr и foreach с doFuture.
future
, но похоже, что он может быть полезен в проектах, где я хочу отслеживать прогресс.
- person Daniel Freeman; 11.06.2020
system
. При последовательном запуске он отображает стандартный вывод исполняемого файла, но для некоторых интерфейсов, таких как Rstudio и графический интерфейс R, он не печатается для параллельных заданий. Я пробовал ваши будущие пакеты, но он делает то же самое, без вывода. Есть ли способ получить это последовательно из параллельного вызова system
?
- person Cole Monnahan; 27.01.2021
system()
вывод на стандартный вывод (stdout) и стандартную ошибку (stderr), зависит от среды, в которой вы запускаете R. Она сильно различается, и ее трудно предсказать. .
- person HenrikB; 27.01.2021
system2()
позволяет вам захватывать stdout и stderr как строки символов в R, которые вы затем можете вывести, когда все будет сделано. В дополнение к этому, вы также можете заглянуть в пакет callr.
- person HenrikB; 27.01.2021
test.fn <- function(i) {Sys.sleep(.5); system('where Rterm')}
. При последовательном запуске он всегда выводит на консоль. Параллельно он печатает только при использовании Rterm, а не Rgui или RStudio. Я также пробовал callr, и он не работает. Вся идея состоит в том, чтобы показать прогресс, выведенный этой конкретной программой, поэтому сохранение его до конца не очень помогает. Это может быть безнадежно, но я подумал, что проверю. Спасибо!
- person Cole Monnahan; 27.01.2021
parallel::mclapply()
в качестве ответа ниже). - person HenrikB   schedule 11.06.2020