我有一个产生数字的函数(神经网络模型)。我希望在带有Torque的标准集群上使用PBS测试python中的几个参数,方法和不同输入(意味着数百次运行)。
注意:我尝试过parallelpython,ipython等,并且从未完全满意,因为我想要更简单的东西。集群处于给定的配置中,我无法改变,这样集成python + qsub的解决方案肯定会对社区有益。
为简化起见,我有一个简单的功能,例如:
import myModule
def model(input, a= 1., N=100):
do_lots_number_crunching(input, a,N)
pylab.savefig('figure_' + input.name + '_' + str(a) + '_' + str(N) + '.png')
其中input
是表示输入的对象,input.name
是字符串,do_lots_number_crunching
可能持续数小时。
我的问题是:是否有正确的方法来转换像
这样的参数扫描之类的东西for a in pylab.linspace(0., 1., 100):
model(input, a)
进入“某事”,为每次调用model
函数启动PBS脚本?
#PBS -l ncpus=1
#PBS -l mem=i1000mb
#PBS -l cput=24:00:00
#PBS -V
cd /data/work/
python experiment_model.py
我在考虑一个包含PBS模板的函数,并从python脚本中调用它,但还不能解决它(装饰器?)。
答案 0 :(得分:4)
pbs_python [1]可以为此工作。如果您可以将experiment_model.py'a'作为参数
import pbs, os
server_name = pbs.pbs_default()
c = pbs.pbs_connect(server_name)
attopl = pbs.new_attropl(4)
attropl[0].name = pbs.ATTR_l
attropl[0].resource = 'ncpus'
attropl[0].value = '1'
attropl[1].name = pbs.ATTR_l
attropl[1].resource = 'mem'
attropl[1].value = 'i1000mb'
attropl[2].name = pbs.ATTR_l
attropl[2].resource = 'cput'
attropl[2].value = '24:00:00'
attrop1[3].name = pbs.ATTR_V
script='''
cd /data/work/
python experiment_model.py %f
'''
jobs = []
for a in pylab.linspace(0.,1.,100):
script_name = 'experiment_model.job' + str(a)
with open(script_name,'w') as scriptf:
scriptf.write(script % a)
job_id = pbs.pbs_submit(c, attropl, script_name, 'NULL', 'NULL')
jobs.append(job_id)
os.remove(script_name)
print jobs
[1]:https://oss.trac.surfsara.nl/pbs_python/wiki/TorqueUsage pbs_python
答案 1 :(得分:3)
您可以使用jug(我为类似的设置开发)轻松完成此操作。
您要写入文件(例如model.py
):
@TaskGenerator
def model(param1, param2):
res = complex_computation(param1, param2)
pyplot.coolgraph(res)
for param1 in np.linspace(0, 1.,100):
for param2 in xrange(2000):
model(param1, param2)
就是这样!
现在您可以在队列中启动“jug jobs”jug execute model.py
,这将自动并行化。会发生的是,每个作业都会循环,执行以下操作:
while not all_done():
for t in tasks in tasks_that_i_can_run():
if t.lock_for_me(): t.run()
(实际上比这更复杂,但你明白了。)
如果您愿意,它使用文件系统进行锁定(如果您在NFS系统上)或redis服务器。它还可以处理任务之间的依赖关系。
这不是你要求的,但我相信这是一个更清洁的架构,可以将它与作业排队系统分开。
答案 2 :(得分:2)
看起来我参加派对的时间有点晚了,但几年前我也遇到了如何将令人尴尬的并行问题映射到python中的问题,并编写了我自己的解决方案。我最近将它上传到github:https://github.com/plediii/pbs_util
要使用pbs_util编写程序,我首先要在包含
的工作目录中创建一个pbs_util.ini[PBSUTIL]
numnodes=1
numprocs=1
mem=i1000mb
walltime=24:00:00
然后像这样的python脚本
import pbs_util.pbs_map as ppm
import pylab
import myModule
class ModelWorker(ppm.Worker):
def __init__(self, input, N):
self.input = input
self.N = N
def __call__(self, a):
myModule.do_lots_number_crunching(self.input, a, self.N)
pylab.savefig('figure_' + self.input.name + '_' + str(a) + '_' + str(self.N) + '.png')
# You need "main" protection like this since pbs_map will import this file on the compute nodes
if __name__ == "__main__":
input, N = something, picklable
# Use list to force the iterator
list(ppm.pbs_map(ModelWorker, pylab.linspace(0., 1., 100),
startup_args=(input, N),
num_clients=100))
这样就可以了。
答案 3 :(得分:0)
我刚开始使用群集和EP应用程序。我的目标(我和图书馆一起工作)是要学到足够的知识,以帮助校园内的其他研究人员使用EP应用程序访问HPC ...尤其是STEM以外的研究人员。我还是很新,但认为这可能有助于这个问题指出在PBS脚本中使用GNU Parallel来启动具有不同参数的基本python脚本。在.pbs文件中,有两行要指出:
module load gnu-parallel # this is required on my environment
parallel -j 4 --env PBS_O_WORKDIR --sshloginfile $PBS_NODEFILE \
--workdir $NODE_LOCAL_DIR --transfer --return 'output.{#}' --clean \
`pwd`/simple.py '{#}' '{}' ::: $INPUT_DIR/input.*
# `-j 4` is the number of processors to use per node, will be cluster-specific
# {#} will substitute the process number into the string
# `pwd`/simple.py `{#}` `{}` this is the command that will be run multiple times
# ::: $INPUT_DIR/input.* all of the files in $INPUT_DIR/ that start with 'input.'
# will be substituted into the python call as the second(3rd) argument where the
# `{}` resides. These can be simple text files that you use in your 'simple.py'
# script to pass the parameter sets, filenames, etc.
作为EP超级计算的新手,即使我还没有理解“并行”的所有其他选项,这个命令允许我以不同的参数并行启动python脚本。如果您可以提前生成大量参数文件来并行化您的问题,那么这将很有效。例如,跨参数空间运行模拟。或使用相同的代码处理许多文件。