我有几个实验,我想在每个节点上运行一个实验,每个实验都是具有多个核心的一系列执行。现在我的代码看起来像:
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 可接受的格式吗?此外,节点返回的结果有一定的顺序。还可以吗
如果没有,你会推荐我使用什么包?
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()
这里需要注意的几点:
mclapply()
。如果您不需要节点上的所有核心,则可以通过在 --map-by
OpenMPI 参数中指定来在每个节点运行此代码的多个实例。my_streams
获取自己的一组 comm.chunk()
。 my_streams
只是一组索引值,用于为每个值设置独立的随机数流。流从中断处继续,并显示下一个 i
值。也可以通过参数 i
将它们重置回每个 reset = TRUE
的开头。finalize()
提供从 MPI 的优雅退出。