我想在每个tclTaskSchedule
线程中执行doParallel
计时器(来自tcltk2
包)。但是,以下最小代码
library(doParallel)
n <- detectCores()
cl <- makeCluster(n, outfile="out.log")
registerDoParallel(cl)
testfn <- function() print(paste("hello from", i))
foreach(i=1:n, .packages = c("tcltk", "tcltk2"), .verbose = T) %dopar% {
tclTaskSchedule(1000, testfn(), id = paste0("task", i), redo = 10)
}
stopCluster(cl)
导致错误(在控制台中打印不,但在out.log
中)
Error in eval(expr, envir, enclos) : could not find function "testfn"
但是,从.verbose = T
参数中,我可以从控制台看到testfn
正在导出:
automatically exporting the following variables from the local environment:
testfn
确实,使用foreach
调用.export = "testfn"
会导致同样的错误。
那么出了什么问题?
(我为什么要这样做?最后,我希望以poll定期以固定的时间间隔异步,并且每个数据源都有自己的数据源特定的轮询间隔)
答案 0 :(得分:1)
我同意Roland的观点,问题在于tclTaskSchedule
评估其论点的方式。我的解决方案并不漂亮,但我通过使用testfn
导出clusterExport
并在foreach循环中将i
分配给worker的全局环境来实现它:
testfn <- function() print(paste("hello from", i))
clusterExport(cl, "testfn")
foreach(i=1:n, .packages = c("tcltk", "tcltk2"), .verbose = F) %dopar% {
i <<- i
tclTaskSchedule(1000, testfn(), id = paste0("task", i), redo = 10)
}
我可能也会将.noexport="testfn"
传递给foreach,但这不是必需的。
答案 1 :(得分:0)
即使没有tclTaskSchedule
,您也会发现另一个问题:
并行化 print
循环中的foreach
语句不会输出到交互式会话中:
来自a blog post:
foreach的一个问题是它为循环的每次迭代创建了新的RScript实例,这可以防止状态消息被记录到控制台输出。
解决方法是创建输出日志文件:
cat("", file="log.txt")
testfn <- function() cat("hello from", i, "\n", file="log.txt", append=TRUE)
foreach(i=1:n, .packages = c("tcltk", "tcltk2"), .verbose = T) %dopar% {
tclTaskSchedule(1000, testfn(), id = paste0("task", i), redo = 10)
}
然后可以使用tail -f log.txt
终端中的bash
来监控此情况。