首页 > 解决方案 > 如何使用 slurm 并行化这个 for 循环?

问题描述

我有大量不同的 bam 文件要处理,这是我的 sbatch 文件:

#! /bin/bash
#
#SBATCH --job-name=test
#SBATCH --ntasks=1
#SBATCH --cpus-per-task=2
#SBATCH --mem-per-cpu=4000
#SBATCH --output=output.%j.out
#SBATCH --error=output.%j.err

srun picard.sh

我的意思是使用threads=2运行

还有我的picard.sh文件:

#!/bin/bash

module load picard-tools/2.4.1-gcb01
module load java/1.8.0_45-fasrc01

picard=./picard-tools/2.4.1-gcb01/picard.jar
outdir=./bam2fastq/fastq
tmpdir=./tmp/

for bam in $(find . -type f -name \*.bam);
do
    echo "processing ${bam}"
    s=${bam##*/}
    r1=${s%.bam}_R1.fastq
    r2=${s%.bam}_R2.fastq
    echo $r1
    echo $r2
    java -Djava.io.tmpdir=${tmpdir} -Xmx8G -jar ${picard} SamToFastq \
        I=${bam} \
        FASTQ=${outdir}/${r1} \
        SECOND_END_FASTQ=${outdir}/${r2}
done

虽然这将使用 thread=2 处理每个 bam,但它将一个接一个。我怎么能运行这个并行化的,比如 6 个 bam 文件同时使用 thread=2 处理?

标签: slurm

解决方案


您能否尝试将您的 for 循环放入一个函数中,将您的输入文件放入一个数组中并启动作业数组。就像是:

#!/bin/bash
#
#SBATCH --job-name=test
#SBATCH --ntasks=1
#SBATCH --cpus-per-task=2
#SBATCH --mem-per-cpu=4000
#SBATCH --output=array_%A_%a.out
#SBATCH --error=array_%A_%a.err
#SBATCH --array=0-5


#Loading modules and variables
module load picard-tools/2.4.1-gcb01
module load java/1.8.0_45-fasrc01

picard=./picard-tools/2.4.1-gcb01/picard.jar
outdir=./bam2fastq/fastq
tmpdir=./tmp/

#Array of my inputs
INPUT=( $(find . -type f -name \*.bam) )

#my function
func () {
    bam=$1
    echo "processing ${bam}"
    s=${bam##*/}
    r1=${s%.bam}_R1.fastq
    r2=${s%.bam}_R2.fastq
    echo $r1
    echo $r2
    java -Djava.io.tmpdir=${tmpdir} -Xmx8G -jar ${picard} SamToFastq \
        I=${bam} \
        FASTQ=${outdir}/${r1} \
        SECOND_END_FASTQ=${outdir}/${r2}
}

#launch job arrays
func "${INPUT[$SLURM_ARRAY_TASK_ID]}"

注意 1:您还可以限制并行运行的进程数,以防您获得更多进程:

#SBATCH --array=0-1000%100

在此示例中,您将从此作业数组中同时运行的任务数限制为 100。

注2:这个问题与这篇文章高度相关

注 3:作业数组的 Slurm 文档


推荐阅读