为什么不在 RStudio 中打印并行作业?
Why don't parallel jobs print in RStudio?
为什么使用 mclapply
并行化的脚本在集群上打印而不是在 RStudio 中打印?只是出于好奇。
mclapply(1:10, function(x) {
print("Hello!")
return(TRUE)
}, mc.cores = 2)
# Hello prints in slurm but not RStudio
None 'parallel' 包中的函数保证正确显示发送到标准输出 (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)
没有捕获到输出。有趣的是,如果我调用它而不在终端的 Linux 上捕获 R 4.0.1 中的输出,我会得到:
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)
有趣吧?但如果你了解 'parallel' 包的内部细节,其实并不奇怪。
(免责声明:我是作者)据我所知,唯一可以正确中继标准输出(例如 cat()
、print()
、...)和消息条件(例如 message()
) 到主 R 会话的是 future framework. You can read about the details in its 'Text and Message Output' vignette 但这里有一个例子表明它有效:
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 控制台。无论您使用哪种未来的 map-reduce 框架,它的行为都是相同的,例如(此处)future.apply, furrr, and foreach with doFuture.
为什么使用 mclapply
并行化的脚本在集群上打印而不是在 RStudio 中打印?只是出于好奇。
mclapply(1:10, function(x) {
print("Hello!")
return(TRUE)
}, mc.cores = 2)
# Hello prints in slurm but not RStudio
None 'parallel' 包中的函数保证正确显示发送到标准输出 (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)
没有捕获到输出。有趣的是,如果我调用它而不在终端的 Linux 上捕获 R 4.0.1 中的输出,我会得到:
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)
有趣吧?但如果你了解 'parallel' 包的内部细节,其实并不奇怪。
(免责声明:我是作者)据我所知,唯一可以正确中继标准输出(例如 cat()
、print()
、...)和消息条件(例如 message()
) 到主 R 会话的是 future framework. You can read about the details in its 'Text and Message Output' vignette 但这里有一个例子表明它有效:
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 控制台。无论您使用哪种未来的 map-reduce 框架,它的行为都是相同的,例如(此处)future.apply, furrr, and foreach with doFuture.