【问题标题】:parLapply within R6 classesparLapply 在 R6 类中
【发布时间】:2016-01-14 08:38:29
【问题描述】:

我希望在 R6 对象内的 Windows 上使用 parLapply(),并注意到(至少在某些情况下)我不需要将 R6 函数或数据导出到节点。

这是我可以在parLapply() 中访问私有方法的示例:

require(R6);require(parallel)
square <-
R6Class("square",
        public = list(
            numbers = NA,
            squares = NA,
            initialize = function(numbers,integer) {
                self$numbers <- numbers
                squares <- private$square.numbers()
            }
        ),
        private = list(
            square = function(x) {
                return(x^2)
            },
            square.numbers = function() {
                cl <- makeCluster(detectCores())
                self$squares <- parLapply(cl,
                                          self$numbers,
                                          function (x) private$square(x)
                                          )
                stopCluster(cl)
            }
        ))
##Test
test <- square$new(list(1,2,3))
print(test$squares)
# [[1]]
# [1] 1
# 
# [[2]]
# [1] 4
# 
# [[3]]
# [1] 9

还有第二个例子,我也可以访问公共成员:

square2 <-
R6Class("square2",
        public = list(
            numbers = NA,
            squares = NA,
            integer = NA,
            initialize = function(numbers,integer) {
                self$numbers <- numbers
                self$integer <- integer
                squares <- private$square.numbers()
            }
        ),
        private = list(
            square = function(x) {
                return(x^2)
            },
            square.numbers = function() {
                cl <- makeCluster(detectCores())
                self$squares <- parLapply(cl,
                                          self$numbers,
                                          function (x) private$square(x)+self$integer
                                          )
                stopCluster(cl)
            }
        ))
##Test
test2 <- square2$new(list(1,2,3),2)
print(test2$squares)
#[[1]]
#[1] 3
#
#[[2]]
#[1] 6
#
#[[3]]
#[1] 11

我的问题是双重的:(1) R6 是什么让这成为可能,这样我就不需要导出数据对象和函数; (2) 我可以依赖这种行为还是这些具体示例的产物?

更新:

在对象被实例化后,这种行为似乎也适用于公共方法和成员:

square3 <- R6Class(
    classname = "square3",
    public = list(
        numbers = NA,
        squares = NA,
        integer = NA,
        square = function(x) {
           return(x^2)
        },
        square.numbers = function() {
            cl <- makeCluster(detectCores())
            self$squares <- parLapply(cl,
                                      self$numbers,
                                   function (x) self$square(x)+self$integer
                                  )
        stopCluster(cl)
    },
    initialize = function(numbers,integer) {
        self$numbers <- numbers
        self$integer <- integer
    }
    )
)
test3.obj <- square3$new(list(1,2,3),2)
test3.obj$square.numbers()
test3.obj$squares

# [[1]] 
# [1] 3
#
# [[2]]
# [1] 6
#
# [[3]]
# [1] 11

【问题讨论】:

    标签: r parallel-processing r6


    【解决方案1】:

    使用 R6 类,每次实例化一个对象时,该对象都会获得每个函数/方法的副本,并带有修改后的环境。函数被分配一个环境,其中self 指向对象的公共环境(这是对象的公共面),private 指向对象的私有环境。

    这与 S3 方法不同,S3 方法不会为对象的每个实例化复制。

    总结:在 R6 中,一切都在对象中自包含;对于 S3,对象不包含方法。

    我对使用 parLapply 不是很熟悉,但我认为使用 parLapply 进行类似工作是安全的。

    【讨论】:

    • 我对这个解释有点困惑:不应该同样适用于 S3,因为 R 的每个分支都有自己的工作集副本(操作系统内核处理这个,而不是R)?无论如何,我一直都像这样使用mclapply(我不使用parLapply 或显式集群),我从来不需要导出任何东西。
    • 听起来你在 os x/linux 上工作。根据我的(有限)理解,在这些操作系统上,“fork”获取整个工作目录,这在 Windows 上不会发生。这就是为什么我对这种行为如此好奇的原因,因为它不需要我们的 Windows 用户导出任何方法或成员(从而使并行实现更加方便)。另外,我对 s3 的工作不多,所以我无法评论它在类似情况下的行为
    猜你喜欢
    • 1970-01-01
    • 2021-09-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多