以下是 R 文档中的一些解释:
parLapply、parSapply和parApply是 lapply、 sapply 和 apply 的并行版本。使用clusterApply将计算块静态分配给节点 。默认情况下,块的数量与节点的数量相同。parLapplyLB,parSapplyLB是负载平衡版本,用于将 FUN 应用于 X 的不同元素需要相当多的时间,并且该函数是确定性的或不需要可重现的结果。计算块使用clusterApplyLB动态分配给节点。
请注意,在 R/3.5.0 中进行了一些更改:
从 R 3.5.0 开始,默认的块数是节点数的两倍。在 R 3.5.0 之前,(固定)块数与节点数相同。至于clusterApplyLB,通过负载平衡,执行特定作业的节点是不确定的,将 RNG 流分配给节点的模拟将无法重现。
clusterApply在带有参数 x[[1]] 和 ... 的第一个节点上调用 fun,在带有 x[[2]] 和 ... 的第二个节点上调用 fun,依此类推,根据需要回收节点。
有clauterApplyLB
一点不同:
clusterApplyLB是 clusterApply 的负载均衡版本。如果 x 的长度 n 不大于节点数 p,则将作业发送到 n 个节点。否则,前 p 个作业按顺序放置在 p 个节点上。当第一个作业完成时,下一个作业被放置在已经空闲的节点上;这一直持续到所有作业完成。与使用clusterApply相比,使用clusterApplyLB可以提高集群利用率,但增加通信会降低性能。此外,执行特定作业的节点是不确定的。这意味着将 RNG 流分配给节点的模拟将无法重现。
所以当你使用parApply
你的矩阵时,它被分成了 5 个块。每个块由其中一个核心处理。在 par*ApplyLB 系列函数的情况下,元素被一个一个地分配给核心,一旦一个核心完成其任务,另一个核心被分配给它。
这是以下代码的输出:
library(parallel)
my.mat <- matrix(c(1:20,rep(0,20)), ncol=2)
head(my.mat)
# [,1] [,2]
# [1,] 1 0
# [2,] 2 0
# [3,] 3 0
# [4,] 4 0
# [5,] 5 0
# [6,] 6 0
cl <- makeCluster(5, "FORK")
parApply(cl = cl, X = my.mat, MARGIN = 1, FUN = function(x){print(paste("sum= ", sum(x), " pid=",Sys.getpid()))})
# [1] "sum= 1 pid= 42569"
# [2] "sum= 2 pid= 42569"
# [3] "sum= 3 pid= 42569"
# [4] "sum= 4 pid= 42569"
# [5] "sum= 5 pid= 42570"
# [6] "sum= 6 pid= 42570"
# [7] "sum= 7 pid= 42570"
# [8] "sum= 8 pid= 42570"
# [9] "sum= 9 pid= 42571"
# [10] "sum= 10 pid= 42571"
# [11] "sum= 11 pid= 42571"
# [12] "sum= 12 pid= 42571"
# [13] "sum= 13 pid= 42572"
# [14] "sum= 14 pid= 42572"
# [15] "sum= 15 pid= 42572"
# [16] "sum= 16 pid= 42572"
# [17] "sum= 17 pid= 42573"
# [18] "sum= 18 pid= 42573"
# [19] "sum= 19 pid= 42573"
# [20] "sum= 20 pid= 42573"
stopCluster(cl)
parLapplyLB
如果我使用块大小=1,请注意与以下输出的区别(查看 pid 值的分布方式) :
mylist <- 1:20
cl <- makeCluster(5, "FORK")
parLapplyLB(cl = cl, X = mylist,function(x){print(paste("sum= ", sum(x), " pid=",Sys.getpid()))}, chunk.size = 1)
# [[1]]
# [1] "sum= 1 pid= 64019"
#
# [[2]]
# [1] "sum= 2 pid= 64020"
#
# [[3]]
# [1] "sum= 3 pid= 64021"
#
# [[4]]
# [1] "sum= 4 pid= 64022"
#
# [[5]]
# [1] "sum= 5 pid= 64023"
#
# [[6]]
# [1] "sum= 6 pid= 64019"
#
# [[7]]
# [1] "sum= 7 pid= 64020"
#
# [[8]]
# [1] "sum= 8 pid= 64019"
#
# [[9]]
# [1] "sum= 9 pid= 64020"
#
# [[10]]
# [1] "sum= 10 pid= 64019"
# . . .
stopCluster(cl)