关于并行任务的 `srun ... >output_file` 的语义
On the semantics of `srun ... >output_file` for parallel tasks
抱歉,这个问题需要大量的积累,但总而言之,它是关于 srun ... >output_file
的许多并行实例会或不会导致某些 process/task 其他 process/task.
产生的输出
案例 0:仅 bash(无 SLURM)
假设prog-0.sh
是下面的玩具脚本:
#!/bin/bash
hostname >&2
if [[ $JOB_INDEX = 0 ]]
then
date
fi
此脚本将一些输出打印到 stderr
,并可能将当前日期打印到 stdout
。
下面显示的 "driver" 脚本 case-0.sh
生成 $NJOBS
个进程,全部写入 [=30=]:
#!/bin/bash
for i in $( seq 0 $(( NJOBS - 1 )) )
do
JOB_INDEX=$i ./prog-0.sh >prog-0-stdout.txt &
done
宁运行后
% NJOBS=100 ./case-0.sh 2>prog-0-stderr.txt
...我的期望是 prog-0-stderr.txt
将包含 100 行,而 prog-0-stdout.txt
将是 空 .
我的期望实现了:
% wc prog-0-std*.txt
100 100 3000 prog-0-stderr.txt
0 0 0 prog-0-stdout.txt
100 100 3000 total
对这些结果的解释是,当 NJOBS
足够大时,对于某些足够高的 $i
值,可能会评估重定向 >prog-0-stdout.txt
在 "designated job" 之后,JOB_INDEX
0(也是唯一一个将输出发送到 stdout
的)已将日期写入 stdout
,因此这将破坏先前由 "designated job" 重定向到 prog-0-stdout.txt
.
的任何输出
顺便说一句,NJOBS
的值需要足够高才能使结果如我刚才所述。例如,如果我使用 NJOBS=2
:
% NJOBS=2 ./case-0.sh 2>prog-0-stderr.txt
...然后不仅 prog-0-stderr.txt
只包含 2 行(不足为奇),而且 prog-0-stdout.txt
将包含一个日期:
% cat prog-0-stdout.txt
Wed Oct 4 15:02:49 EDT 2017
在这种情况下,所有 >prog-0-stdout.txt
重定向都在指定作业将日期打印到 prog-0-stdout.txt
之前进行了评估。
案例 1:SLURM 作业数组
现在,考虑一个非常相似的场景,但改用 SLURM。脚本 prog-1.sh
与 prog-0.sh
相同,只是它检查不同的变量来决定是否将日期打印到 stdout
:
#!/bin/bash
hostname >&2
if [[ $SLURM_ARRAY_TASK_ID = 0 ]]
then
date
fi
这是相应的 "driver" 脚本,case-1.sh
:
#!/bin/bash
#SBATCH -t 1
#SBATCH -p test
#SBATCH -e prog-1-%02a-stderr.txt
#SBATCH -n 1
#SBATCH -a 0-99
srun ./prog-1.sh >prog-1-stdout.txt
与 case-0.sh
一样,此脚本将其主要步骤的输出重定向到单个文件 ./prog-1-stdout.txt
.
重要的是,此作业的所有 运行 ./prog-1.sh
节点都可以看到同一个文件。
如果我现在运行
sbatch case-1.sh
...我得到 100 个文件 prog-1-00-stderr.txt
... prog-1-99-stderr.txt
,每个文件包含 1 行,还有一个 空 prog-1-stdout.txt
。我假设前面的解释也解释了为什么 prog-1-stdout.txt
是空的。
到目前为止一切顺利。
案例 2:SLURM 任务
最后,再考虑一个基于 SLURM 的案例,这次使用核心脚本 prog-2.sh
和驱动程序脚本 case-2.sh
。同样,prog-2.sh
中唯一的变化是它检查的变量,以确定是否将日期打印到 stdout
:
#!/bin/bash
hostname >&2
if [[ $SLURM_PROCID = 1 ]]
then
date
fi
这里是 case-2.sh
:
#!/bin/bash
#SBATCH -t 1
#SBATCH -p test
#SBATCH -e prog-2-stderr.txt
#SBATCH -N 10
#SBATCH --tasks-per-node=10
srun -l ./prog-2.sh >prog-2-stdout.txt
和以前一样,prog-2-stdout.txt
对所有处理作业的节点可见。
现在,如果我 运行 sbatch case-2.sh
并等待批处理作业完成,那么 prog-2-stderr.txt
包含 100 行(如预期的那样),但是 我的惊喜,prog-2-stdout.txt
是不是空的。实际上,它包含一个日期:
% cat prog-2-stdout.txt
01: Wed Oct 4 15:21:17 EDT 2017
我能想到的唯一解释类似于我之前对 运行
时得到的结果给出的解释
% NJOBS=2 ./case-0.sh 2>prog-0-stderr.txt
如果这个解释是正确的,我担心 case-2.sh
比预期效果更好(即 prog-2-stdout.txt 最终得到正确的输出)只是巧合,有与并发事件的相对时间有关。
现在,终于,我的问题是:
Q: SLURM gua运行tee prog-2-stdout.txt
文件包含指定任务生成的输出(即打印date to stdout
) 当 >prog-2-stdout.txt
重定向被非指定任务之一评估时不会被破坏?
您对 srun 的工作原理有误解。在案例 1 中,srun 的使用无关紧要,因为它在批处理脚本中用于启动并行作业。在案例 1 中你只有一项任务,所以
srun ./prog-1.sh >prog-1-stdout.txt
等同于:
./prog-1.sh >prog-1-stdout.txt
案例 2 不同,因为您有不止一项任务。在这种情况下,srun -l ./prog-2.sh >prog-2-stdout.txt
只计算一次,srun 将负责产生 10*10 个任务。 srun会将所有task的输出重定向到job的master节点,它会写入prog-2-stdout.txt
.
因此您可以确定在这种情况下不会破坏输出文件,因为它只被计算一次。
抱歉,这个问题需要大量的积累,但总而言之,它是关于 srun ... >output_file
的许多并行实例会或不会导致某些 process/task 其他 process/task.
案例 0:仅 bash(无 SLURM)
假设prog-0.sh
是下面的玩具脚本:
#!/bin/bash
hostname >&2
if [[ $JOB_INDEX = 0 ]]
then
date
fi
此脚本将一些输出打印到 stderr
,并可能将当前日期打印到 stdout
。
下面显示的 "driver" 脚本 case-0.sh
生成 $NJOBS
个进程,全部写入 [=30=]:
#!/bin/bash
for i in $( seq 0 $(( NJOBS - 1 )) )
do
JOB_INDEX=$i ./prog-0.sh >prog-0-stdout.txt &
done
宁运行后
% NJOBS=100 ./case-0.sh 2>prog-0-stderr.txt
...我的期望是 prog-0-stderr.txt
将包含 100 行,而 prog-0-stdout.txt
将是 空 .
我的期望实现了:
% wc prog-0-std*.txt
100 100 3000 prog-0-stderr.txt
0 0 0 prog-0-stdout.txt
100 100 3000 total
对这些结果的解释是,当 NJOBS
足够大时,对于某些足够高的 $i
值,可能会评估重定向 >prog-0-stdout.txt
在 "designated job" 之后,JOB_INDEX
0(也是唯一一个将输出发送到 stdout
的)已将日期写入 stdout
,因此这将破坏先前由 "designated job" 重定向到 prog-0-stdout.txt
.
顺便说一句,NJOBS
的值需要足够高才能使结果如我刚才所述。例如,如果我使用 NJOBS=2
:
% NJOBS=2 ./case-0.sh 2>prog-0-stderr.txt
...然后不仅 prog-0-stderr.txt
只包含 2 行(不足为奇),而且 prog-0-stdout.txt
将包含一个日期:
% cat prog-0-stdout.txt
Wed Oct 4 15:02:49 EDT 2017
在这种情况下,所有 >prog-0-stdout.txt
重定向都在指定作业将日期打印到 prog-0-stdout.txt
之前进行了评估。
案例 1:SLURM 作业数组
现在,考虑一个非常相似的场景,但改用 SLURM。脚本 prog-1.sh
与 prog-0.sh
相同,只是它检查不同的变量来决定是否将日期打印到 stdout
:
#!/bin/bash
hostname >&2
if [[ $SLURM_ARRAY_TASK_ID = 0 ]]
then
date
fi
这是相应的 "driver" 脚本,case-1.sh
:
#!/bin/bash
#SBATCH -t 1
#SBATCH -p test
#SBATCH -e prog-1-%02a-stderr.txt
#SBATCH -n 1
#SBATCH -a 0-99
srun ./prog-1.sh >prog-1-stdout.txt
与 case-0.sh
一样,此脚本将其主要步骤的输出重定向到单个文件 ./prog-1-stdout.txt
.
重要的是,此作业的所有 运行 ./prog-1.sh
节点都可以看到同一个文件。
如果我现在运行
sbatch case-1.sh
...我得到 100 个文件 prog-1-00-stderr.txt
... prog-1-99-stderr.txt
,每个文件包含 1 行,还有一个 空 prog-1-stdout.txt
。我假设前面的解释也解释了为什么 prog-1-stdout.txt
是空的。
到目前为止一切顺利。
案例 2:SLURM 任务
最后,再考虑一个基于 SLURM 的案例,这次使用核心脚本 prog-2.sh
和驱动程序脚本 case-2.sh
。同样,prog-2.sh
中唯一的变化是它检查的变量,以确定是否将日期打印到 stdout
:
#!/bin/bash
hostname >&2
if [[ $SLURM_PROCID = 1 ]]
then
date
fi
这里是 case-2.sh
:
#!/bin/bash
#SBATCH -t 1
#SBATCH -p test
#SBATCH -e prog-2-stderr.txt
#SBATCH -N 10
#SBATCH --tasks-per-node=10
srun -l ./prog-2.sh >prog-2-stdout.txt
和以前一样,prog-2-stdout.txt
对所有处理作业的节点可见。
现在,如果我 运行 sbatch case-2.sh
并等待批处理作业完成,那么 prog-2-stderr.txt
包含 100 行(如预期的那样),但是 我的惊喜,prog-2-stdout.txt
是不是空的。实际上,它包含一个日期:
% cat prog-2-stdout.txt
01: Wed Oct 4 15:21:17 EDT 2017
我能想到的唯一解释类似于我之前对 运行
时得到的结果给出的解释% NJOBS=2 ./case-0.sh 2>prog-0-stderr.txt
如果这个解释是正确的,我担心 case-2.sh
比预期效果更好(即 prog-2-stdout.txt 最终得到正确的输出)只是巧合,有与并发事件的相对时间有关。
现在,终于,我的问题是:
Q: SLURM gua运行tee prog-2-stdout.txt
文件包含指定任务生成的输出(即打印date to stdout
) 当 >prog-2-stdout.txt
重定向被非指定任务之一评估时不会被破坏?
您对 srun 的工作原理有误解。在案例 1 中,srun 的使用无关紧要,因为它在批处理脚本中用于启动并行作业。在案例 1 中你只有一项任务,所以
srun ./prog-1.sh >prog-1-stdout.txt
等同于:
./prog-1.sh >prog-1-stdout.txt
案例 2 不同,因为您有不止一项任务。在这种情况下,srun -l ./prog-2.sh >prog-2-stdout.txt
只计算一次,srun 将负责产生 10*10 个任务。 srun会将所有task的输出重定向到job的master节点,它会写入prog-2-stdout.txt
.
因此您可以确定在这种情况下不会破坏输出文件,因为它只被计算一次。