我有一段python代码在一台机器上运行,multiprocessing.Pool
用于许多独立的工作。我想知道是否有可能在SGE网格上使其更加平行,例如,网格的每个节点为这些独立的作业运行多个线程。
最初,我有:
# function def
# some_function(param1, param2, param3, process_index)
func = functools.partial(some_function, file_list, param1, param2, param3)
pool = multiprocessing.Pool(processes=some_integer)
ret_list = pool.map(func, range(processes))
pool.close()
它似乎在本地计算机上工作正常,但如果按原样提交到SGE网格,它确实会异常退出而不会出现错误消息。提交命令可能如下所示:
qsub -V -b yes -cwd -l h_vmem=10G -N jobname -o grid_job.log -j yes "python worker.py"
理想情况下,我正在寻找本地版本的python代码的最小更改,以便它可以在SGE网格上运行,因为很难在网格上安装新工具或更改任何网格配置而不影响其他用户。
至少,我理解可以只重写代码,以便每个作业(file_list
中的文件)的处理由一个qsub命令处理。但我想知道最佳做法是什么。
答案 0 :(得分:4)
我要做的是将Python脚本读取文件列表和进程数作为命令行参数。这样就可以更容易地调用它。我会写一个Bash脚本,它接收文件列表作为参数,并根据你想要做的事情提交所有作业。这样,您可以执行两个级别的并行化:在多个节点(qsub)和每个节点的多个进程(python多进程)。要以正确的方式执行,您需要告诉qsub每个作业所需的SLOT数量。这是通过在并行环境中提交并指定SLOT编号(-pe ENV_NAME NBSLOTS
)来完成的:
#!/bin/bash
NB_PROCESS_PER_JOB=2
NB_FILE_PER_JOB=3
CPT=0
BUF=""
NUMJOB=1
for i in "$@"; do
BUF="$BUF '$i'"
((CPT++))
if ((CPT == NB_FILE_PER_JOB)); then
echo qsub -pe multithread $CPT -V -b yes -cwd -l h_vmem=10G -N jobname$NUMJOB -o grid_job.log -j yes "python worker.py $NB_PROCESS_PER_JOB $BUF"
BUF=""
CPT=0
((NUMJOB++))
fi
done
if [[ "$BUF" != "" ]]; then
echo qsub -pe multithread $CPT -V -b yes -cwd -l h_vmem=10G -N jobname$NUMJOB -o grid_job.log -j yes "python worker.py $NB_PROCESS_PER_JOB $BUF"
fi
Python脚本如下所示:
import sys
nb_processes = int(sys.argv[1])
file_list = sys.argv[2:]
pool = multiprocessing.Pool(processes=nb_processes)
ret_list = pool.map(some_function, file_list)
pool.close()
如果你的SGE集群没有任何并行环境,我建议你不要并行化Python脚本(删除-pe ENV_NAME NBSLOTS
参数,不要在Python脚本中使用池,或者只生成一个进程)。一个简单的SGE作业不应该是多线程的。如果一个简单的作业是多线程的,它会使用未预留的资源,并可能减慢其他用户的工作。