我的任务是:
我目前的情况是:
我以以下形式编写了程序:
import io
from optparse import OptionParser
parser = OptionParser()
parser.add_option("-f", "--file",action="store", type="string", dest="filename")
parser.add_option("-a", "--input_a",type="int", dest="a")
parser.add_option("-b", "--input_b",type="int", dest="b")
parser.add_option("-c", "--input_c",type="int", dest="c")
(options, args) = parser.parse_args()
def F(a,b,c):
return((a+b, b+c))
Alice = options.input_a
Bob = options.input_b
Carol = options.input_c
with io.open("results_a_{0}_b_{1}_c_{2}.txt".format(Alice, Bob, Carol), "a") as f:
(x,y) = F(Alice, Bob, Carol)
f.write(u"first output = {0}, second output = {1}".format(x,y))
这使我可以运行一次程序,并将结果保存在一个文件中。
我想知道的是:
...
for a in 1 2 3; do
for b in 10 20 30; do
for c in 100 200 300; do
python toy_experiment.py -a $a -b $b -c $c &
done
done
done
wait
[我很警惕,这里可能还有很多其他地方我出了问题-我愿意使用optparse之外的其他方法将参数传递给程序,以其他方式保存结果等。-我的主要目标是找到可行的解决方案。]
答案 0 :(得分:0)
TL; DR
您应该研究如何在系统中使用文件锁定,并使用它来安全地访问单个输出文件。
您还应该使用作业数组提交脚本,并让数组中的每个作业运行一个实验。
这里发生了很多事情。
一个重要问题:计算F()通常需要多长时间?我假设您只是写了一个示例,但这是决定解决问题的最佳方法所必需的。
如果每个计算的时间间隔很短,则也许您可以运行几个批处理,在一个脚本中聚合几个计算:在本示例中,为3个批处理(对于a == 1,a == 2和a == 3) ,它们每个都会计算b和c的所有可能实验,并生成3个文件,这些文件必须在最后汇总。
如果时间跨度很长,那么创建数千个小文件的负担就不大了。然后将它们串联起来很容易。
另一件事:通过将所有作业同时在后台运行,您可能会使一台机器超载。我不知道您如何向SLURM请求资源,但是可以肯定的是,您将只使用一个节点。并过度使用它。如果那里还有其他用户,他们可能会生气。您必须将节点中运行的同时作业数控制为该节点中授予的处理器数。大概,使用srun开始计算会有所帮助。
另一种方法是为每个计算创建一个作业。您可以将它们封装在作业数组中。在这种情况下,每个作业只需要运行一个实验,而不必在后台开始等待任何事情。
最后,您要回答的主要问题是:这是将所有这些信息有效保存在磁盘中的最佳方法。
创建数千个文件是容易且可能的,但不是文件系统的最佳方法。也许您可以访问公共节点中的某些RAMdisk。在计算节点本地存储中写入一个小文件,然后将该文件复制到公用内存磁盘中,效率会大大提高。完成所有实验后,您可以轻松汇总结果。缺点是空间通常非常有限(我真的不知道您的数据的实际大小),并且它将是内存中的磁盘:万一断电,它可能会丢失。
使用单个文件是一种更好的方法,但是正如Dmitri Chubarov指出的那样,您必须使用文件锁定机制。否则,您可能会面临混合结果的风险。
最后,我认为最适合您的问题的方法是使用某种类似于数据库的解决方案。如果您有权访问支持事务的关系数据库,则只需创建带有所需字段的表,然后让您的代码连接并插入结果即可。最后提取它们会很容易。数据库可以是客户端/服务器(MySQL,PostgreSQL,Oracle ...),也可以是嵌入式(HSQLDB)。另一种选择是使用某种文件格式,例如NetCDF,它正是针对此类科学数据而设计的,并且对并行访问具有一定的支持。