1

假设我有一个parApply()电话如下:

cl <- makeCluster("FORK", 5)
parApply(cl = cl, X = my.mat, MARGIN = 1, FUN = myFun)

Wherenrow(my.mat)非常大,但myFun()计算速度非常快。请注意,核心数cl5。我想知道如何进行并行化。

my.mat分成5个子矩阵,然后每个子矩阵由一个线程处理,然后在所有线程完成后组合在一起?还是通过将元素my.mat一个一个地发送到每个线程来完成?

4

1 回答 1

1

以下是 R 文档中的一些解释:

parLapplyparSapplyparApply是 lapply、 sapply 和 apply 的并行版本。使用clusterApply将计算块静态分配给节点 。默认情况下,块的数量与节点的数量相同。parLapplyLBparSapplyLB是负载平衡版本,用于将 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)
于 2019-06-26T13:27:04.810 回答