我正在尝试使用 doParallel 后端在并行 foreach 循环中使用标准 R Shiny 进度条。但是,这会导致以下错误消息:
Warning: Error in {: task 1 failed - "'session' is not a ShinySession object."
代码(最小工作示例)
library(shiny)
library(doParallel)
ui <- fluidPage(
actionButton(inputId = "go", label = "Launch calculation")
)
server <- function(input, output, session) {
workers=makeCluster(2)
registerDoParallel(workers)
observeEvent(input$go, {
Runs=c(1:4)
Test_out=foreach(i=Runs, .combine=cbind, .inorder=TRUE, .packages=c("shiny"),.export=c("session")) %dopar% {
pbShiny = shiny::Progress$new()
pbShiny <- Progress$new(session,min = 0, max = 10)
on.exit(pbShiny$close())
test_vec=rep(0,100)
for(i in 1:10){
test_vec=test_vec+rnorm(100)
pbShiny$set(message="Simulating",detail=paste(i),
value=i)
Sys.sleep(0.2)
}
}
})
}
shinyApp(ui = ui, server = server)
如果我顺序运行 foreach 循环(使用 registerDoSEQ()),代码就会运行。 有谁知道如何解决这个问题吗?
<小时/>总体目标
- 使用 doParallel 在并行 foreach 循环中向用户显示进度 后端 Shiny
- 用户应了解 worker 的数量和 每个 worker 的进度和/或总体进度
以下链接下有类似的问题,但由于未提供工作示例而未得到解决:
最佳答案
doParallel 包是并行包的扩展,如此处的文档所示。
https://cran.r-project.org/web/packages/doParallel/doParallel.pdf
阅读并行包的文档,我们发现它实现了 3 种不同的方法来实现并行性。请记住,R 是一种单线程语言。
- 一个新的 R session ,其中父进程与工作进程或子进程进行通信。
- 通过 fork
- 使用操作系统级别的工具
您可以在此处找到此信息,
https://stat.ethz.ch/R-manual/R-devel/library/parallel/doc/parallel.pdf
这样做的结果是子进程在完成计算并返回值之前无法与父进程通信。据我所知,这是。
因此,无法在工作进程内勾选进度条。
完全披露,我没有使用过 doParallel 包,并且有关 Shiny 的文档是有限的。
<小时/>替代解决方案
有一个类似的包,但是有关于 Shiny 的大量文档。这些是 futures
和 promises
以及 ipc
包。 futures
和 promises
支持异步编程,而 ipc
支持进程间通信。为了给我们提供更多帮助,它还有一个 AsyncProgress()
函数。
这是一个我们同步勾选两个计数器的示例。
示例
library(shiny)
library(future)
library(promises)
library(ipc)
plan(multisession)
ui <- fluidPage(
actionButton(inputId = "go", label = "Launch calculation")
)
server <- function(input, output, session) {
observeEvent(input$go, {
progress = AsyncProgress$new(message="Complex analysis")
future({
for (i in 1:15) {
progress$inc(1/15)
Sys.sleep(0.5)
}
progress$close()
return(i)
})%...>%
cat(.,"\n")
Sys.sleep(1)
progress2 = AsyncProgress$new(message="Complex analysis")
future({
for (i in 1:5) {
progress2$inc(1/5)
Sys.sleep(0.5)
}
progress2$close()
return(i)
})%...>%
cat(.,"\n")
NULL
})
}
shinyApp(ui = ui, server = server)
您的代码已调整
这是您编写的代码,稍加修改即可分离出许多异步进程。任何工作都可以在工作线程中执行,例如您创建并添加 rnorm
的向量。 (此处未显示)
library(shiny)
library(future)
library(promises)
library(ipc)
plan(multisession)
ui <- fluidPage(
actionButton(inputId = "go", label = "Launch calculation")
)
server <- function(input, output, session) {
observeEvent(input$go, {
Runs=c(1:4) #define the number of runs
progress = list() #A list to maintain progress for each run
for(j in Runs){
progress[[j]] = AsyncProgress$new(message="Complex analysis")
future({
for (i in 1:10) {
progress[[j]]$inc(1/10)
Sys.sleep(0.2)
}
progress[[j]]$close()
return(i)
})%...>%
cat(.,'\n')
}
NULL
})
}
shinyApp(ui = ui, server = server)
上面的代码是在 ipc 文档中找到的代码的修改版本:
http://htmlpreview.github.io/?https://github.com/fellstat/ipc/blob/master/inst/doc/shinymp.html
其他资源:
关于r - 在并行 foreach 计算中使用标准 R Shiny 进度条,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54532486/