我有一个大的列表(~30GB),功能如下:
cl <- makeCluster(24, outfile = "")
Foo1 <- function(cl, largeList) {
return(parLapply(cl, largeList, Bar))
}
Bar1 <- function(listElement) {
return(nrow(listElement))
}
Foo2 <- function(cl, largeList, arg) {
clusterExport(cl, list("arg"), envir = environment())
return(parLapply(cl, largeList, function(x) Bar(x, arg)))
}
Bar2 <- function(listElement, arg) {
return(nrow(listElement))
}
没有问题:
Foo1(cl, largeList)
观察每个进程的内存使用情况我可以看到只有一个列表元素被复制到每个节点。
然而,在致电时:
Foo2(cl, largeList, 0)
正在将largeList的副本复制到每个节点。单步执行Foo2,largeList复制不会发生在clusterExport上,而是发生在parLapply上。此外,当我从全局环境(不在函数内)执行Foo2的主体时,没有问题。造成这种情况的原因是什么?
> sessionInfo()
R version 3.2.2 (2015-08-14)
Platform: x86_64-redhat-linux-gnu (64-bit)
Running under: Fedora 21 (Twenty One)
locale:
[1] LC_CTYPE=en_US.UTF-8 LC_NUMERIC=C
[3] LC_TIME=en_US.UTF-8 LC_COLLATE=en_US.UTF-8
[5] LC_MONETARY=en_US.UTF-8 LC_MESSAGES=en_US.UTF-8
[7] LC_PAPER=en_US.UTF-8 LC_NAME=C
[9] LC_ADDRESS=C LC_TELEPHONE=C
[11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C
attached base packages:
[1] parallel splines stats graphics grDevices utils
[7] datasets methods base
other attached packages:
[1] xts_0.9-7 zoo_1.7-12 snow_0.3-13
[4] Rcpp_0.12.2 randomForest_4.6-12 gbm_2.1.1
[7] lattice_0.20-33 survival_2.38-3 e1071_1.6-7
loaded via a namespace (and not attached):
[1] class_7.3-13 tools_3.2.2 grid_3.2.2
答案 0 :(得分:2)
问题是作为parLapply
的第三个参数的worker函数被序列化并与输入数据一起发送给每个worker。如果在函数内部定义了worker函数,例如Foo2
,则本地环境将与其一起序列化。由于largeList
是Foo2
的参数,因此它位于本地环境中,因此与worker函数一起序列化。
您对Foo1
没有问题,因为Bar
可能是在全球环境中创建的,而且全局环境从未与函数一起序列化。
换句话说,在使用parLapply
,clusterApply
,clusterApplyLB
等时,始终在全局环境或包中定义辅助功能是个好主意。当然,如果您从全局环境中调用parLapply
,则匿名函数将在全局环境中定义。