【问题标题】:How to model a tree of computations with Slurm?如何使用 Slurm 对计算树进行建模?
【发布时间】: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


    【解决方案1】:

    我能想到的一个解决方案是,每次运行都负责在中间状态转储之后提交依赖于它的运行的作业。有了这个解决方案,在提交作业到 Slurm 时声明依赖关系有什么意义吗?

    这是一种简单的工作流程通常采用的方法,其中涉及必须检查点并重新启动的长时间运行的作业。

    我可以看到的另一个解决方案是打破多个依赖作业中的长计算链。如果 Slurm 从一开始就知道作业的完整列表及其依赖关系,他作为调度程序会做得更好吗?

    没有。 Slurm 将忽略那些不符合开始条件的工作,因为它们的依赖工作尚未完成。

    从用户的角度来看,提交所有作业并与依赖项相关联(例如,取消所有依赖于根作业的作业)是否有一些优势?

    是的,但这有点用处。

    我知道我可以使用作业数组一次提交多个作业,但我没有看到一种方法来声明同一数组的作业之间的依赖关系。是可能的,甚至是可取的吗?

    不,您不能在同一数组的作业之间设置依赖关系。

    最后,还有其他我没有想到的方法吗?

    您可以使用workflow management system

    最简单的解决方案之一是Makeflow。它使用看起来像经典Makefiles 的文件来描述作业之间的依赖关系。然后,只需运行类似makeflow –T slurm makefile.mf

    另一个选项是Bosco。 Bosco 提供了更多的可能性,并且适合个人使用。它易于设置并且可以将作业提交到多个集群。

    最后,Fireworks 是一个非常强大的解决方案。它需要 MongoDB,更适合实验室使用,但它可以根据作业的输出实现非常复杂的作业提交/重新提交逻辑,并且可以巧妙地处理错误。例如,您可以实现一个工作流,其中使用给定参数的给定值提交作业,并让 Fireworks 基于输出文件监控收敛,并在收敛不满意的情况下取消并使用另一个值重新提交。

    【讨论】:

    • 我的理解是否正确,即使用工作流管理系统会排除使用我的第一个解决方案?也就是说,它假设我们事先知道所有的依赖关系,并且每个作业都有一个输入和一个输出?
    • 使用像 Makeflow 这样的简单解决方案,是的,但使用 Fireworks 没有;您可以根据先前作业的输出来实现决定依赖关系的规则,并且作业可以有多个输入和输出
    【解决方案2】:

    另一个可能的解决方案是使用管道工具。在生物信息学领域SnakeMake 变得非常流行。 SnakeMake 基于 GNU Make,但使用 Python 制作,因此得名 SnakeMake。为了让 SnakeMake 工作,您指定您想要的输出,SnakeMake 将推断它必须为此输出运行哪个 rules。 SnakeMake 的优点之一是它非常容易从个人笔记本电脑扩展到更大的计算机,甚至集群(例如 slurm 集群)。您的示例如下所示:

    rule all:
        input:
            ['S4_speed_2_height_12.out',
             'S4_speed_2_height_20.out',
             'S4_speed_2_height_40.out',
             'S4_speed_5_height_12.out',
             'S4_speed_5_height_80.out']
    
    rule S1:
        output:
            "S1.out"
        shell:
            "touch {output}"  # do your heavy computations here
    
    rule S2:
        input:
            "S1.out"
        output:
            "S2_speed_{speed}.out"
        shell:
            "touch {output}"
    
    rule S3:
        input:
            "S2_speed_{speed}.out"
        output:
            "S3_speed_{speed}_height_{height}.out"
        shell:
            "touch {output}"
    
    rule S4:
        input:
            "S3_speed_{speed}_height_{height}.out"
        output:
            "S4_speed_{speed}_height_{height}.out"
        shell:
            "touch {output}"
    

    然后我们可以让 snakemake 制作一张漂亮的图像,说明它将如何执行这些计算:

    Snakemake 会自动计算出哪些输出可以被不同的规则使用。

    在您的本地机器上运行它就像执行 snakemake 一样简单,将操作提交给 slurm 只需 snakemake --cluster "sbatch"。我给出的示例显然过于简单化,但 SnakeMake 是高度可定制的(每个规则的线程数、内存使用量等),并且具有基于 Python 的优势。需要花点时间弄清楚 SnakeMake 中的一切是如何工作的,但我绝对可以推荐它。

    【讨论】:

    • 感谢您的意见。如果我理解正确,SnakeMake 可以处理共享磁盘上的输入/输出文件,并根据修改日期检查文件是否是最新的。在我们的例子中,输出不是文件而是数据库中的条目,所以我认为它对我们不起作用。
    • 我不确定 SnakeMake 与数据库的配合情况如何,您可以随时尝试'flagging' 文件。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-05
    • 2018-01-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多