29

我最近开始在 R 中为一个项目使用并行技术,并使用并行包中的mclapply我的程序在 Linux 系统上运行。但是,我对 Windows 的理解遇到了障碍。parLapply

使用mclapply我可以设置核心数、迭代数,并将其传递给我工作区中的现有函数。

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

我似乎无法在 Windows 中使用parLapply. 据我了解,我需要通过 using 传递所有变量clusterExport(),并将我想要应用的实际函数传递给参数。

这是正确的还是有类似于mclapply适用于 Windows 的功能的东西?

4

2 回答 2

34

其美妙之mclapply处在于,工作进程都是在mclapply被调用的点上作为主进程的克隆创建的,因此您不必担心在每个集群工作人员上复制您的环境。不幸的是,这在 Windows 上是不可能的。

使用时parLapply,您通常必须执行以下附加步骤:

  • 创建 PSOCK 集群
  • 如果需要,注册集群
  • 在集群工作人员上加载必要的包
  • 将必要的数据和功能导出到集群工作者的全局环境

此外,完成后,最好使用stopCluster.

这是您的示例的翻译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. 你可以很容易地做到这一点clusterEvalQ

clusterEvalQ(NULL, library(MASS))

请注意, 和 的第一个NULL参数表示它们应该使用通过 注册的集群对象。如果您的程序在许多不同的函数中使用,这将非常有用,这样您就不必在将程序转换为 use 时将集群对象传递给每个需要它的函数。clusterExportclusterEvalparLapplysetDefaultClustermclapplyparLapply

当然,adder可能会调用全局环境中调用其他函数等的其他函数。在这种情况下,您还必须导出它们并加载它们需要的任何包。另请注意,如果您导出的任何变量在程序过程中发生变化,您必须再次导出它们才能在集群工作程序上更新它们。同样,这不是必需的,mclapply因为它总是在调用时创建/克隆/分叉工人,因此没有必要。

于 2013-06-19T21:22:05.060 回答
4

mclapply 使用更简单,并使用底层操作系统的 fork() 功能来实现并行化。但是,由于 Windows 没有 fork(),它将改为运行标准 lapply - 没有并行化。

parLapply 是一个不同的野兽。它将创建一个进程集群,这些进程甚至可以驻留在网络上的不同机器上,它们通过 TCP/IP 进行通信,以便在彼此之间传递任务和结果。

您的代码中的问题是您没有意识到 parLapply 的第一个参数应该是“集群”对象。我能想到的使用 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)

将 parLapply 与上述使用 makeForkCluster 创建的集群一起使用在功能上等同于调用 mclapply。所以它也不能在 Windows 上运行。:) 在文档中查看可以使用 makeCluster 和 makePSOCKcluster 创建集群的其他方法,并查看最适合您要求的方法。

于 2013-06-19T17:28:58.357 回答