我有一个运行多个文件的 R 脚本,例如 file=1 到 50。我通常通过更改 R 脚本中的数字来提交重复的作业,例如每次 10 个文件 5 次。那么,如何才能一次提交5个作业而不需要提交5次作业呢?另外,我想更新一下默认输出和错误文件对于每项工作。
示例 bash 代码:
#!/bin/bash
#PBS -l nodes=1:ppn=20,walltime=05:00:00
#PBS -m e
#PBS -o default.out
#PBS -e errorfile
module load R/4.0
Rscript ~/r_script1.R
答案1
您可以在命令行中指定任何或所有这些选项qsub
,而不是#PBS ...
在脚本中作为注释。
例如,您的批处理脚本可以重写为:
qsub -l nodes=1:ppn=20,walltime=05:00:00 -m e -o default.out -e errorfile script.sh
使用 qsub 命令行上的所有选项,script.sh
只需要包含:
#!/bin/bash
module load R/4.0
Rscript ~/r_script1.R
您可以混合使用这两种方法来为 qsub 提供选项。例如,您可以在命令行上提供-o
和-e
选项,并将脚本中的其余部分作为#PBS
注释:
$ qsub -o default.out -e errorfile script2.sh
脚本2.sh:
#!/bin/bash
#PBS -l nodes=1:ppn=20,walltime=05:00:00
#PBS -m e
module load R/4.0
Rscript ~/r_script1.R
然后您可以将其与 bashfor
循环结合起来:
for i in {1..5} ; do
qsub -o "default.$i.out" -e "errorfile.$i" script2.sh
done
如果您需要将循环变量的值传递$i
给脚本,这是可能的 - 但有几种不同的方法可以做到这一点,具体取决于您使用的集群管理软件(例如 slurm 或 Torque 或其他软件)。最简单且无论qsub
您使用哪个版本都可能可用的方法之一是使用 qsub 的-v
选项。
例如,如果您需要在每个作业中运行不同的 R 脚本,r_script1.R、r_script2.R 等,您可以使用在脚本环境中可用-v i
:$i
for i in {1..5} ; do
qsub -o "default.$i.out" -e "errorfile.$i" -v i script3.sh
done
脚本3.sh:
#!/bin/bash
#PBS -l nodes=1:ppn=20,walltime=05:00:00
#PBS -m e
module load R/4.0
Rscript ~/r_script"$i".R
qsub 的某些实现允许直接在命令行上将参数传递给脚本,然后您可以将其用作脚本中的普通位置参数($1、$2、$3 等)。
大多数(全部?)实现qsub
还支持-t
指定作业数组的选项。可以使用 PBS_ARRAYID 环境变量在作业脚本中访问它。例如
qsub script4.sh
script4.sh(这对输出和错误文件使用 shell 重定向,而不是 qsub-o
和-e
选项):
#!/bin/bash
#PBS -l nodes=1:ppn=20,walltime=05:00:00
#PBS -m e
#PBS -t 1-5
module load R/4.0
Rscript ~/r_script"$PBS_ARRAYID".R > "default.$PBS_ARRAYID.out" 2> "errorfile.$PBS_ARRAYID"
Sys.getenv("PBS_ARRAYID")
顺便说一句,PBS_ARRAYID 是一个导出的环境变量,因此如果需要,可以在 R 脚本中访问。例如,您可以使用它来构造输入和输出文件名以及 if/then/else 决策来控制 R 脚本的操作。这比同一个 R 脚本有多个略有不同的版本要好。
注意:虽然我曾经管理过同时运行 Torque 和 slurm 的 HPC 集群,但距我这样做已经过去了大约 8 年。上述所有示例都是凭记忆编写的(并qsub
在互联网上搜索手册页),尚未在实际集群上进行测试。他们可能(可能会)需要一些更改才能工作,特别是使用 $PBS_ARRAYID 的最后一个示例 - 它们是作为如何做你想做的事情的粗略示例提供的。