
本文探讨了在slurm集群中,通过sbatch提交一个bash脚本,该bash脚本进而调用python脚本,而python脚本内部再通过subprocess模块调用srun来启动大规模并行计算任务的工作流。研究表明,这种嵌套调用方式在作业启动阶段会引入微乎其微的(可忽略不计的)开销,但对实际hpc工作负载的运行时性能没有负面影响,只要python脚本仅在启动时执行一次srun调用。
在高性能计算(HPC)环境中,Slurm作业调度系统是管理和分配计算资源的关键工具。用户通常通过sbatch命令提交一个包含作业配置和执行指令的Bash脚本。本教程关注一种特定的工作流,其层级结构如下:
这种多层嵌套的调用方式为复杂的作业配置和动态参数生成提供了灵活性。
核心问题在于,将Python脚本作为中间层来调用srun,是否会引入显著的性能开销,从而影响整个HPC工作负载的效率。
结论是:这种方式引入的性能开销非常小,通常可以忽略不计,且不会影响大规模并行计算任务的运行时性能。
立即学习“Python免费学习笔记(深入)”;
具体分析如下:
为了更好地理解上述工作流,以下是一个简化的代码示例。
#!/bin/bash
#SBATCH --job-name=python_srun_example
#SBATCH --nodes=2 # 请求2个计算节点
#SBATCH --ntasks-per-node=1 # 每个节点1个任务(Python脚本)
#SBATCH --cpus-per-task=1 # 每个任务1个CPU核心
#SBATCH --time=00:10:00 # 作业最长运行时间10分钟
#SBATCH --output=slurm-%j.out # 标准输出文件
#SBATCH --error=slurm-%j.err # 标准错误文件
# 载入必要的模块,例如Python环境或MPI库
# module load python/3.9
# module load openmpi/4.1.4
echo "-----------------------------------------"
echo "Slurm Job ID: ${SLURM_JOB_ID}"
echo "Nodes allocated: ${SLURM_NNODES}"
echo "Tasks per node: ${SLURM_NTASKS_PER_NODE}"
echo "Starting Python script..."
# 调用Python脚本
python running.py
echo "Python script finished."
echo "-----------------------------------------"import subprocess
import sys
import os
def main():
print("Python script: Initializing and preparing to call srun...")
# 假设你的并行程序是 'my_parallel_app'
# 这个程序应该在Slurm环境的PATH中,或者提供完整路径
parallel_app = "my_parallel_app"
# srun 参数:通常srun会继承sbatch的环境变量,
# 但为了清晰或覆盖特定设置,可以显式指定部分参数。
# 注意:srun请求的资源不应超过sbatch脚本中已分配的资源。
# 在这个例子中,sbatch请求了2个节点,每个节点1个任务。
# srun将使用这些资源来启动my_parallel_app。
srun_command = [
"srun",
# "--ntasks-per-node=1", # 如果sbatch已指定,通常不需要重复
# "--nodes=2", # 如果sbatch已指定,通常不需要重复
parallel_app, # 你的并行应用程序
"input_file.dat", # 应用程序的参数1
"output_results.txt" # 应用程序的参数2
]
print(f"Python script: Executing srun command: {' '.join(srun_command)}")
try:
# check_call 会等待命令完成,如果返回非零状态码则抛出CalledProcessError
# 这是阻塞式调用,Python脚本会等待srun启动的并行程序执行完毕
subprocess.check_call(srun_command)
print("Python script: srun command executed successfully. Parallel application finished.")
except subprocess.CalledProcessError as e:
print(f"Python script: Error executing srun command. Return code: {e.returncode}", file=sys.stderr)
sys.exit(e.returncode) # 退出Python脚本,并传递srun的错误码
except FileNotFoundError:
print(f"Python script: Error: '{parallel_app}' or 'srun' command not found.", file=sys.stderr)
sys.exit(1)
except Exception as e:
print(f"Python script: An unexpected error occurred: {e}", file=sys.stderr)
sys.exit(1)
print("Python script: All tasks completed.")
if __name__ == "__main__":
main()my_parallel_app是一个占位符,代表你实际需要运行的大规模并行应用程序。它可能是一个使用MPI、OpenMP或其他并行库编写的C/C++/Fortran程序。例如,它可能是一个模拟程序、数据分析工具或机器学习训练任务。这个程序将由srun在Slurm分配的计算资源上并行执行。
在使用这种嵌套调用方式时,需要考虑以下几点以确保作业的稳定性和效率:
# myscript.sh 中 # source /path/to/your/venv/bin/activate # 或者 # conda activate your_env
在Slurm集群中,通过sbatch -> Bash脚本 -> Python脚本 -> srun -> HPC工作负载的嵌套调用方式,是一种灵活且功能强大的作业提交策略。尽管这种方法引入了Python解释器启动的微小开销,但该开销在作业启动阶段发生,对于大规模并行计算任务的整体运行时性能影响微乎其微,可以忽略不计。只要Python脚本主要充当启动器角色,并仅在启动时执行一次srun调用,用户就可以放心地利用Python的强大功能进行复杂的作业配置、环境管理和前处理任务,而无需担心对核心HPC工作负载的性能产生负面影响。
以上就是Slurm作业提交:Python脚本内嵌srun的性能影响分析的详细内容,更多请关注php中文网其它相关文章!
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号