

# 适用于 GPU 工作负载的 Amazon ECS 任务定义
<a name="ecs-gpu"></a>

当您使用支持 GPU 的容器实例创建集群时，Amazon ECS 支持使用 GPU 的工作负载。使用 p2、p3、p5、g3、g4 和 g5 实例类型的基于 GPU 的 Amazon EC2 容器实例提供对 NVIDIA GPU 的访问权限。有关更多信息，请参阅《Amazon EC2 示例类型指南》中的 [Linux 加速型计算实例](https://docs.aws.amazon.com/ec2/latest/instancetypes/ac.html)**。

Amazon ECS 提供了经 GPU 优化的 AMI，后者附带了预配置的 NVIDIA 内核驱动程序和 Docker GPU 运行时。有关更多信息，请参阅 [经 Amazon ECS 优化的 Linux AMI](ecs-optimized_AMI.md)。

您可以在任务定义中指定多个 GPU，以便在容器级别考虑任务放置。Amazon ECS 将安排支持 GPU 的可用容器实例，并将物理 GPU 固定到正确的容器以获得最佳性能。

支持以下基于 GPU 的 Amazon EC2 实例类型。有关更多信息，请参阅 [Amazon EC2 P2 实例](https://aws.amazon.com/ec2/instance-types/p2/)、[Amazon EC2 P3 实例](https://aws.amazon.com/ec2/instance-types/p3/)、[Amazon EC2 P4d 实例](https://aws.amazon.com/ec2/instance-types/p4/)、[Amazon EC2 P5 实例](https://aws.amazon.com/ec2/instance-types/p5/)、[Amazon EC2 G3 实例](https://aws.amazon.com/ec2/instance-types/g3/)、[Amazon EC2 G4 实例](https://aws.amazon.com/ec2/instance-types/g4/)、[Amazon EC2 G5 实例](https://aws.amazon.com/ec2/instance-types/g5/)、[Amazon EC2 G6 实例](https://aws.amazon.com/ec2/instance-types/g6/)和[Amazon EC2 G6e 实例](https://aws.amazon.com/ec2/instance-types/g6e/)。


|  实例类型  |  GPU  |  GPU 内存（GiB）  |  vCPU  |  内存（GiB）  | 
| --- | --- | --- | --- | --- | 
|  p3.2xlarge  |  1  |  16  |  8  |  61  | 
|  p3.8xlarge  |  4  |  64  |  32  |  244  | 
|  p3.16xlarge  |  8  |  128  |  64  |  488  | 
|  p3dn.24xlarge  |  8  |  256  |  96  |  768  | 
|  p4d.24xlarge  | 8 | 320 | 96 | 1152 | 
| p5.48xlarge | 8 | 640 | 192 | 2048 | 
|  g3s.xlarge  |  1  |  8  |  4  |  30.5  | 
|  g3.4xlarge  |  1  |  8  |  16  |  122  | 
|  g3.8xlarge  |  2  |  16  |  32  |  244  | 
|  g3.16xlarge  |  4  |  32  |  64  |  488  | 
|  g4dn.xlarge  |  1  |  16  |  4  |  16  | 
|  g4dn.2xlarge  |  1  |  16  |  8  |  32  | 
|  g4dn.4xlarge  |  1  |  16  |  16  |  64  | 
|  g4dn.8xlarge  |  1  |  16  |  32  |  128  | 
|  g4dn.12xlarge  |  4  |  64  |  48  |  192  | 
|  g4dn.16xlarge  |  1  |  16  |  64  |  256  | 
|  g5.xlarge  |  1  |  24  |  4  |  16  | 
|  g5.2xlarge  |  1  |  24  |  8  |  32  | 
|  g5.4xlarge  |  1  |  24  |  16  |  64  | 
|  g5.8xlarge  |  1  |  24  |  32  |  128  | 
|  g5.16xlarge  |  1  |  24  |  64  |  256  | 
|  g5.12xlarge  |  4  |  96  |  48  |  192  | 
|  g5.24xlarge  |  4  |  96  |  96  |  384  | 
|  g5.48xlarge  |  8  |  192  |  192  |  768  | 
| g6.xlarge | 1 | 24 | 4 | 16 | 
| g6.2xlarge | 1 | 24 | 8 | 32 | 
| g6.4xlarge | 1 | 24 | 16 | 64 | 
| g6.8xlarge | 1 | 24 | 32 | 128 | 
| g6.16.xlarge | 1 | 24 | 64 | 256 | 
| g6.12xlarge | 4 | 96 | 48 | 192 | 
| g6.24xlarge | 4 | 96 | 96 | 384 | 
| g6.48xlarge | 8 | 192 | 192 | 768 | 
| g6.metal | 8 | 192 | 192 | 768 | 
| gr6.4xlarge | 1 | 24 | 16 | 128 | 
| g6e.xlarge | 1 | 48 | 4 | 32 | 
| g6e.2xlarge | 1 | 48 | 8 | 64 | 
| g6e.4xlarge | 1 | 48 | 16 | 128 | 
| g6e.8xlarge | 1 | 48 | 32 | 256 | 
| g6e16.xlarge | 1 | 48 | 64 | 512 | 
| g6e12.xlarge | 4 | 192 | 48 | 384 | 
| g6e24.xlarge | 4 | 192 | 96 | 768 | 
| g6e48.xlarge | 8 | 384 | 192 | 1536 | 
| gr6.8xlarge | 1 | 24 | 32 | 256 | 

您可以通过查询 AWS Systems Manager Parameter Store API 来检索经 Amazon EKS 优化的 AMI 的亚马逊机器映像（AMI）ID。使用此参数，您无需手动查找经 Amazon ECS 优化的 AMI ID。有关 Systems Manager Parameter Store API 的更多信息，请参阅 [GetParameter](https://docs.aws.amazon.com/systems-manager/latest/APIReference/API_GetParameter.html)。您使用的用户必须具有 `ssm:GetParameter` IAM 权限才能检索经 Amazon ECS 优化的 AMI 元数据。

```
aws ssm get-parameters --names /aws/service/ecs/optimized-ami/amazon-linux-2/gpu/recommended --region us-east-1
```

# 将 GPU 与 Amazon ECS 托管实例结合使用
<a name="managed-instances-gpu"></a>

Amazon ECS 托管实例通过以下 Amazon EC2 实例类型对机器学习、高性能计算和视频处理等工作负载支持 GPU 加速计算。有关 Amazon ECS 托管实例支持的实例类型的更多信息，请参阅[Amazon ECS 托管实例实例类型](managed-instances-instance-types.md)。

下面是 Amazon ECS 托管实例上支持的部分基于 GPU 的实例类型：
+ `g4dn`：由 NVIDIA T4 GPUs 提供支持，适用于机器学习推理、计算机视觉和图形密集型应用程序。
+ `g5`：由 NVIDIA A10G GPUs 提供支持，为图形密集型应用程序和机器学习工作负载提供更高性能。
+ `p3`：由 NVIDIA V100 GPUs 提供支持，专为高性能计算和深度学习训练而设计。
+ `p4d`：由 NVIDIA A100 GPUs 提供支持，为机器学习训练和高性能计算提供最高性能。

当您将支持 GPU 的实例类型与 Amazon ECS 托管实例一起使用时，NVIDIA 驱动程序和 CUDA 工具包已预先安装在实例上，从而更轻松地运行 GPU 加速的工作负载。

## 选择支持 GPU 的实例
<a name="managed-instances-gpu-instance-selection"></a>

要为您的 Amazon ECS 托管实例工作负载选择选择 GPU 的实例类型，请使用容量提供程序的启动模板中的 `instanceRequirements` 对象。以下代码段展示了可用于选择支持 GPU 的实例的属性。

```
{
  "instanceRequirements": {
    "acceleratorTypes": "gpu",
    "acceleratorCount": 1,
    "acceleratorManufacturers": ["nvidia"]
  }
}
```

以下代码段展示了可用于在启动模板中指定支持 GPU 的实例类型的属性。

```
{
  "instanceRequirements": {
    "allowedInstanceTypes": ["g4dn.xlarge", "p4de.24xlarge"]
  }
}
```

## 支持 GPU 的容器映像
<a name="managed-instances-gpu-container-images"></a>

要在容器中使用 GPU，您需要使用包含必要 GPU 库和工具的容器映像。NVIDIA 提供了一些预构建的容器映像，您可以将其用作 GPU 工作负载的基础，包括：
+ `nvidia:cuda`：包含用于 GPU 计算的 CUDA 工具包的基础映像。
+ `tensorflow/tensorflow:latest-gpu`：支持 GPU 的 TensorFlow。
+ `pytorch/pytorch:latest-cuda`：支持 GPU 的 PyTorch。

有关涉及使用 GPU 的 Amazon ECS 托管实例的 Amazon ECS 任务定义示例，请参阅[在 Amazon ECS 任务定义中指定 GPU 数](ecs-gpu-specifying.md)。

## 注意事项
<a name="gpu-considerations"></a>

**注意**  
已弃用对 g2 实例系列类型的支持。  
Amazon ECS 经 GPU 优化的 AMI 的 `20230912` 版本之前的版本仅支持 p2 实例系列类型。如果您需要继续使用 p2 实例，请参阅 [如果您需要 P2 实例该怎么办](#p2-instance)。  
这两种实例系列类型上的 NVIDIA/CUDA 驱动程序的就地更新将导致 GPU 工作负载出现潜在故障。

开始在 Amazon ECS 上使用 GPU 之前，我们建议您考虑以下事项。
+ 您的集群可以包含 GPU 和非 GPU 容器实例的组合。
+ 您可以在外部实例上运行 GPU 工作负载。当向集群注册外部实例时，请确保安装脚本中包含 `--enable-gpu` 标记。有关更多信息，请参阅 [将外部实例注册到 Amazon ECS 集群](ecs-anywhere-registration.md)。
+ 您必须在代理配置文件中将 `ECS_ENABLE_GPU_SUPPORT` 设置为 `true`。有关更多信息，请参阅 [Amazon ECS 容器代理配置](ecs-agent-config.md)。
+ 在运行任务或创建服务时，您可以在配置任务放置约束时使用实例类型属性，以确定要在其上启动任务的容器实例。通过这样做，您可以更有效地使用您的资源。有关更多信息，请参阅 [Amazon ECS 如何将任务放置在容器实例上](task-placement.md)。

  以下示例在您的默认集群中的 `g4dn.xlarge` 容器实例上启动一个任务。

  ```
  aws ecs run-task --cluster default --task-definition ecs-gpu-task-def \
       --placement-constraints type=memberOf,expression="attribute:ecs.instance-type ==  g4dn.xlarge" --region us-east-2
  ```
+ 对于在容器定义中指定了 GPU 资源要求的每个容器，Amazon ECS 将容器运行时设置为 NVIDIA 容器运行时。
+ NVIDIA 容器运行时需要在容器中设置一些环境变量才能工作。有关这些环境变量的列表，请参阅[使用 Docker 的专用配置](https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/latest/docker-specialized.html?highlight=environment%20variable)。Amazon ECS 设置 `NVIDIA_VISIBLE_DEVICES` 环境变量值设置为 Amazon ECS 分配给容器的 GPU 设备 ID 列表。对于其他必需的环境变量，Amazon ECS 不会对其进行设置。因此，请确保容器映像对其进行设置，或者在容器定义中对其进行设置。
+ `20230929` 版本和更高版本的 Amazon ECS 经 GPU 优化的 AMI 支持 p5 实例类型系列。
+ `20230913` 版本和更高版本的 Amazon ECS 经 GPU 优化的 AMI 支持 g4 实例类型系列。有关更多信息，请参阅 [经 Amazon ECS 优化的 Linux AMI](ecs-optimized_AMI.md)。它在 Amazon ECS 控制台的“创建集群”工作流中不受支持。要使用这些实例类型，您必须使用 Amazon EC2 控制台、AWS CLI 或 API 并手动将实例注册到您的集群。
+ p4d.24xlarge 实例类型仅适用于 CUDA 11 或更高版本。
+ Amazon ECS 经 GPU 优化的 AMI 启用了 IPv6，这会导致使用 `yum` 时出现问题。可以通过配置 `yum` 将 IPv4 与以下命令结合使用。

  ```
  echo "ip_resolve=4" >> /etc/yum.conf
  ```
+  当您构建不使用 NVIDIA/CUDA 基础映像的容器映像时，必须设置 `NVIDIA_DRIVER_CAPABILITIES` 容器运行时变量设置为以下值之一：
  + `utility,compute`
  + `all`

  有关如何设置变量的信息，请参阅 NVIDIA 网站上的[控制 NVIDIA 容器运行时](https://sarus.readthedocs.io/en/stable/user/custom-cuda-images.html#controlling-the-nvidia-container-runtime)
+ Windows 容器不支持 GPU。

# 启动适用于 Amazon ECS 的 GPU 容器实例
<a name="gpu-launch"></a>

要在 Amazon EC2 上的 Amazon ECS 上使用 GPU 实例，您需要创建启动模板、用户数据文件，然后启动实例。

然后，您可以运行使用为 GPU 配置的任务定义的任务。

## 使用启动模板
<a name="gpu-launch-template"></a>

您可以创建启动模板。
+ 创建将经 Amazon ECS 优化的 GPU AMI ID 用于 AMI 的启动模板。有关如何创建启动模板的信息，请参阅《Amazon EC2 用户指南》中的[使用您定义的参数创建新启动模板](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/create-launch-template.html#create-launch-template-define-parameters)**。

  将上一步中的 AMI ID 用于**亚马逊机器映像**。有关如何使用 Systems Manager 参数指定 AMI ID 的信息，请参阅《Amazon EC2 用户指南》中的[在启动模板中指定 Systems Manager 参数](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/create-launch-template.html#use-an-ssm-parameter-instead-of-an-ami-id)**。

  将以下各项添加到启动模板中的**用户数据**中。将 *cluster-name* 替换为您集群的名称。

  ```
  #!/bin/bash
  echo ECS_CLUSTER=cluster-name >> /etc/ecs/ecs.config;
  echo ECS_ENABLE_GPU_SUPPORT=true >> /etc/ecs/ecs.config
  ```

## 使用 AWS CLI
<a name="gpu-launch-cli"></a>

您可以使用 AWS CLI 启动容器实例。

1. 创建名为 `userdata.toml` 的文件。此文件会用于实例用户数据。将 *cluster-name* 替换为您集群的名称。

   ```
   #!/bin/bash
   echo ECS_CLUSTER=cluster-name >> /etc/ecs/ecs.config;
   echo ECS_ENABLE_GPU_SUPPORT=true >> /etc/ecs/ecs.config
   ```

1. 运行以下命令以获取 GPU AMI ID。您将在以下步骤中使用此 ID。

   ```
   aws ssm get-parameters --names /aws/service/ecs/optimized-ami/amazon-linux-2/gpu/recommended --region us-east-1
   ```

1. 运行以下命令来启动 GPU 实例。请记得替换以下参数：
   + 用您的实例将在其中启动的私有或公有子网的 ID 替换*子网*。
   + 将 *gpu\$1ami* 替换为上一步中的 AMI ID。
   + 将 *t3.large* 替换为您要使用的实例类型。
   + 将 *region* 替换为区域代码。

   ```
   aws ec2 run-instances --key-name ecs-gpu-example \
      --subnet-id subnet \
      --image-id gpu_ami \
      --instance-type t3.large \
      --region region \
      --tag-specifications 'ResourceType=instance,Tags=[{Key=GPU,Value=example}]' \
      --user-data file://userdata.toml \
      --iam-instance-profile Name=ecsInstanceRole
   ```

1. 运行以下命令，以验证容器实例是否注册到集群。在运行此命令时，请记得替换以下参数：
   + 将 *cluster* 替换为您的集群名称。
   + 将 *region* 替换为区域代码。

   ```
   aws ecs list-container-instances --cluster cluster-name --region region
   ```

# 在 Amazon ECS 任务定义中指定 GPU 数
<a name="ecs-gpu-specifying"></a>

要在容器实例和 Docker GPU 运行时上使用 GPU，请确保在任务定义中指定容器所需的 GPU 数量。由于已放置支持 GPU 的容器，Amazon ECS 容器代理会将所需数量的物理 GPU 固定到相应的容器中。为某个任务中的所有容器预留的 GPU 的数量不能超过该任务在其上启动的容器实例的可用 GPU 的数量。有关更多信息，请参阅 [使用控制台创建 Amazon ECS 任务定义](create-task-definition.md)。

**重要**  
如果任务定义中未指定 GPU 要求，则任务将使用原定设置 Docker 运行时。

下面显示了任务定义中的 GPU 要求的 JSON 格式：

```
{
  "containerDefinitions": [
     {
        ...
        "resourceRequirements" : [
            {
               "type" : "GPU", 
               "value" : "2"
            }
        ],
     },
...
}
```

以下示例演示了指定 GPU 要求的 Docker 容器的语法。此容器使用两个 GPU，运行 `nvidia-smi` 实用程序，然后退出。

```
{
  "containerDefinitions": [
    {
      "memory": 80,
      "essential": true,
      "name": "gpu",
      "image": "nvidia/cuda:11.0.3-base",
      "resourceRequirements": [
         {
           "type":"GPU",
           "value": "2"
         }
      ],
      "command": [
        "sh",
        "-c",
        "nvidia-smi"
      ],
      "cpu": 100
    }
  ],
  "family": "example-ecs-gpu"
}
```

以下示例任务定义展示了一个打印可用 GPU 数量的 TensorFlow 容器。该任务在 Amazon ECS 托管实例上运行，需要一个 GPU，并使用 `g4dn.xlarge` 实例。

```
{
  "family": "tensorflow-gpu",
  "networkMode": "awsvpc",
  "executionRoleArn": "arn:aws:iam::account-id:role/ecsTaskExecutionRole",
  "containerDefinitions": [
    {
      "name": "tensorflow",
      "image": "tensorflow/tensorflow:latest-gpu",
      "essential": true,
      "command": [
        "python",
        "-c",
        "import tensorflow as tf; print('Num GPUs Available: ', len(tf.config.list_physical_devices('GPU')))"
      ],
      "resourceRequirements": [
        {
          "type": "GPU",
          "value": "1"
        }
      ],
      "logConfiguration": {
        "logDriver": "awslogs",
        "options": {
          "awslogs-group": "/ecs/tensorflow-gpu",
          "awslogs-region": "region",
          "awslogs-stream-prefix": "ecs"
        }
      }
    }
  ],
  "requiresCompatibilities": [
    "MANAGED_INSTANCES"
  ],
  "cpu": "4096",
  "memory": "8192",
}
```

## 共享 GPU
<a name="share-gpu"></a>

当想要共享 GPU 时，需要进行以下配置。

1. 从任务定义中移除 GPU 资源要求，以便 Amazon ECS 不会预留任何应共享的 GPU。

1. 当想要共享 GPU 时，请将以下用户数据添加到您的实例。这将使 nvidia 成为容器实例上的默认 Docker 容器运行时，以便所有 Amazon ECS 容器都可以使用 GPU。有关更多信息，请参阅《Amazon EC2 用户指南》**中的[在启动包含用户数据输入的 EC2 实例时运行命令](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/user-data.html)。

   ```
   const userData = ec2.UserData.forLinux();
    userData.addCommands(
    'sudo rm /etc/sysconfig/docker',
    'echo DAEMON_MAXFILES=1048576 | sudo tee -a /etc/sysconfig/docker',
    'echo OPTIONS="--default-ulimit nofile=32768:65536 --default-runtime nvidia" | sudo tee -a /etc/sysconfig/docker',
    'echo DAEMON_PIDFILE_TIMEOUT=10 | sudo tee -a /etc/sysconfig/docker',
    'sudo systemctl restart docker',
   );
   ```

1. 在容器上设置 `NVIDIA_VISIBLE_DEVICES` 环境变量。您可以通过在任务定义中指定环境变量来执行此操作。有关有效值的信息，请参阅 NVIDIA 文档网站上的 [GPU Enumeration](https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/latest/docker-specialized.html#gpu-enumeration)。

## 如果您需要 P2 实例该怎么办
<a name="p2-instance"></a>

如果您需要使用 P2 实例，可以使用以下选项之一继续使用实例。

您必须修改这两个选项的实例用户数据。有关更多信息，请参阅《Amazon EC2 用户指南》**中的[在启动包含用户数据输入的 EC2 实例时运行命令](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/user-data.html)。

**使用最新支持的经 GPU 优化的 AMI**

您可以使用经 GPU 优化的 AMI 的 `20230906` 版本，并将以下内容添加到实例用户数据中。

将 cluster-name 替换为您集群的名称。

```
#!/bin/bash
echo "exclude=*nvidia* *cuda*" >> /etc/yum.conf
echo "ECS_CLUSTER=cluster-name" >> /etc/ecs/ecs.config
```

**使用最新的经 GPU 优化的 AMI，并更新用户数据**

您可在实例用户数据中添加以下内容。这将卸载 Nvidia 535/Cuda12.2 驱动程序，然后安装 Nvidia 470/Cuda11.4 驱动程序并修复该版本。

```
#!/bin/bash
yum remove -y cuda-toolkit* nvidia-driver-latest-dkms*
tmpfile=$(mktemp)
cat >$tmpfile <<EOF
[amzn2-nvidia]
name=Amazon Linux 2 Nvidia repository
mirrorlist=\$awsproto://\$amazonlinux.\$awsregion.\$awsdomain/\$releasever/amzn2-nvidia/latest/\$basearch/mirror.list
priority=20
gpgcheck=1
gpgkey=https://developer.download.nvidia.com/compute/cuda/repos/rhel7/x86_64/7fa2af80.pub
enabled=1
exclude=libglvnd-*
EOF

mv $tmpfile /etc/yum.repos.d/amzn2-nvidia-tmp.repo
yum install -y system-release-nvidia cuda-toolkit-11-4 nvidia-driver-latest-dkms-470.182.03
yum install -y libnvidia-container-1.4.0 libnvidia-container-tools-1.4.0 nvidia-container-runtime-hook-1.4.0 docker-runtime-nvidia-1

echo "exclude=*nvidia* *cuda*" >> /etc/yum.conf
nvidia-smi
```

**创建您自己的兼容 P2 且经过 GPU 优化的 AMI**

您可以创建与 P2 实例兼容的自定义 Amazon ECS GPU 优化型 AMI，然后使用 AMI 启动 P2 实例。

1. 运行以下命令以克隆 `amazon-ecs-ami repo`。

   ```
   git clone https://github.com/aws/amazon-ecs-ami
   ```

1. 在 `release.auto.pkrvars.hcl` 或 `overrides.auto.pkrvars.hcl` 中设置所需的 Amazon ECS 代理和源 Amazon Linux AMI 版本。

1. 运行以下命令来构建兼容 P2 的私有 EC2 AMI。

   将“区域”替换为“区域”和“实例区域”。

   ```
   REGION=region make al2keplergpu
   ```

1. 使用包含以下实例用户数据的 AMI 连接到 Amazon ECS 集群。

   将 cluster-name 替换为您集群的名称。

   ```
   #!/bin/bash
   echo "ECS_CLUSTER=cluster-name" >> /etc/ecs/ecs.config
   ```