IBM LSF调度器结合GNU Parallel运行无输出问题排查求助
我尝试将bash脚本提交至IBM Load Sharing Facility(LSF)高性能计算(HPC)作业调度器,同时使用GNU Parallel加速执行,通过samtools工具对大量分散存储的.bam文件按固定区域进行子集提取,以缩短总运行时间。
单独用GNU Parallel在本地运行、仅通过LSF调度器运行(不并行)都能正常生成输出,但两者结合时无输出文件生成。目前只能使用bash,无法采用Nextflow或Snakemake等工作流工具。
作业脚本如下:
### /some/fixed/directory/myscript.sh ### #!/usr/bin/env bash #BSUB -J my_job_name #BSUB -q hpc_queue #BSUB -n 16 #BSUB -R "rusage[mem=8GB] span[hosts=1]" #BSUB -o logs/out.%J.log #BSUB -e logs/err.%J.log basedir="/some/fixed/directory" # absolute paths to a large number of .bam files # none of them in the same directory, so no wildcards input_bam_files="${basedir}/input_bam_files.txt" # used across all input files ref_genome_file="${basedir}/ref_genome.fa" regions_file="${basedir}/required_chr_start_end.bed" # fixed version 1.16 on HPC module load samtools mkdir -p "${basedir}/output" extract_regions_from_bam() { input_bam_file="$1" output_fn=$(basename "$input_bam_file") output_bam_file="${basedir}/output/${output_fn}" echo "Start: ${input_bam_file} -> ${output_bam_file}" samtools view --with-header --reference "$ref_genome_file" --regions-file "$regions_file" "$input_bam_file" | samtools sort -T $basedir/ -O bam -o "$output_bam_file" samtools index "$output_bam_file" echo "End: ${input_bam_file} -> ${output_bam_file}" } export -f extract_regions_from_bam cat "$input_bam_files" | parallel -j 8 --joblog "${basedir}/extract_regions_from_bam.log" extract_regions_from_bam {}
提交命令:bsub < /some/fixed/directory/myscript.sh
这种组合方式完全可行,问题大概率出在环境变量传递、资源配置或GNU Parallel的执行模式上,以下是具体修复步骤:
1. 确保GNU Parallel在LSF作业环境中可用
LSF作业的环境变量可能与登录节点不同,需显式加载Parallel模块或指定绝对路径:
# 若HPC采用模块管理,加载Parallel module load gnu-parallel # 或先通过`which parallel`获取绝对路径,再直接调用 # parallel_path=$(which parallel) # cat "$input_bam_files" | $parallel_path -j 8 --joblog "${basedir}/extract_regions_from_bam.log" extract_regions_from_bam {}
2. 对齐资源分配与并行数
你申请了-n 16个CPU核心,但当前Parallel仅用-j 8,且samtools sort默认会占用多个线程,容易导致资源冲突。建议调整并行数并为samtools sort指定线程数:
# 修改samtools sort,指定4线程 samtools view --with-header --reference "$ref_genome_file" --regions-file "$regions_file" "$input_bam_file" | samtools sort -@ 4 -T $basedir/ -O bam -o "$output_bam_file" # 调整Parallel并行数为4,确保总线程数(4×4)不超过申请的16 cat "$input_bam_files" | parallel -j 4 --joblog "${basedir}/extract_regions_from_bam.log" extract_regions_from_bam {}
同时检查rusage[mem=8GB]的定义:若为整个作业的内存配额,需确保并行任务的总内存消耗不超过限制,必要时调小并行数或修改rusage参数(如rusage[mem=2GB])。
3. 修复环境变量传递问题
LSF中export -f导出的函数可能无法被Parallel的子进程正确识别,可通过两种方式解决:
- 方式1:将函数写入临时脚本
# 生成包含函数的临时脚本 cat > "${basedir}/extract_func.sh" << 'EOF' extract_regions_from_bam() { input_bam_file="$1" output_fn=$(basename "$input_bam_file") output_bam_file="${basedir}/output/${output_fn}" echo "Start: ${input_bam_file} -> ${output_bam_file}" samtools view --with-header --reference "$ref_genome_file" --regions-file "$regions_file" "$input_bam_file" | samtools sort -T $basedir/ -O bam -o "$output_bam_file" samtools index "$output_bam_file" echo "End: ${input_bam_file} -> ${output_bam_file}" } EOF # Parallel调用时先加载脚本 cat "$input_bam_files" | parallel -j 8 --joblog "${basedir}/extract_regions_from_bam.log" 'source '"${basedir}/extract_func.sh"' && extract_regions_from_bam {}'
- 方式2:用Parallel的
--env _传递所有环境变量
cat "$input_bam_files" | parallel -j 8 --env _ --joblog "${basedir}/extract_regions_from_bam.log" extract_regions_from_bam {}
--env _会将当前shell的所有环境变量(包括导出的函数、模块加载的路径)传递给Parallel的子进程。
4. 检查日志定位错误
优先查看以下日志文件:
logs/out.%J.log:确认Parallel是否启动,以及任务的Start/End输出logs/err.%J.log:查找Parallel或samtools的报错(如命令不存在、权限不足、文件路径错误)extract_regions_from_bam.log:查看Parallel的任务调度记录,确认任务是否执行、是否失败
5. 验证输出目录权限
确保LSF作业运行用户对${basedir}/output有读写权限,若为共享目录,需检查ACL设置。
6. 测试最小用例
先在input_bam_files.txt中放入1-2个bam文件路径,提交作业测试,缩小问题范围。若最小用例可行,再逐步扩大任务量。
内容的提问来源于stack exchange,提问作者Ankit

