如何借助SLURM实现数组中每两个文件一组的并行循环
利用SLURM数组任务并行处理成对文件
需求背景
现有一批txt文件,原本通过循环每两个一组迭代处理,现在希望借助SLURM的$SLURM_ARRAY_TASK_ID变量,让每一组文件对应一个独立的并行任务,同时希望了解是否有无需数组的实现方式。
基于数组的可行方案
你的尝试思路是对的,这里可以优化自动计算任务范围,避免手动调整--array参数:
优化后的脚本示例
#!/bin/bash #SBATCH --job-name=pair_process # 加载文件到数组 declare -a files=( *.txt ) # 计算总组数(兼容奇数个文件的情况) total_pairs=$(( (${#files[@]} + 1) / 2 )) # 校验任务ID是否在有效范围内 if (( SLURM_ARRAY_TASK_ID > total_pairs )); then echo "任务ID超出有效范围,退出" exit 1 fi # 计算当前任务对应的文件索引 index1=$(( 2 * (SLURM_ARRAY_TASK_ID - 1) )) index2=$(( index1 + 1 )) # 执行任务,兼容奇数个文件的最后一个单独处理 if [[ -f "${files[index1]}" ]]; then if [[ -f "${files[index2]}" ]]; then echo "处理文件对:${files[index1]} ${files[index2]}" mycommand "${files[index1]}" "${files[index2]}" else echo "处理单个文件:${files[index1]}" # 若需处理单个文件,在此添加对应命令 # mycommand_single "${files[index1]}" fi fi
提交脚本时自动指定数组范围
先计算总组数,再提交任务,无需手动修改脚本内的--array参数:
# 计算总组数 num_tasks=$(( $(printf "%s\n" *.txt | wc -l) / 2 )) # 提交SLURM数组任务 sbatch --array=1-$num_tasks your_script.sh
无需数组的替代方法
方法1:用split生成分组列表
先将文件按每2个一组写入临时文件,再让每个SLURM任务对应一行:
# 生成每2个文件一行的分组列表 printf "%s\n" *.txt | xargs -n2 > file_pairs.txt # 计算分组数 num_pairs=$(wc -l < file_pairs.txt) # 提交数组任务 sbatch --array=1-$num_pairs << 'EOF' #!/bin/bash # 读取当前任务对应的文件对 pair=$(sed -n "${SLURM_ARRAY_TASK_ID}p" file_pairs.txt) echo "处理:$pair" mycommand $pair EOF
方法2:通过序号直接取文件
借助sed按行号取文件,无需数组存储:
#!/bin/bash #SBATCH --array=1-4 # 获取当前任务对应的两个文件 file1=$(printf "%s\n" *.txt | sed -n "$((2 * SLURM_ARRAY_TASK_ID - 1))p") file2=$(printf "%s\n" *.txt | sed -n "$((2 * SLURM_ARRAY_TASK_ID))p") # 执行任务 if [[ -n "$file1" ]]; then if [[ -n "$file2" ]]; then mycommand "$file1" "$file2" else # 处理单个文件的逻辑 # mycommand_single "$file1" fi fi
注意:推荐用
printf "%s\n" *.txt替代ls *.txt,避免文件名含特殊字符时出现格式问题。
内容的提问来源于stack exchange,提问作者pedro
相关产品推荐
相关产品推荐

