2016-01-14 42 views
10

我期待在R6對象的窗口中使用parLapply(),並注意到(至少在某些情況下)我不需要將R6函數或數據導出到節點。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)我可以依賴這種行爲嗎?或者這是這些具體例子的人造物嗎?

UPDATE:

對象已經被實例化後,這種現象也出現利用公共方法和成員的工作:

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 

回答

1

隨着R6類,每次你實例化一個對象時,該對象通過修改後的環境獲取每個函數/方法的副本。爲這些功能分配了一個環境,其中self指向該對象的公共環境(這是該對象的公共環境),private指向該對象的私有環境。

這與S3方法不同,後者不會針對對象的每個實例化進行復制。

總結:在R6中,一切都是自包含在對象中;與S3,該對象不包含方法。

我對使用parLapply並不熟悉,但我認爲依靠parLapply這樣的工作是安全的。

+0

謝謝!這是一個很大的幫助 – chandler

+0

我對這個解釋有點困惑:不應該同樣適用於S3,因爲R的每個分支都會得到它自己的工作集副本(操作系統內核處理這個,而不是R) ?無論如何,我一直在使用'mclapply'(我不使用'parLapply'或顯式集羣),我從來不需要導出任何東西。 –

+0

這聽起來像你在os x/linux上的工作。從我的(有限的)理解中,在這些操作系統上,「fork」得到整個工作目錄,這在Windows上不會發生。這就是爲什麼我對這種行爲很好奇,因爲它不會要求我們的Windows用戶導出任何方法或成員(從而使並行實現更加方便)。另外,我對s3沒有太多的工作,所以我不能評論它在類似情況下的行爲 – chandler