运行 集群中不同节点上的并行 RandomForest

Running RandomForest in parallel on different nodes in a cluster

我想 运行 集群(大学服务器)上的并行 randomForest,我可以同时保留 4 个节点,每个节点进一步包含 12 个核心。我使用了 foreach 包描述中提到的 foreach 和 doSNOW 包,但是通过使用以下代码,我可以看到所有负载都在第一个节点上,而对于其他 3 个节点,没有内存消耗。有人可以指导我如何编辑这段代码,以便每个节点的每个核心都得到平等的工作,然后我们将它组合成 1 个森林。

> library("foreach")
> library("doSNOW")
> registerDoSNOW(makeCluster(48, type="SOCK"))

> x <- matrix(runif(500), 100)
> y <- gl(2, 50)

> rf <- foreach(ntree = rep(22, 48), .combine = combine, .packages = "randomForest") %dopar%
+    randomForest(x, y, ntree = ntree)
> rf
Call:
randomForest(x = x, y = y, ntree = ntree)
Type of random forest: classification
Number of trees: 1056

要在 SOCK 集群中的多个节点上启动工作程序,makeCluster 的第一个参数应该是节点名称向量而不是数字。在这种情况下,makeCluster 将使用 ssh 命令在每个指定节点上启动一个 worker。

例如,要在每个节点 "n1"、"n2"、"n3" 和 "n4" 上启动 12 个 worker,您可以使用:

> nodelist <- rep(c("n1", "n2", "n3", "n4"), each=12)
> cl <- makeCluster(nodelist, type="SOCK")
> registerDoSNOW(cl)

注意每个节点名在nodelist中出现了12次,所以nodelist的长度是48。

如果您正在使用批处理排队系统 运行 您的作业,您应该获得分配给您的作业的节点名称列表,而不是在脚本中对它们进行硬编码。您通常可以从环境变量中获取该信息,但这取决于您的批处理排队系统。例如,对于 Torque,您可以使用以下方式获取节点列表:

> nodelist <- readLines(Sys.getenv("PBS_NODEFILE"))

我更喜欢使用 makeMPIcluster 创建 MPI 集群,并在 运行 在 HPC 集群上执行并行作业时将其注册到 doSNOW,但这种方法对初学者来说可能更难。例如,您必须安装 Rmpi​​ 包并且必须通过 "mpirun" 命令执行 R 脚本。如果你能从知识渊博的系统管理员那里得到帮助,它可能会在长期 运行.

中工作得更好

另一种方法是使用 doMPI 并行后端而不是 doSNOW,因为 doMPI 是专门为在 HPC 集群上使用而设计的。有关详细信息,请参阅 doMPI vignette.


另请注意,如果在此示例中使用 foreach .multicombine=TRUE 参数,您将获得更好的性能。这将导致 combine 函数被调用一次而不是 47 次。