

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# 在 Deadline 云中安排作业
<a name="build-jobs-scheduling"></a>

创建任务后，De AWS adline Cloud 会安排任务在与队列关联的一个或多个队列上进行处理。处理特定任务的队列是根据调度配置、为队列配置的功能以及特定步骤的主机要求来选择的。

以下各节详细介绍了调度任务的过程。

## 调度配置
<a name="jobs-scheduling-configuration"></a>

您可以通过在队列上设置计划配置来配置 Deadline Cloud 如何调度队列中的作业。调度配置控制如何在任务之间分配工作人员。

您可以使用 Deadline Cloud 控制台或调用[CreateQueue](https://docs.aws.amazon.com/deadline-cloud/latest/APIReference/API_CreateQueue.html)或 [ UpdateQueue ](https://docs.aws.amazon.com/deadline-cloud/latest/APIReference/API_UpdateQueue.html) API 来设置日程安排配置。

有三种可用的调度配置：
+ **优先级，先入先出 ** (`priorityFifo`) — 安排优先级最高、最早提交的作业（默认）。
+ **优先级，平衡 ** (`priorityBalanced`) — 按最高优先级将工作人员平均分配到各个工作中。
+ **加权，平衡 ** (`weightedBalanced`)-使用加权公式来确定工作人员在各个工作中的分布情况。

在所有调度配置中，在做出新的调度决策之前，正在进行的任务会一直运行到完成。如果您在任务运行时更改计划配置，则更改仅在接下来分配工作人员时适用。正在运行的任务不会中断或重新分配。

### 优先，先入先出
<a name="jobs-scheduling-priority-fifo"></a>

优先级，先入先出 (`priorityFifo`) 是新队列的默认调度配置。Deadline Cloud 首先将工作人员分配到优先级最高的工作。当多个作业共享相同的优先级时，最旧（最早提交）的作业将首先接收所有可用工作人员。

当您想要严格排序任务时，请使用优先级 FIFO。当作业应按提交顺序逐一完成时，这种配置是适当的，例如顺序流水线阶段或批处理，其中每个作业必须在下一个任务开始之前完成。

此配置没有其他参数。

### 优先，平衡
<a name="jobs-scheduling-priority-balanced"></a>

Priority，balanced (`priorityBalanced`) 以最高优先级将工作人员平均分配给所有任务。当只有一项任务处于最高优先级时，Deadline Cloud 会将所有工作人员分配给该工作。当多个任务共享最高优先级时，工作人员将在它们之间平均分配。如果工作人员不能平均分配，则额外的工作人员将分配到优先级最高的工作中。

当多个艺术家或用户以相同的优先级提交作业且每个用户都需要即时反馈时，请使用优先级平衡器。此配置可确保任何单个任务都不会垄断所有可用的工作人员，因此所有用户在提交后不久就会被分配到工作人员。

如果一项工作的剩余任务少于其工人所占比例，则剩余的工人将重新分配给具有相同优先级的其他工作。如果优先级最高的所有工作都得到充分分配，剩余的工人就会级联到下一个最高优先级的工作岗位。

此配置具有以下参数：

`renderingTaskBuffer`  
控制员工的粘性。只有当渲染任务的差异超过该`renderingTaskBuffer`值时，工作器才以相同优先级从其当前作业切换到另一个任务。更高的价值可以延长员工当前工作的时间，从而减少上下文切换。默认值为 `1`。

### 加权、平衡
<a name="jobs-scheduling-weighted-balanced"></a>

加权，平衡 (`weightedBalanced`) 使用公式计算每项任务的权重。Deadline Cloud 首先为员工分配权重最高的工作。如果多个任务的权重相同，则将工人分布在这些工作中。

如果您需要精细控制工作人员在优先级、错误率和提交时间各不相同的任务中的分配方式，请使用加权平衡。此配置适用于复杂的渲染农场环境，在这些环境中，您想要调整任务优先级、作业年限、错误处理和工作人员粘性之间的平衡。

每项任务的权重计算方法如下：

```
weight = (job.Priority * priorityWeight) +
         (job.Errors * errorWeight) +
         ((currentTimeInSeconds - job.SubmissionTime) * submissionTimeWeight) +
         ((job.RenderingTasks - renderingTaskBuffer) * renderingTaskWeight)
```

仅当工作人员当前正在处理任务时，才会应用该`renderingTaskBuffer`组件。通常设置为负值，这样分配了工作人员的任务的权重就会降低，从而使其他任务排在队列的前面。`renderingTaskWeight`通常也`errorWeight`为负数，因此出现错误的任务会被取消优先级。您可以对最低和最高优先级的任务使用调度替代。

此配置具有以下参数：

`priorityWeight`  
适用于工作优先级的权重。正值表示优先级更高的作业会先安排。默认值为 `100.0`。范围：`0`至`10000`。

`errorWeight`  
应用于任务错误数的权重。负值表示首先安排没有错误的作业。默认值为 `-10.0`。范围：`-10000`至`10000`。

`submissionTimeWeight`  
应用于作业提交时间的权重（以秒为单位）。正值表示先前提交的任务将首先排定。默认值为 `3.0`。范围：`0`至`10000`。

`renderingTaskWeight`  
应用于当前为作业呈现的任务数量的权重。负值表示接下来将安排工人较少的工作。默认值为 `-100.0`。范围：`-10000`至`10000`。

`renderingTaskBuffer`  
在渲染任务权重生效之前的渲染任务数。正值可以让员工继续从事当前的工作。默认值为 `1`。范围：`0`至`1000`。

`maxPriorityOverride`  
可选。如果设置为`alwaysScheduleFirst`，则无论使用何种加权公式，最高优先级 (100) 的任务始终排在其他任务之前。当多个任务具有最高优先级时，使用标准加权公式打破平局。当不存在替代时，最高优先级的任务将使用标准加权公式，不进行特殊处理。

`minPriorityOverride`  
可选。如果设置为`alwaysScheduleLast`，则无论加权公式如何，最低优先级 (0) 的任务始终排在其他任务之后。当多个任务具有最低优先级时，使用标准加权公式打破平局。当不存在替代时，最低优先级的任务使用标准加权公式，不进行特殊处理。

## 确定舰队兼容性
<a name="jobs-scheduling-compatibility"></a>

队列和队列将路由任务的工作分开。队列组织任务并控制谁可以提交和查看任务。舰队和房东要求选择由哪些工作人员运行每个步骤。

要将特定工作人员专门用于某些工作，请为这些工作人员创建单独的队列，而不是单独的队列。例如，对于具有特定硬件的计算机或为敏感内容预留的计算机，使用单独的队列。一个队列可以与多个队列相关联，每个步骤的主机要求会选择一个兼容的队列。如果你即将到来 10 号截止日期，那么车队和房东的要求将取代工作人员群体。有关完整的概念图，请参阅[从截止日期 10 迁移到 AWS 截止日期云](migrate-from-deadline-10.md)。

创建任务后，Deadline Cloud 会根据与提交任务的队列相关的队列的能力检查任务中每个步骤的主机要求。如果舰队符合宿主要求，则将工作交给该`READY`州。

如果任务中的任何步骤具有与队列关联的队列无法满足的要求，则该步骤的状态将设置为`NOT_COMPATIBLE`。此外，任务中的其余步骤也被取消。如果您稍后将兼容队列与队列相关联，则现有`NOT_COMPATIBLE`任务不会自动重启——要运行它们，请重新排队。有关更多信息，请参阅 [在截止日期云中修改作业](build-jobs-modifying.md)。

舰队的能力是在舰队级别上设置的。即使车队中的工作人员符合工作要求，如果其机队不符合工作要求，也不会从工作中为其分配任务。

**重要**  
舰队级`workerCapabilities`申报是调度合同。调度程序专门根据舰队级别的能力评估步骤兼容性——它不检查个别工作人员。如果某一步骤`hostRequirements`超过了机队中申报的最低值`workerCapabilities`，即使车队中的某些工人能够满足要求，该机队也会被评估为不兼容。

以下作业模板包含一个为该步骤指定主机要求的步骤：

```
name: Sample Job With Host Requirements
specificationVersion: jobtemplate-2023-09
steps:
- name: Step 1
  script:
    actions:
      onRun:
        args:
        - '1'
        command: /usr/bin/sleep
  hostRequirements:
    amounts:
    # Capabilities starting with "amount." are amount capabilities. If they start with "amount.worker.",
    # they are defined by the OpenJD specification. Other names are free for custom usage.
    - name: amount.worker.vcpu
      min: 4
      max: 8
    attributes:
    - name: attr.worker.os.family
      anyOf:
      - linux
```

提交者通过 “**主机要求” 选项卡设置相同的要求**。选择 “在满足以下要求**的工作主机上**运行”，无需编辑模板即可设置操作系统、CPU 架构和硬件范围。

![选择了自定义要求的主机要求选项卡，显示操作系统、CPU 架构和硬件范围。](https://docs.aws.amazon.com/zh_cn/deadline-cloud/latest/developerguide/images/bundle-gui-submit-host-requirements.png)


可以将此任务安排到具有以下功能的舰队中：

```
{
    "vCpuCount": {"min": 4, "max": 8},
    "memoryMiB": {"min": 1024},
    "osFamily": "linux",
    "cpuArchitectureType": "x86_64"
}
```

无法将此任务安排到具有以下任何功能的舰队：

```
{
    "vCpuCount": {"min": 4},
    "memoryMiB": {"min": 1024},
    "osFamily": "linux",
    "cpuArchitectureType": "x86_64"
}
    The vCpuCount has no maximum, so it exceeds the maximum vCPU host requirement.
    
{
    "vCpuCount": {"max": 8},
    "memoryMiB": {"min": 1024},
    "osFamily": "linux",
    "cpuArchitectureType": "x86_64"
}
    The vCpuCount has no minimum, so it doesn't satisfy the minimum vCPU host requirement.

{
    "vCpuCount": {"min": 4, "max": 8},
    "memoryMiB": {"min": 1024},
    "osFamily": "windows",
    "cpuArchitectureType": "x86_64"
}    
    The osFamily doesn't match.
```

### 舰队设计最佳实践
<a name="jobs-scheduling-fleet-design"></a>

由于调度程序会评估机群级别的兼容性，因此请设计您的客户管理的队列，使申报的队列`workerCapabilities`代表队列中每个工作人员的最低硬件特性：
+ 根据保证的最低硬件特性（例如 GPU 数量、VRAM 或 CPU 数量）将工作人员分成多个队列，而不是使用一个范围广泛的异构队列。
+ 即使工作人员没有相同的硬件，也要确保车队中的每位工作人员达到或超过申报的最低限额。
+ 将多个队列与单个队列关联起来，以便调度器根据每个步骤选择兼容的队列。`hostRequirements`

例如，如果您的工作人员拥有 1 个 GPU（24 GiB VRAM）和拥有 4 个 GPU（96 GiB VRAM）的工作人员，请创建两个单独的队列：一个声明至少 1 个 GPU 和 24 GiB GPU 内存，另一个声明至少 4 个 GPU 和 96 GiB GPU 内存。然后将两个舰队关联到同一个队列。需要 4 个 GPU 的步骤会自动路由到高 GPU 队列。

有关创建客户管理队列的更多信息，请参阅[创建由客户管理的车队](create-a-cmf.md)。

### 自定义功能
<a name="jobs-scheduling-custom-capabilities"></a>

除了内置的工作器功能（vCPU、内存、GPU、操作系统和 CPU 架构）外，您还可以在队列上定义自定义数量和自定义属性以表达额外的调度限制：
+ **自定义金额 **-数值，例如可用磁盘空间或专用硬件计数器。
+ **自定义属性 **-字符串值，例如已安装的软件、求解器版本或站点标签。例如，您可以使用诸如路由`["vray-6", "arnold-7"]`需要特定软件`attr.sw.solvers`的任务之类的值进行定义。

在舰队层面，只有在保证该队列中的所有工作人员都存在软件或硬件组合的情况下，才能在自定义功能中声明这些组合。

Fleet-level 自定义功能有以下限制：
+ 每个舰队最多 15 个自定义金额
+ 每个舰队最多 15 个自定义属性

采用`amount.worker.*`和格式的名称`attr.worker.*`，由服务保留用于内置功能。为您的自定义功能使用其他前缀。

以下示例将需要特定求解器的步骤路由到提供该求解器的队列。舰队在自定义属性中声明其所有工作人员上安装的解算器。此舰队配置是[CreateFleet](https://docs.aws.amazon.com/deadline-cloud/latest/APIReference/API_CreateFleet.html)请求的一部分：

```
"workerCapabilities": {
    "vCpuCount": {"min": 4},
    "memoryMiB": {"min": 16384},
    "osFamily": "linux",
    "cpuArchitectureType": "x86_64",
    "customAttributes": [
        {
            "name": "attr.sw.solvers",
            "values": ["vray-6", "arnold-7"]
        }
    ]
}
```

需要其中一个声明值的步骤会在作业模板中`hostRequirements`说明该要求：

```
steps:
- name: RenderWithVray
  hostRequirements:
    attributes:
    - name: attr.sw.solvers
      anyOf:
      - vray-6
  script:
    actions:
      onRun:
        command: '{{Task.File.Render}}'
```

该要求使未申报`vray-6`的`RenderWithVray`舰队无法离开。相反的情况并不成立：没有`attr.sw.solvers`要求的步骤仍然与该机队兼容，可以对其进行调度。

**注意**  
自定义属性和主机要求路由工作。它们不是访问控制。主机要求由提交任务的人在作业模板中设置，声明属性的队列仍会接受未提及该属性的步骤。要为敏感内容预留工作人员，请让他们加入自己的队列，并仅将该队列与经批准的队列关联。有关更多信息，请参阅[访问控制和工作人员选择](#jobs-scheduling-access-control)和[使用农场、队列和队列隔离工作负载](farm-structure.md)。

有关在创建队列时配置自定义功能的更多信息，请参阅[创建由客户管理的车队](create-a-cmf.md)。

### GPU 内存报告
<a name="jobs-scheduling-gpu-memory"></a>

当您为需要特定每个 GPU VRAM 阈值 GPU-intensive 的工作负载配置队列时，请了解工作代理如何报告 GPU 内存。

Deadline Cloud 工作器代理报告的是工作器上所有 G * PU * 的最低 GPU 内存`amount.worker.gpu.memory`，而不是总和。这种行为可确保将需要特定 GPU VRAM 数量的任务路由到每个 GPU 都满足该要求的工作人员。

例如，如果工作器有两个 GPU，分别具有 24 GiB 和 48 GiB 的 VRAM，则工作器代理将 24 GiB 报告为 GPU 内存值。

在队列级别，将每个 GPU VRAM `acceleratorTotalMemoryMiB` 的最小值设置为队列中所有工作人员保证拥有的最低值。

### Per-worker 能力
<a name="jobs-scheduling-worker-capabilities"></a>

当您需要在不影响日程安排决策的情况下跟踪个别工作人员的运行状态时，请使用每位工作人员的功能。例如，您可以标记工作人员进行维护，跟踪软件发布状态或记录运行状况检查指标。

您可以使用 `UpdateWorker` API 操作为个别工作人员设置功能。 Per-worker 能力*不*用作调度合同。调度器仅根据舰队`workerCapabilities`级声明评估兼容性。

`GetWorker`和`ListWorkers`操作不会返回已设置的工作器功能`UpdateWorker`。

有关更多信息，请参阅 Deadl * ine Cloud API 参考[UpdateWorker](https://docs.aws.amazon.com/deadline-cloud/latest/APIReference/API_UpdateWorker.html)中的内容*。

### 访问控制和工作人员选择
<a name="jobs-scheduling-access-control"></a>

Deadline Cloud 将谁可以使用资源与作业运行地点区分开来。IAM 政策以及 AWS IAM Identity Center 用户和群组成员资格控制谁可以查看、提交和管理农场、队列或队列。队列-舰队关联和主机要求控制哪些工作人员运行每项作业。

舰队的群组成员资格允许人们在监视器中查看和管理该舰队。成员资格不会将工作分配给舰队或将工作拒之门外。要将工作引导到或离开车队，请使用队列-舰队关联。

宿主要求是工作模板的一部分，因此无论谁提交任务，都会选择这些要求。它们将工作分配给有能力的车队，但它们不是访问控制。队列与舰队的关联是执行点：无论该步骤的主机要求如何，该服务仅向与任务队列相关的舰队安排一个步骤。为防止受限队列进行未经授权的工作，请仅将该队列与受限队列相关联，并控制谁可以提交这些队列。有关队列和共享工作人员的队列之间的安全边界的更多信息，请参阅。[使用农场、队列和队列隔离工作负载](farm-structure.md)

## 实例集扩展
<a name="jobs-scheduling-scaling"></a>

将任务分配给兼容的服务管理队列时，该队列将自动扩展。队列中的工作人员数量根据可供舰队运行的任务数量而变化。

将任务分配给客户管理的队列时，工作人员可能已经存在，也可以使用基于事件的自动缩放来创建。有关更多信息，请参阅 A * mazon EC2 自动扩展用户指南[中的](https://docs.aws.amazon.com/autoscaling/ec2/userguide/automating-ec2-auto-scaling-with-eventbridge.html)用于 EventBridge处理自动扩展事件*。

## 会话
<a name="jobs-scheduling-sessions"></a>

作业中的任务分为一个或多个会话。工作人员运行会话来设置环境、运行任务，然后拆除环境。每个会话都由工作人员必须采取的一项或多项操作组成。

当工作人员完成分区操作时，可以向该工作人员发送其他会话操作。工作人员重复使用会话中的现有环境和工作附件，以更高效地完成任务。

在服务管理的队列工作人员上，会话结束后会话目录将被删除，但在会话之间保留其他目录。此行为允许您为可在多个会话中重复使用的数据实施缓存策略。要在会话之间缓存数据，请将其存储在运行作业的用户的主目录下。例如，conda 包缓存在作业用户的主目录下，分别位`C:\Users\job-user\.conda-pkgs`于 on workers 和 w Windows orkers `/home/job-user/.conda-pkgs` 上Linux。在工作人员关闭之前，这些数据一直可用。

作业附件由提交者创建，您将其用作 Deadline Cloud CLI 任务包的一部分。您也可以使用该`create-job` AWS CLI 命令的`--attachments`选项创建作业附件。环境在两个地方定义：附加到特定队列的队列环境以及作业模板中定义的作业和步骤环境。

有四种会话操作类型：
+ `syncInputJobAttachments`— 将输入作业附件下载给工作人员。
+ `envEnter`— 为环境执行`onEnter`操作。
+ `taskRun`— 执行任务的`onRun`操作。
+ `envExit`— 为环境执行`onExit`操作。

以下作业模板具有步骤环境。它有一个`onEnter`用于设置步骤环境的`onRun`定义，一个定义要运行的任务的`onExit`定义，以及一个用于拆分步骤环境的定义。为此任务创建的会话将包括一个`envEnter`操作、一个或多个`taskRun`操作，然后是一个`envExit`操作。

```
name: Sample Job with Maya Environment
specificationVersion: jobtemplate-2023-09
steps:
- name: Maya Step
  stepEnvironments:
  - name: Maya
    description: Runs Maya in the background.
    script:
      embeddedFiles:
      - name: initData
        filename: init-data.yaml
        type: TEXT
        data: |
          scene_file: MyAwesomeSceneFile
          renderer: arnold
          camera: persp
      actions:
        onEnter:
          command: MayaAdaptor
          args:
          - daemon
          - start
          - --init-data
          - file://{{Env.File.initData}}
        onExit:
          command: MayaAdaptor
          args:
          - daemon
          - stop
  parameterSpace:
    taskParameterDefinitions:
    - name: Frame
      range: 1-5
      type: INT
  script:
    embeddedFiles:
    - name: runData
      filename: run-data.yaml
      type: TEXT
      data: |
        frame: {{Task.Param.Frame}}
    actions:
      onRun:
        command: MayaAdaptor
        args:
        - daemon
        - run
        - --run-data
        - file://{{ Task.File.runData }}
```

### 会话操作流水线
<a name="jobs-session-pipelining"></a>

会话操作流水线允许调度器将多个会话操作预先分配给工作人员。然后，工作人员可以按顺序运行这些操作，从而减少或消除任务之间的空闲时间。

要创建初始任务，调度器会创建一个包含一项任务的会话，工作人员完成任务，然后调度器分析任务持续时间以确定将来的分配。

为了使调度程序有效，有任务持续时间规则。对于一分钟以下的任务，调度器使用 2 的次方增长模式。例如，对于一个 1 秒钟的任务，调度器会分配 2 个新任务，然后分配 4 个，再分配 8 个。对于超过一分钟的任务，调度器仅分配一项新任务，流水线仍处于禁用状态。

要计算管道大小，调度器执行以下操作：
+ 使用已完成任务的平均任务持续时间
+ 旨在让工人忙一分钟
+ 仅考虑同一会话中的任务
+ 不在工作人员之间共享工时数据

通过会话操作流水线，工作人员可以立即开始新任务，并且调度器请求之间没有等待时间。它还提高了工作人员效率，并为长时间运行的流程提供了更好的任务分配。

此外，如果有新的更高优先级的作业可用，则该工作人员将在其当前会话结束之前完成其先前分配的所有工作，并分配来自更高优先级任务的新会话。

## 步骤依赖关系
<a name="jobs-scheduling-dependencies"></a>

Deadline Cloud 支持定义步骤之间的依赖关系，这样一个步骤会等到另一个步骤完成后再开始。您可以为一个步骤定义多个依赖关系。只有在所有依赖项都完成后，才会对具有依赖关系的步骤进行调度。

如果作业模板定义了循环依赖关系，则作业将被拒绝并将作业状态设置为`CREATE_FAILED`。

以下作业模板通过两个步骤创建作业。`StepB`取决于`StepA`。`StepB`仅在成功`StepA`完成后运行。

创建任务后，`StepA`处于`READY`状态并`StepB`处于`PENDING`状态。`StepA`完成后，`StepB`移至`READY`状态。如果`StepA`失败或取消，则`StepA``StepB`移至`CANCELED`状态。

您可以对多个步骤设置依赖关系。例如，如果同时`StepC`依赖`StepA`和`StepB`，`StepC`则要等到其他两个步骤完成后才会启动。

步骤依赖关系有以下限制：
+ **每个步骤的依赖关系 **-一个步骤最多可以依赖于 128 个其他步骤。
+ **每步消费者 ** — 单个步骤最多可以有 32 个其他步骤。

```
name: Step-Step Dependency Test
specificationVersion: 'jobtemplate-2023-09'
steps:
- name: A
  script:
    actions:
      onRun:
        command: bash
        args: ['{{ Task.File.run }}']
    embeddedFiles:
      - name: run
        type: TEXT
        data: |
          #!/bin/env bash

          set -euo pipefail

          sleep 1
          echo Task A Done!
- name: B
  dependencies:
  - dependsOn: A # This means Step B depends on Step A
  script:
    actions:
      onRun:
        command: bash
        args: ['{{ Task.File.run }}']
    embeddedFiles:
      - name: run
        type: TEXT
        data: |
          #!/bin/env bash

          set -euo pipefail

          sleep 1
          echo Task B Done!
```