2

最近,我正在尝试将引用类与parallel. 我尝试了 4 种不同的方案,多核、MPI、Socket 和 Forking。但是,只有多核才能产生正确的结果。而 MPI、PSOCK 和 Forking 都会产生错误。

PS:我在支持 MPI 的计算机集群上运行此脚本。

library(doParallel)

np = 4L
# cl <- makeCluster(np, type="MPI", outfile = "")
# cl <- makeCluster(np, type="PSOCK", outfile = "")
# cl <- makeCluster(np, type="FORK", outfile = "")
cl <- np # multicore

registerDoParallel(cl)
myClass = setRefClass("myClass",
    fields = c("a"),
    methods = list(
        hello = function(){cat("hello\n")},
        show = function(){cat("show\n")}
    )
)
objs = foreach(i = 1:4) %dopar% {
    obj = new("myClass")
    obj$a=i
    obj
}

它可能与参考类的并行计算有关

更新:

更多调查表明,引用类实例是克隆的,但不是引用类定义。

library(doParallel)

np = 4L
cl <- makeCluster(np, type="MPI", outfile = "")
# cl <- makeCluster(np, type="PSOCK", outfile = "")
# cl <- makeCluster(np, type="FORK", outfile = "")
# cl <- np # multicore
registerDoParallel(cl)

myClass = setRefClass("myClass",
    fields = c("a"),
    methods = list(
        hello = function(){cat("hello\n")},
        show = function(){cat("show\n")}
    )
)
obj = new("myClass")
obj$a = 0

results = foreach(i = 1:4) %dopar% {
    obj$a # no error
    newobj = new("myClass") # error
}
4

1 回答 1

2

问题是集群工作者需要被初始化。对于这样的情况,我会使用clusterEvalQor clusterCall

clusterEvalQ(cl, {
    myClass <- setRefClass("myClass",
                           fields = c("a"),
                           methods = list(
                               hello = function(){cat("hello\n")},
                               show = function(){cat("show\n")}
                           ))
    NULL
})

请注意,我在 R 表达式中包含了“NULL”,以避免序列化并从集群工作人员返回生成器函数。

使用“多核”版本时,不需要此初始化,因为使用了 mclapply,因此通过执行初始化的主进程分叉来初始化工作程序。

有趣的是,在使用“FORK”集群时不必进行此初始化,但必须在创建“FORK”集群setRefClass 之前调用。

于 2014-03-09T16:47:28.163 回答