HPC集群入门指南

先决条件

本教程页面需要先完成以下前置教程:

目标

在本教程结束时,您将完成Cromwell与HPC集群的对接配置。我们将以SGE为例进行说明,但这些步骤同样适用于LSF等其他调度系统。

让我们开始吧!

告知 Cromwell 后端类型

首先在backend部分定义您的新后端配置。目前,我们将您的后端命名为SGE,但您可以使用任何喜欢的名称。

backend {
  providers {
    SGE {
      actor-factory = "cromwell.backend.impl.sfs.config.ConfigBackendLifecycleActorFactory"
      config {
        # to be filled in
      }
    }
  }
}

上面的actor-factory告诉cromwell,你将使用config部分来告诉cromwell如何提交作业、中止作业等。

您可能还想通过设置以下配置值,将默认后端更改为您的新后端:

backend.default = SGE

为您的HPC任务指定运行时属性

在后端配置部分,您可以定义HPC任务将支持的不同运行时属性。此处配置的任何运行时属性都将从WDL任务中读取,然后传递到用于向HPC集群提交作业的命令行中。

所有运行时属性必须在一个多行代码块中定义。该代码块的语法与定义WDL任务的输入相同。

backend.providers.SGE.config {
  runtime-attributes = """
  Int cpu = 1
  Float? memory_gb
  String? sge_queue
  String? sge_project
  """
}

在上面的示例中,我们定义了四个不同的WDL变量:cpumemory_gbsge_queuesge_project。下面您将找到关于cpumemory的更多信息,以及添加自定义运行时属性(如sge_queuesge_project)的功能。

CPU

当你声明一个名为cpu的运行时属性时,它必须是一个Int类型。这个整数值会被验证确保始终>= 1

backend.providers.SGE.config {
  runtime-attributes = """
  Int cpu = 1
  # ...
  """
}

内存

运行工作流时,任务中的内存运行时属性将指定内存的单位。例如,此作业指定运行时仅需要512兆字节的内存。

task hello {
  command { echo hello }
  runtime { memory: "512 MB" }
}

然而,在向HPC集群提交作业时,您可能希望以GB为单位进行指定。

要指定提交命令应使用的内存单位,请将单位附加到内存运行时属性。例如:

backend.providers.SGE.config {
  runtime-attributes = """
  Float? memory_gb
  # ...
  """
}

现在,无论任务中使用何种内存单位,该值都会在传递给您的提交命令之前转换为千兆字节。

自定义属性

您还可以声明WDL任务可能使用的其他运行时属性。例如,假设您希望允许WDL在任务中指定一个sge队列,如下所示:

task hello {
  command { echo hello }
  runtime { sqe_queue: "short" }
}

您可以在配置文件中声明运行时属性,只需将其他自定义值添加到runtime-attributes部分:

backend.providers.SGE.config {
  runtime-attributes = """
  String? sge_queue
  # ...
  """
}

在这种情况下,我们声明sge_queue是可选的。这允许我们重用其他可能没有设置sge_queue的流程作者编写的WDL。

或者,您也可以为声明的运行时属性设置默认值。

backend.providers.SGE.config {
  runtime-attributes = """
  String sge_queue = "short"
  # ...
  """
}
基于运行时属性的调用缓存

HPC后端调用缓存的规则如下: * docker: 调用缓存时会被考虑。 * 内存选项:调用缓存时不会被考虑。 * CPU选项:调用缓存时不会被考虑。 * 自定义属性:默认情况下调用缓存时不会被考虑。

虽然默认情况下调用缓存时不会考虑自定义属性,但你可以在runtime-attributes-for-caching部分覆盖此设置。例如:

backend.providers.SGE.config {
  runtime-attributes = """
  String sge_queue = "short"
  String singularity_image
  # ...
  """
  runtime-attributes-for-caching {
    sge_queue: false
    singularity_image: true
  }
}
  • 注意:只有自定义属性可以通过这种方式修改。内存、CPU和docker将始终保持其默认的缓存考虑行为。
  • Note: Unlike memory, cpu and docker attributes which inherit validation and hash-lookup behavior, any custom attributes will be simple primitive comparisons.
    • 例如,docker属性会通过查询docker仓库中的哈希值进行缓存,而自定义的singularity属性则采用原始字符串匹配方式。

