HPC 系列文章(9):指定作业参数

parameter

上一节中我们介绍了最简单的作业提交,我们将脚本编辑好之后交由Slurm调度,然后该脚本会运行在合适的节点上,并得到输出结果。在单台计算机上运行时,我们会觉得一切都很自然,就像是写几行代码然后编译运行得到结果一样。不过当你有一个集群时,就有一些区别了。假设我们有一个20个计算节点的集群,假设是如下配置:

1
2
3
4
5
6
7
8
9
10
11
12
################################################
# Nodes Configurations #
################################################
NodeName=node[01-10] Sockets=2 CoresPerSocket=32 ThreadsPerCore=1 Gres=gpu:tesla:no_consume:2 RealMemory=65535 TmpDisk=100000 Weight=6 Feature=video
NodeName=node[11-20] CPUs=4 RealMemory=8192 TmpDisk=14190
#
################################################
# Partition Configurations #
################################################
PartitionName=node-all Nodes=node[01-20] State=UP Default=YES MaxTime=60
PartitionName=performance MaxTime=UNLIMITED Nodes=node[01-10] State=UP
PartitionName=common MaxTime=UNLIMITED Nodes=node[11-20] State=UP

一共有20个节点,我将他们分成了三个队列:高性能、普通、二者混合。

从上面可以看到同一个节点是允许同时出现在多个分区中的,分区只是逻辑上的一种组合。

指定参数

既然我们有那么多节点,我们如何把作业提交到我们想要的某些或者某个节点上呢?我们能否指定作业的优先级、运行时长和各种运行策略呢?这就要结合上一节讲到的节点/队列配置和接下来我们要讲的作业参数的指定。

通过命令行参数

假设我们的某个作业需要3个节点同时计算,并且每个节点的内存不低于8G,并且希望运行在高性能的节点上。那么我们可以这样写:

1
sbatch --nodes=3 --mem=8192 --partiton=performance myjob.sh

我们来看一个更复杂的例子:

1
sbatch --nodes=5 --mem=8192 --partion=node-all --nodelist=node01,node02,node03,node11,node20 --cpus-per-task=4 myjob.sh

上面的命令翻译一下就是,需要5个节点,每个需要4核处理器,8G内存,指定运行在node01,node02,node03,node11,node20这五个节点上运行。

我们可以指定更多更详细的参数,包括处理器、内存、通用资源(GPU/IB网络/共享存储等)、License、优先级、预约资源等等,除此之外我们还可以指定开始时间、运行时长、作业名、输出文件等等。更多的选项可以参考文档:sbatch进行了解。

通过脚本注释指定参数

在命令行中指定参数很简单方便,不过不方便重复运行。Slurm还提供了另一种作业参数指定方式,将参数以注释的形式写到脚本中,Slurm会自动解析这些参数。

parameter

常见误区

曾有人问我:我有4台8核处理器的服务器,为什么我提交一个需要16核的任务的时候,作业永远不会运行?

其实这是很多人对调度系统的一个错误认识,我们必须清楚计算单元并不会自动融合,调度系统也并不会自动拆分作业,这是学习调度系统之前应该了解的要点。我们可以把集群具体的计算资源认为是用户无感知的,也就是说用户无需关心具体跑在某个服务器上,但并不是所有的计算资源可以看作是一台机器。

大家小学应该都学过乌鸦喝水的故事,这里我举一个例子,我们把集群中单台服务器看作是一个瓶子,作业看作是一颗一颗不规则的石头,集群则是一大堆瓶子,我们可以得到以下简单的结论:

  • 石头尺寸是大小不一的(每个作业对硬件资源的需求不一样,需要16核的作业就是大石头,只需要1核的就是小石头)
  • 一块石头显然没有办法同时放在两个瓶子里(一个作业不能同时部分运行在两台服务器上)
  • 我们希望瓶子盛放尽可能多的石头(调度系统的作用是将作业放到能放下的服务器上,并且尽可能的多放)
  • 当石头的尺寸超过任意的瓶子所能容纳的体积时,我们无法将石头放入瓶子内(16核需求的作业无法放到任意一台8核的服务器上)
  • 大石头不会自动变成小石头,除非我们主动敲碎它(调度系统不会为你自动将一个作业拆成两个小作业)。

回到上面那个问题,我们该如何处理呢?答案是要么你将作业需求变得更小,改成两个并行作业,每个只需要8核处理器。要么就往系统中添加一台16核以上配置的服务器。至于具体怎么做这不是本节要讨论的,后面再做介绍。

总结

这一节我们介绍了如何为作业指定参数,我们可以通过命令行参数或者将参数编写在作业脚本中两种不同的方式来指定作业参数。后面我们将进一步介绍一些高级的用法。

坚持原创技术分享,您的支持将鼓励我继续创作!