这个任务适合rslurm吗?

问题描述 投票:0回答:1

我有几个实验,我想在每个节点上运行一个实验,每个实验都是具有多个核心的一系列执行。现在我的代码看起来像:

run_seeds <- c(1,2,3,4,5,6,7,8,9,10)

write_lines(paste("problem", "run_seed", "num_patients", "method", "name", "type", "error", sep="\t"), file=err_file_name)

# initialize loop
for (j in 1:length(run_seeds)) {
    ...
}

# start loop
for (i in range_pat) {

  print(paste("iteration",i))
  
  for (j in 1:length(run_seeds)) {

    run_seed<-run_seeds[[j]]
    set.seed(run_seed)
    ...
    write_lines(paste(problem, run_seed, i, "dst", ind_name, type, error, sep="\t"), file=err_file_name, append=TRUE)

  }
}

这个任务适合rslurm吗?如果是这样,我该如何更改代码?通过查看给出的示例https://cran.r-project.org/web/packages/rslurm/vignettes/rslurm.html,我不一定要导出 rds 文件或生成 slurm 脚本。我想在一个 slurm 脚本中运行它。可行吗?或者我需要将其更改为 rslurm 可接受的格式吗?此外,节点返回的结果有一定的顺序。还可以吗

如果没有,你会推荐我使用什么包?

r parallel-processing mpi slurm multicore
1个回答
0
投票

Slurm 仍然在各个 HPC 中心以不同的默认设置和 R 最佳实践使用,因此在尝试通过 R 脚本管理 Slurm 之前,有必要学习一些直接使用 Slurm 的基础知识。

对于多节点实验,您应该编写两个脚本:Slurm 提交脚本(例如 script.sh)和启用 MPI 的 R 脚本(例如 script.R)。

提交脚本请求节点,请求您的软件环境(R 版本、BLAS 库、MPI 版本等),这在不同的 HPC 中心中会有所不同,您需要咨询可用的内容。例如,

script.sh
可能如下所示:

#!/bin/bash
#SBATCH -A <your-account>
#SBATCH -p <submission-queue-name>
#SBATCH --nodes=4
#SBATCH --exclusive
#SBATCH -t 00:02:00

cd <directory-of-your-rscript>

module load r
module load openmpi

time mpirun --map-by ppr:1:node Rscript  script.R

使用

sbatch script.sh
提交脚本。这请求对 4 个节点上的所有核心进行独占访问,作业限制为 2 分钟。 <...> 中的项目应该是不言自明的。加载的模块在您的集群上可能有所不同,并且可能还需要其他模块,具体取决于 R 的部署方式。最后一行使用 OpenMPI,为每个节点运行一个
script.R
实例。

script.R
将使用包 pbdMPI,您可以在登录节点上的交互式 R 会话中从 CRAN 安装该包(同样,在特定于您的集群的适当
module load r
module load openmpi
之后)。

pbdMPI 提供独立于所使用的节点和核心数量的 RNG 再现性。在幕后,它使用来自 parallel 包的独立流。你的

script.R
看起来像这样:

library(pbdMPI)
num_streams <- 10

my_streams <- comm.chunk(num_streams, form = "vector", rng = TRUE, seed = 12345)

# initialize loop
for (j in my_streams) {
    err_file_name = paste0("err_file_", j, ".txt)
    write_lines(paste("problem", "run_seed", "num_patients", "method", "name", "type", "error", sep="\t"), file=err_file_name)
    ...
}


# start loop
for (i in range_pat) {

  comm.print(paste("iteration",i))
  
  for (j in my_streams) {
    comm.set.stream(j)
    err_file_name = paste0("err_file_", j, ".txt)
    ...
    write_lines(paste(problem, j, i, "dst", ind_name, type, error, sep="\t"), file=err_file_name, append=TRUE)
  }
}

finalize()

这里需要注意的几点:

  • 为了避免此代码的并行实例相互叠加,每个种子写入不同的文件。他们都得到了标题行。
  • 只有一个实例将迭代次数(等级 0)写入标准输出。
  • 由于每个节点上运行一个实例,因此该节点上的所有核心都可以并行工作。如果您自己管理此问题,我建议
    mclapply()
    。如果您不需要节点上的所有核心,则可以通过在
    --map-by
    OpenMPI 参数中指定来在每个节点运行此代码的多个实例。
  • 代码的每个实例都从
    my_streams
    获取自己的一组
    comm.chunk()
    my_streams
    只是一组索引值,用于为每个值设置独立的随机数流。流从中断处继续,并显示下一个
    i
    值。也可以通过参数
    i
    将它们重置回每个
    reset = TRUE
    的开头。
  • 如果您有大量种子,这最终可以扩展到任意数量的节点。它也可以使用单个种子来重现,与您使用的节点数或每个节点的实例数无关。
  • finalize()
    提供从 MPI 的优雅退出。
© www.soinside.com 2019 - 2024. All rights reserved.