了解R中mclapply和parLapply之间的区别

fivyi3re  于 2023-02-20  发布在  其他
关注(0)|答案(3)|浏览(207)

我最近开始在一个项目中使用R中的并行技术,并使用parallel包中的mclapply在Linux系统上运行我的程序,但是,我对parLapply for Windows的理解遇到了障碍。
使用mclapply,我可以设置内核数量、迭代次数,并将其传递给工作区中的现有函数。

mclapply(1:8, function(z) adder(z, 100), mc.cores=4)

我似乎不能在windows中使用parLapply实现同样的效果,据我所知,我需要使用clusterExport()传递所有变量,并将我想要应用的实际函数传递到参数中。
这是正确的,还是有类似于mclapply函数的东西适用于Windows?

fnatzsnv

fnatzsnv1#

mclapply的美妙之处在于,在调用mclapply时,所有工作进程都被创建为主进程的克隆,因此您不必担心在每个集群工作进程上复制您的环境,不幸的是,这在Windows上是不可能的。
使用parLapply时,通常必须执行以下附加步骤:

  • 创建PSOCK群集
  • 根据需要注册群集
  • 在群集工作进程上加载必要的软件包
  • 将必要的数据和函数导出到集群工作线程的全局环境

此外,完成后,最好使用stopCluster关闭PSOCK群集。
下面是您的示例到parLapply的翻译:

library(parallel)
cl <- makePSOCKcluster(4)
setDefaultCluster(cl)
adder <- function(a, b) a + b
clusterExport(NULL, c('adder'))
parLapply(NULL, 1:8, function(z) adder(z, 100))

如果你的adder函数需要一个包,你必须在parLapply调用它之前在每个worker上加载这个包,你可以很容易地在clusterEvalQ中做到这一点:

clusterEvalQ(NULL, library(MASS))

注意,clusterExportclusterEvalparLapply的第一个参数NULL表示它们应该使用通过setDefaultCluster注册的集群对象。如果程序在许多不同的函数中使用mclapply,这将非常有用。这样,在转换程序以使用parLapply时,就不必将cluster对象传递给每个需要它的函数。
当然,adder可能会调用全局环境中的其他函数,而全局环境又调用了其他函数等。在这种情况下,您还必须导出它们,并加载它们所需的任何包。还要注意的是,如果您导出的任何变量在程序运行过程中发生了更改,则必须再次导出它们,以便在集群工作线程上更新它们。同样,对于mclapply,这是不必要的,因为无论何时调用它,它总是创建/克隆/派生工作线程,因此这是不必要的。

gopyfrb3

gopyfrb32#

mclapply使用起来更简单,它使用底层操作系统的fork()功能来实现并行化。但是,由于Windows没有fork(),它将运行标准的lapply--没有并行化。
parLapply则不同,它将创建一个进程集群,这些进程甚至可以驻留在网络上的不同机器上,它们通过TCP/IP通信,以便在彼此之间传递任务和结果。
代码中的问题在于,你没有意识到parLapply的第一个参数应该是一个“cluster”对象,我能想到的在一台机器上运行parLapply的最简单的例子是:

library(parallel)

# Spawn child processes using fork() on the local machine
cl <- makeForkCluster(getOption("cl.cores", 2))

# Use parLapply to calculate lengths of 1000 strings
text = rep("Hello, world!", 1000)
len = parLapply(cl, text, nchar)

# Kill child processes since they are no longer needed
stopCluster(cl)

在使用makeForkCluster创建的集群中使用parLapply在功能上等同于调用mclapply,因此它在Windows上也不起作用。:)查看文档中使用makeCluster和makePSOCKcluster创建集群的其他方法,并找出最适合您需求的方法。

72qzrwbm

72qzrwbm3#

下面是我如何使用parLapply进行并行计算:

library(parallel)
##
test_func0 = function(i) {
  lfactorial(i) + q + d
}
##
x = 1:100
q=20
d= 25
##
t1=Sys.time()
##
clust <- makeCluster(4)

## clusterExport loads these objects from the specified environment into the clust object
clusterExport(clust, c("test_func0", "q", "d"), envir = environment())
a <- do.call(c, parLapply(clust, x, function(i) {
  test_func0(i)
}))
print(Sys.time()-t1)
##
stopCluster(clust)

请记住,makeClustermakePSOCKcluster更快地创建变量的环境集群以提供给parLapply

相关问题