我正在使用一个 R 脚本,它基本上将命令行命令粘贴在一起通过
system2()
执行。这些命令运行一些 Java 应用程序。
现在,我想立即生成该 Java 应用程序的多个进程,以在集群计算机上执行一些任务。作业通过 Slurm 提交。使用
doParallel
以及为 Slurm 作业保留的核心数量从 R 内部执行系统调用是否有意义?或者是否有更有效的选项(例如,通过 Slurm 并行运行 R 脚本的多个实例,以便生成并行 Java 实例)?
我不确定 Slurm 或
parallel
如何分配资源以及如何最有效地生成进程。哪个进程将控制此设置中 Java 实例的执行位置?
Slurm 作业示例:
#!/bin/bash
#SBATCH --job-name=somejob
#SBATCH --output=somejob%a.out
#SBATCH --time=2:00:00
#SBATCH --partition=node
#SBATCH --qos=normal
#SBATCH --account=node
#SBATCH --cpus-per-task=20
#SBATCH --mem-per-cpu=3200
#SBATCH --ntasks=1
#SBATCH --array=1#-12
srun R --vanilla -f somescript.R
R 脚本示例:
#!/usr/bin/env Rscript
require("doParallel")
cl <- parallel::makeCluster(20)
doParallel::registerDoParallel(cl)
foreach::foreach(
arg1 = 1:20, .packages = "mypackage"
) %dopar% {
arg2 <- "some_arg"
system2("/path/to/java.exe", args = c(arg1, arg2), stdout = TRUE)
}
假设您有一个节点集群,每个节点都有 32 个核心,以下 R 脚本和 shell 脚本将运行 2 个 R 会话,每个会话使用 32 个核心,以实现 Java 代码的 64 次并行执行。
library(mypackage) # substitute your package name and add others
library(pbdMPI)
my_arg1 = comm.chunk(64, form = "vector") # gets arg1 instances for this rank
sys_call = function(arg1) {
arg2 <- "some_arg"
system2("/path/to/java.exe", args = c(arg1, arg2), stdout = TRUE)
}
mclapply(my_arg1, sys_call, mc.cores = 32)
finalize()
将以上内容保存在
my_r_script.R
中。
#!/bin/bash
#SBATCH --nodes=2
#SBATCH --exclusive
module load r
mpirun --map-by ppr:1:node Rscript my_r_script.R
将以上内容保存在
my_script.sh
中并使用 sbatch my_script.sh
提交到 Slurm。
shell 脚本要求 2 个节点以及节点上的所有核心。 OpenMPI
mpirun
每个节点放置 1 个 R 会话,并且由于独占访问,所有内核均可用于 mclapply()
。
您可能需要加载提供您的软件环境的模块,包括
module load r
。这些详细信息通常取决于站点。
您将需要额外的
#SBATCH
帐户、队列、时间和可能的内存参数,这些参数可能因具有不同本地默认值的不同集群而异。
您的
arg1
参数在 64 个实例中每个都不同,可用于在 Java 代码中创建不同的输出文件名。