【发布时间】:2019-11-07 02:46:50
【问题描述】:
我有一个由 N 个步骤组成的模拟,按顺序运行。这些步骤中的每一个都会修改内存中的全局状态,直到作为结果的最后一步。在一个步骤运行后,可以将这个步骤刚刚计算的中间状态写入磁盘,并加载这样的中间状态,而不是从头开始。写入和加载中间状态的成本不可忽略。
我想在 Slurm 集群上运行多种模拟。每个变化都会改变一些步骤的参数。
示例
模拟步骤
S1 --> S2 --> S3 --> S4
变化
run1: S2.speed=2, S3.height=12
run2: S2.speed=2, S3.height=20
run3: S2.speed=2, S3.height=40
run4: S2.speed=5, S3.height=12
run5: S2.speed=5, S3.height=80
我想要做的是通过转储共享步骤的中间状态,让各种运行共享通用计算。这将形成一个步骤运行树:
S1
├─ S2 (speed=2)
│ ├─ S3 (height=12)
│ │ └─ S4
│ ├─ S3 (height=20)
│ │ └─ S4
│ └─ S3 (height=40)
│ └─ S4
└─ S2 (speed=5)
├─ S3 (height=12)
│ └─ S4
└─ S3 (height=80)
└─ S4
我知道我可以通过运行 5 个进程得到 5 次运行的结果:
run1: S1 --> S2 (speed=2) --> S3 (height=12) --> S4
run2: (dump of run1.S2) --> S3 (height=20) --> S4
run3: (dump of run1.S2) --> S3 (height=40) --> S4
run4: (dump of run1.S1) --> S2 (speed=5) --> S3 (height=12) --> S4
run5: (dump of run4.S2) --> S3 (height=80) --> S4
这将使用简单方法的 20 步计算减少到 13 步,使用 3 次转储和 4 次加载。
现在,我的问题是如何使用 Slurm 进行建模,以充分利用调度程序?
我能想到的一个解决方案是,每次运行都负责在中间状态转储之后提交依赖于它的运行的作业。 run1转储S1后会提交run4,然后转储S2后会提交run2和run3,run4转储S2后会提交run5。有了这个解决方案,在提交作业到 Slurm 时声明依赖关系有什么意义吗?
我可以看到的另一个解决方案是打破多个依赖作业中的长计算链。要提交的作业列表及其依赖关系基本上是我在上面绘制的树(除了 S3/S4 对将合并到同一个作业中)。这是要提交的 8 个作业而不是 5 个,但我可以从一开始就一次性提交它们,并且具有正确的依赖关系。但是,我不确定这种方法的优点是什么。如果 Slurm 从一开始就知道作业的完整列表及其依赖关系,他作为调度程序会做得更好吗?从用户的角度来看,提交所有作业并与依赖项链接(例如,取消所有依赖于根作业的作业)是否有一些优势?我知道我可以使用作业数组一次提交许多作业,但我没有看到一种方法来声明同一数组的作业之间的依赖关系。是可能的,甚至是可取的吗?
最后,还有其他我没有想到的方法吗?
编辑
我给出的例子当然简化了很多。真正的模拟将包含数百个步骤,大约有一千种变化可供尝试。所选解决方案的可扩展性很重要。
【问题讨论】:
标签: slurm