Cromwell如何启动HPC作业

当Cromwell运行任务时,它会使用声明的运行时属性填充作业模板。这个具体模板会根据您HPC集群的要求而变化。例如,假设您通常使用以下命令向SGE提交作业:

qsub -terse -V -b y -N my_job_name \
  -wd /path/to/working_directory \
  -o /path/to/stdout.qsub \
  -e /path/to/stderr.qsub \
  -pe smp 1 -l mem_free=0.5g -q short \
  /usr/bin/env bash myScript.bash

对于这个特定的SGE集群,上述配置设置了工作目录、标准输出和错误输出路径,将CPU数量设为1,内存设为0.5GB,并在短队列中运行。

使用我们的运行时属性将其转换为模板需要像定义WDL任务command那样定义submit

backend.providers.SGE.config {
  submit = """
  qsub \
  -terse \
  -V \
  -b y \
  -N ${job_name} \
  -wd ${cwd} \
  -o ${out}.qsub \
  -e ${err}.qsub \
  -pe smp ${cpu} \
  ${"-l mem_free=" + memory_gb + "g"} \
  ${"-q " + sge_queue} \
  ${"-P " + sge_project} \
  /usr/bin/env bash ${script}
  """
}

当任务提交完成后,Cromwell需要获取作业ID,以便在必要时中止该作业。提交后,该作业ID应写入标准输出(stdout),Cromwell随后会读取这个ID。由于作业ID可能被其他文本包围,需要使用自定义正则表达式来捕获实际的作业ID。由于上述提交使用了-terse参数,作业ID将是标准输出的全部内容,但应该全由数字组成:

backend.providers.SGE.config {
  job-id-regex = "(\\d+)"
}

Cromwell如何中止HPC作业

当中止HPC作业时,Cromwell将运行在kill键下配置的命令,并传入WDL变量job_id

backend.providers.SGE.config {
  kill = "qdel ${job_id}"
}

Cromwell如何检查HPC作业是否存活

每当Cromwell重启时,它会通过在一个名为rc的文件中搜索返回码来检查作业是否已完成。如果该文件不可用,在这种情况下Cromwell会运行额外检查以确保作业仍在运行。您可以通过以下方式配置用于此检查的命令:

backend.providers.SGE.config {
  check-alive = "qstat -j ${job_id}"
}

其他后端设置

在某些系统中,管理员可能会限制用户同时运行的HPC作业数量。要配置此限制,您可以使用concurrent-job-limit值来限制作业数量。

backend.providers.SGE.config {
  concurrent-job-limit = 100
}

整合配置部分

通过以上章节,我们可以将它们全部整合在一起,创建一个完全可用的HPC后端。

backend {
  default = SGE

  providers {
    SGE {
      actor-factory = "cromwell.backend.impl.sfs.config.ConfigBackendLifecycleActorFactory"
      config {
        concurrent-job-limit = 100

        runtime-attributes = """
        Int cpu = 1
        Float? memory_gb
        String? sge_queue
        String? sge_project
        """

        submit = """
        qsub \
        -terse \
        -V \
        -b y \
        -N ${job_name} \
        -wd ${cwd} \
        -o ${out} \
        -e ${err} \
        -pe smp ${cpu} \
        ${"-l mem_free=" + memory_gb + "g"} \
        ${"-q " + sge_queue} \
        ${"-P " + sge_project} \
        /usr/bin/env bash ${script}
        """

        job-id-regex = "(\\d+)"

        kill = "qdel ${job_id}"
        check-alive = "qstat -j ${job_id}"
      }
    }
  }
}

在配置文件中使用Cromwell运行此设置后,现在可以将作业提交到SGE!

后续步骤

你可能会对接下来要学习的以下教程感兴趣: