假设我有一个parApply()
通话,如下:
cl <- makeCluster("FORK", 5)
parApply(cl = cl, X = my.mat, MARGIN = 1, FUN = myFun)
nrow(my.mat)
很大,但是myFun()
的计算速度很快。请注意,cl
的核心数为5
。我想知道如何进行并行化。
my.mat
是否被分为5个子矩阵,然后每个子矩阵都由一个线程处理,然后在所有线程完成后合并在一起?还是通过将my.mat
的元素一一发送到每个线程来完成?
答案 0 :(得分:1)
以下是R文档中的一些解释:
parLapply , parSapply 和 parApply 是lapply的并行版本, 申请并申请。 大块计算静态分配给 使用 clusterApply 的节点。默认情况下,块数相同 作为节点数。 parLapplyLB , parSapplyLB 版本,旨在将FUN应用于以下内容的不同元素时使用 X需要花费相当多的时间,并且其中一个函数是 不需要确定性或可重复的结果。的块 使用 clusterApplyLB 将计算动态分配给节点。
请注意,R / 3.5.0中进行了一些更改:
从R 3.5.0起,默认的块数是块数的两倍 节点。在R 3.5.0之前,块的(固定)数目与 节点数。至于 clusterApplyLB ,通过负载均衡 执行特定作业的节点是不确定的,并且 将RNG流分配给节点的模拟将无法重现。
clusterApply 在第一个节点上使用参数x [[1]]和 ...,在第二个节点上使用x [[2]]和...,依此类推,回收 节点。
clauterApplyLB
的工作方式略有不同:
clusterApplyLB 是clusterApply的负载平衡版本。如果 x的长度n不大于节点p的数量,则作业为 发送到n个节点。否则,将前p个作业按顺序放置在 p个节点。当第一个作业完成时,下一个作业将放置在 已变为免费的节点;这一直持续到所有作业完成为止。 使用 clusterApplyLB 可以比 使用 clusterApply ,但是增加交流可以减少 性能。此外,执行特定作业的节点是 不确定的。这意味着分配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)