

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

# 在截止日期云中安排作业
<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) APIs。

有三种可用的调度配置：
+ **优先级， first-in-first-out**(`priorityFifo`)-首先安排优先级最高、最早提交的作业（默认）。
+ **优先级，平衡** (`priorityBalanced`)-在优先级最高的工作中平均分配员工。
+ **加权，平衡** (`weightedBalanced`)-使用加权公式来确定员工在不同工作中的分布情况。

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

### 优先级， first-in-first-out
<a name="jobs-scheduling-priority-fifo"></a>

优先级， first-in-first-out(`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>

创建任务后，Deadline Cloud 会根据与提交任务的队列关联的队列的能力来检查任务中每个步骤的主机要求。如果舰队符合主机要求，则该任务将进入该`READY`状态。

如果任务中的任何步骤具有与队列关联的队列无法满足的要求，则该步骤的状态将设置为`NOT_COMPATIBLE`。此外，作业中的其余步骤也将被取消。

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

以下作业模板的步骤指定了该步骤的主机要求：

```
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
```

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

```
{
    "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-scaling"></a>

将任务分配给兼容的服务托管队列时，队列会自动缩放。车队中的工作人员数量会根据可供车队运行的任务数量而变化。

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

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

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

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

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

作业附件由提交者创建，您将其用作 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!
```