优化亚马逊 EC2 上人工智能/机器学习工作负载的 GPU 利用率

作者: 希拉·布瑟 | 2023 年 4 月

这篇博客文章由开发运营顾问 Ben Minahan 和机器学习工程师 Amir Sotoodeh 撰写。

机器学习工作负载可能非常昂贵,而人工智能/机器学习 (AI/ML) 团队可能很难跟踪和保持有效的资源利用率。机器学习工作负载通常会广泛使用 GPU,因此,在系统性能方面,CPU、内存和磁盘使用率等典型的应用程序性能指标并不能反映出全貌。此外,数据科学家还会在符合其独特规格的现有计算实例上进行长期实验和模型训练活动。强迫这些实验在新配置的基础设施上安装适当的监控系统可能不是一个可行的选择。

在这篇文章中,我们描述了如何跟踪所有 AI/ML 工作负载的 GPU 利用率,并实现准确的容量规划,而无需团队使用自定义 Amazon 机器映像 (AMI) 或重新部署现有基础设施。您可以使用 亚马逊 CloudWatch 来跟踪 GPU 使用率,并利用 亚马逊云科技 System s Manager 运行命令在支持 GPU 的现有实例队列中安装和配置代理。

概述

首先,确保您的现有 亚马逊弹性计算云 (Amazon EC2) 实例安装了系统管理器代理,并且还具有相应级别的 亚马逊云科技 身份和访问管理 (IAM ) 权限以运行亚马逊 CloudWat ch 代理。 接下来,在系统管理器参数存储中指定 CloudWatch 代理的配置,然后将 CloudWatch 代理部署到我们支持 GPU 的 EC2 实例。最后,创建一个 CloudWatch 控制面板来分析 GPU 利用率。

Architecture Diagram depicting the integration between AWS Systems Manager with RunCommand Arguments stored in SSM Parameter Store, your Amazon GPU enabled EC2 instance with installed Amazon CloudWatch Agen­t, and Amazon CloudWatch Dashboard that aggregates and displays the ­reported metrics.

  1. 在您现有的支持 GPU 的 EC2 实例上安装 CloudWatch 代理。
  2. 您的 CloudWatch 代理配置存储在系统管理器参数存储中。
  3. 系统管理员文档用于在您的 EC2 实例上安装和配置 CloudWatch 代理。
  4. GPU 指标发布到 CloudWatch,然后您可以通过 CloudWatch 控制面板对其进行可视化。

先决条件

这篇文章假设您的 亚马逊云科技 账户中已经运行了支持 GPU 的 EC2 工作负载。如果 EC2 实例没有任何 GPU,则自定义配置将不会应用于 CloudWatch 代理。而是使用默认配置。对于这些实例,利用 CloudWatch 代理的默认配置更适合跟踪资源利用率。

为了让 CloudWatch 代理收集您的实例的 GPU 指标,必须在您的实例上安装适当的 NVIDIA 驱动程序。包括深度学习 AMI 在内的几个 亚马逊云科技 官方 AMI 已经安装了这些驱动程序。要查看预装了 NVIDIA 驱动程序的 AMI 列表以及基于 Linux 的实例的完整安装说明,请参阅在 Linux 实例 上 安装 NVIDIA 驱动程序

此外,部署和管理 CloudWatch 代理需要实例处于运行状态。如果您的实例当前已停止,则必须按照本文中概述的说明启动实例。

准备您的 EC2 实例

您使用系统管理器来部署 CloudWatch 代理,因此请确保您的 EC2 实例安装了系统管理器代理。许多 亚马逊云科技 提供的 AMI 已经安装了系统管理器代理。有关预装了系统管理器代理的 AMI 的完整列表,请参阅预装了 SSM 代理的 亚马逊系统映像 (AMI) 。 如果您的 AMI 未安装 Systems Manager 代理,请参阅 使用 SSM 代理 ,了解如何根据您的操作系统 (OS) 进行安装。

安装后,CloudWatch 代理需要一定的权限才能接受来自系统管理器的命令、读取系统管理器参数存储条目以及向 CloudWatch 发布指标。 这些权限捆绑到托管 IAM 策略 A mazonec2RoleforSSM、AmazonsmReadonlyAccess 和 CloudWatchAgentS erverPolicy 中。 要创建附有这些策略的新 IAM 角色和相关的 IAM 实例配置文件,您可以运行以下 亚马逊云科技 命令行接口 (亚马逊云科技 CLI ) 命令 ,替换为 您的 亚马逊云科技 区域以及要与实例配置文件关联的 EC2 实例 ID:

aws iam create-role --role-name CloudWatch-Agent-Role --assume-role-policy-document  '{"Statement":{"Effect":"Allow","Principal":{"Service":"ec2.amazonaws.com"},"Action":"sts:AssumeRole"}}'
aws iam attach-role-policy --role-name CloudWatch-Agent-Role --policy-arn arn:aws:iam::aws:policy/service-role/AmazonEC2RoleforSSM
aws iam attach-role-policy --role-name CloudWatch-Agent-Role --policy-arn arn:aws:iam::aws:policy/AmazonSSMReadOnlyAccess
aws iam attach-role-policy --role-name CloudWatch-Agent-Role --policy-arn arn:aws:iam::aws:policy/CloudWatchAgentServerPolicy
aws iam create-instance-profile --instance-profile-name CloudWatch-Agent-Instance-Profile
aws iam add-role-to-instance-profile --instance-profile-name CloudWatch-Agent-Instance-Profile --role-name CloudWatch-Agent-Role
aws ec2 associate-iam-instance-profile --region <REGION_NAME> --instance-id <INSTANCE_ID> --iam-instance-profile Name=CloudWatch-Agent-Instance-Profile

或者,您可以将 IAM 策略附加到与现有 IAM 实例配置文件关联的现有 IAM 角色。

aws iam attach-role-policy --role-name <ROLE_NAME> --policy-arn arn:aws:iam::aws:policy/service-role/AmazonEC2RoleforSSM
aws iam attach-role-policy --role-name <ROLE_NAME> --policy-arn arn:aws:iam::aws:policy/AmazonSSMReadOnlyAccess
aws iam attach-role-policy --role-name <ROLE_NAME> --policy-arn arn:aws:iam::aws:policy/CloudWatchAgentServerPolicy
aws ec2 associate-iam-instance-profile --region <REGION_NAME> --instance-id <INSTANCE_ID> --iam-instance-profile Name=<INSTANCE_PROFILE>

完成后,您应该看到您的 EC2 实例与相应的 IAM 角色相关联。

An Amazon EC2 Instance with the CloudWatch-Agent-Role IAM Role attached

此角色应附加 Amazon ec2RoleforSSM 、AmazonsmReadonlyAccess 和 CloudWatch A gent 服务器政策 IAM 政策。

The CloudWatch-Agent-Role IAM Role’s attached permission policies, Amazon EC2 Role for SSM, CloudWatch Agent Server ¬Policy, and Amazon SSM Read Only Access

配置和部署 CloudWatch 代理

在我们的 EC2 实例上部署 CloudWatch 代理之前,请确保这些代理已正确配置以收集 GPU 指标。为此,您必须创建 CloudWatch 代理配置并将其存储在系统管理器参数存储中。

将以下内容复制到 cloudwatch-agent-config.json 文件中:

{
    "agent": {
        "metrics_collection_interval": 60,
        "run_as_user": "cwagent"
    },
    "metrics": {
        "aggregation_dimensions": [
            [
                "InstanceId"
            ]
        ],
        "append_dimensions": {
            "AutoScalingGroupName": "${aws:AutoScalingGroupName}",
            "ImageId": "${aws:ImageId}",
            "InstanceId": "${aws:InstanceId}",
            "InstanceType": "${aws:InstanceType}"
        },
        "metrics_collected": {
            "cpu": {
                "measurement": [
                    "cpu_usage_idle",
                    "cpu_usage_iowait",
                    "cpu_usage_user",
                    "cpu_usage_system"
                ],
                "metrics_collection_interval": 60,
                "resources": [
                    "*"
                ],
                "totalcpu": false
            },
            "disk": {
                "measurement": [
                    "used_percent",
                    "inodes_free"
                ],
                "metrics_collection_interval": 60,
                "resources": [
                    "*"
                ]
            },
            "diskio": {
                "measurement": [
                    "io_time"
                ],
                "metrics_collection_interval": 60,
                "resources": [
                    "*"
                ]
            },
            "mem": {
                "measurement": [
                    "mem_used_percent"
                ],
                "metrics_collection_interval": 60
            },
            "swap": {
                "measurement": [
                    "swap_used_percent"
                ],
                "metrics_collection_interval": 60
            },
            "nvidia_gpu": {
                "measurement": [
                    "utilization_gpu",
                    "temperature_gpu",
                    "utilization_memory",
                    "fan_speed",
                    "memory_total",
                    "memory_used",
                    "memory_free",
                    "pcie_link_gen_current",
                    "pcie_link_width_current",
                    "encoder_stats_session_count",
                    "encoder_stats_average_fps",
                    "encoder_stats_average_latency",
                    "clocks_current_graphics",
                    "clocks_current_sm",
                    "clocks_current_memory",
                    "clocks_current_video"
                ],
                "metrics_collection_interval": 60
            }
        }
    }
}

运行以下 亚马逊云科技 CLI 命令来部署系统管理器参数 C loudwatch-Agent-config, 其中包含用于 GPU 指标收集的最低代理配置。替换 为您的 亚马逊云科技 区域

aws ssm put-parameter \
--region <REGION_NAME> \
--name CloudWatch-Agent-Config \
--type String \
--value file://cloudwatch-agent-config.json

现在,您可以在系统管理器参数存储中看到 CloudWatch Agent-config 参数,其中包含您的 CloudWatch 代理的 JSON 配置。

CloudWatch-Agent-Config stored in Systems Manager Parameter Store

接下来,在您的 EC2 实例上安装 CloudWatch 代理。为此,你可以利用 Systems Manager 运行命令,特别是自动安装 CloudWatch 代理的 亚马逊云科技-ConfigureawsPackage 文档。

  1. 运行以下 亚马逊云科技 CLI 命令, 替换为部署实例的区域,以及 要在其上安装 CloudWatch 代理的 EC2 实例 ID。
aws ssm send-command \
--query 'Command.CommandId' \
--region <REGION_NAME> \
--instance-ids <INSTANCE_ID> \
--document-name AWS-ConfigureAWSPackage \
--parameters '{"action":["Install"],"installationType":["In-place update"],"version":["latest"],"name":["AmazonCloudWatchAgent"]}'

2。要监控命令的状态,请使用 get-command-invocation 亚马逊云科技 CLI 命令。 替换为上一步的命令 ID 输出、 您的 亚马逊云科技 区域和 EC2 实例 ID。

aws ssm get-command-invocation --query Status --region <REGION_NAME> --command-id <COMMAND_ID> --instance-id <INSTANCE_ID>

3. 等待命令显示 “ 成功” 状态后 再继续。

$ aws ssm send-command \
	 --query 'Command.CommandId' \
    --region us-east-2 \
    --instance-ids i-0123456789abcdef \
    --document-name AWS-ConfigureAWSPackage \
    --parameters '{"action":["Install"],"installationType":["Uninstall and reinstall"],"version":["latest"],"additionalArguments":["{}"],"name":["AmazonCloudWatchAgent"]}'

"5d8419db-9c48-434c-8460-0519640046cf"

$ aws ssm get-command-invocation --query Status --region us-east-2 --command-id 5d8419db-9c48-434c-8460-0519640046cf --instance-id i-0123456789abcdef

"Success"

对要在其上安装 CloudWatch 代理的所有 EC2 实例重复此过程。

接下来,配置 CloudWatch 代理的安装。为此,再次利用系统管理器运行命令。但是,这次应用您的自定义 代理配置的 AmazonCloudwatch-ManageAgent 文档存储在系统管理器参数存储库中,供您部署的代理使用。

  1. 运行以下 亚马逊云科技 CLI 命令, 替换为部署实例的区域,以及 要在其上配置 CloudWatch 代理的 EC2 实例 ID。
aws ssm send-command \
--query 'Command.CommandId' \
--region <REGION_NAME> \
--instance-ids <INSTANCE_ID> \
--document-name AmazonCloudWatch-ManageAgent \
--parameters '{"action":["configure"],"mode":["ec2"],"optionalConfigurationSource":["ssm"],"optionalConfigurationLocation":["/CloudWatch-Agent-Config"],"optionalRestart":["yes"]}'

2。要监控命令的状态,请使用 get-command-invocation 亚马逊云科技 CLI 命令。 替换为上一步的命令 ID 输出、 您的 亚马逊云科技 区域和 EC2 实例 ID。

aws ssm get-command-invocation --query Status --region <REGION_NAME> --command-id <COMMAND_ID> --instance-id <INSTANCE_ID>

3。等待命令显示成功状态后再继续。

$ aws ssm send-command \
    --query 'Command.CommandId' \
    --region us-east-2 \
    --instance-ids i-0123456789abcdef \
    --document-name AmazonCloudWatch-ManageAgent \
    --parameters '{"action":["configure"],"mode":["ec2"],"optionalConfigurationSource":["ssm"],"optionalConfigurationLocation":["/CloudWatch-Agent-Config"],"optionalRestart":["yes"]}'

"9a4a5c43-0795-4fd3-afed-490873eaca63"

$ aws ssm get-command-invocation --query Status --region us-east-2 --command-id 9a4a5c43-0795-4fd3-afed-490873eaca63 --instance-id i-0123456789abcdef

"Success"

对要在其上安装 CloudWatch 代理的所有 EC2 实例重复此过程。完成后,CloudWatch 代理的安装和配置即告完成,您的 EC2 实例现在会向 CloudWatch 报告 GPU 指标。

在 CloudWatch 中可视化实例的 GPU 指标

现在,启用 GPU 的 EC2 实例已将其利用率指标发布到 CloudWatch,您可以对这些指标进行可视化和分析,以更好地了解您的资源利用模式。

CloudWatch 代理收集的 GPU 指标位于 C W Agent 命名空间内。使用 CloudWatch 指标资源管理器浏览您的 GPU 指标 ,或部署我们提供的示例控制面板。

  1. 将以下内容复制到名为 cloudwatch-dashboard.json 的文件中 ,将的实例替换为您的区域:
{
    "widgets": [
        {
            "height": 10,
            "width": 24,
            "y": 16,
            "x": 0,
            "type": "metric",
            "properties": {
                "metrics": [
                    [{"expression": "SELECT AVG(nvidia_smi_utilization_gpu) FROM SCHEMA(\"CWAgent\", InstanceId) GROUP BY InstanceId","id": "q1"}]
                ],
                "view": "timeSeries",
                "stacked": false,
                "region": "<REGION_NAME>",
                "stat": "Average",
                "period": 300,
                "title": "GPU Core Utilization",
                "yAxis": {
                    "left": {"label": "Percent","max": 100,"min": 0,"showUnits": false}
                }
            }
        },
        {
            "height": 7,
            "width": 8,
            "y": 0,
            "x": 0,
            "type": "metric",
            "properties": {
                "metrics": [
                    [{"expression": "SELECT AVG(nvidia_smi_utilization_gpu) FROM SCHEMA(\"CWAgent\", InstanceId)", "label": "Utilization","id": "q1"}]
                ],
                "view": "gauge",
                "stacked": false,
                "region": "<REGION_NAME>",
                "stat": "Average",
                "period": 300,
                "title": "Average GPU Core Utilization",
                "yAxis": {"left": {"max": 100, "min": 0}
                },
                "liveData": false
            }
        },
        {
            "height": 9,
            "width": 24,
            "y": 7,
            "x": 0,
            "type": "metric",
            "properties": {
                "metrics": [
                    [{ "expression": "SEARCH(' MetricName=\"nvidia_smi_memory_used\" {\"CWAgent\", InstanceId} ', 'Average')", "id": "m1", "visible": false }],
                    [{ "expression": "SEARCH(' MetricName=\"nvidia_smi_memory_total\" {\"CWAgent\", InstanceId} ', 'Average')", "id": "m2", "visible": false }],
                    [{ "expression": "SEARCH(' MetricName=\"mem_used_percent\" {CWAgent, InstanceId} ', 'Average')", "id": "m3", "visible": false }],
                    [{ "expression": "100*AVG(m1)/AVG(m2)", "label": "GPU", "id": "e2", "color": "#17becf" }],
                    [{ "expression": "AVG(m3)", "label": "RAM", "id": "e3" }]
                ],
                "view": "timeSeries",
                "stacked": false,
                "region": "<REGION_NAME>",
                "stat": "Average",
                "period": 300,
                "yAxis": {
                    "left": {"min": 0,"max": 100,"label": "Percent","showUnits": false}
                },
                "title": "Average Memory Utilization"
            }
        },
        {
            "height": 7,
            "width": 8,
            "y": 0,
            "x": 8,
            "type": "metric",
            "properties": {
                "metrics": [
                    [ { "expression": "SEARCH(' MetricName=\"nvidia_smi_memory_used\" {\"CWAgent\", InstanceId} ', 'Average')", "id": "m1", "visible": false } ],
                    [ { "expression": "SEARCH(' MetricName=\"nvidia_smi_memory_total\" {\"CWAgent\", InstanceId} ', 'Average')", "id": "m2", "visible": false } ],
                    [ { "expression": "100*AVG(m1)/AVG(m2)", "label": "Utilization", "id": "e2" } ]
                ],
                "sparkline": true,
                "view": "gauge",
                "region": "<REGION_NAME>",
                "stat": "Average",
                "period": 300,
                "yAxis": {
                    "left": {"min": 0,"max": 100}
                },
                "liveData": false,
                "title": "GPU Memory Utilization"
            }
        }
    ]
}

2. 运行以下 亚马逊云科技 CLI 命令, 替换为您所在地区的名称:

aws cloudwatch put-dashboard \
    --region <REGION_NAME> \
    --dashboard-name My-GPU-Usage \
    --dashboard-body file://cloudwatch-dashboard.json

在您的 亚马逊云科技 地区的 CloudWatch 控制台中查 看 MY-GPU 使用情况 CloudWatch 控制面板。

An example CloudWatch dashboard, My-GPU-Usage, showing the GPU usage metrics over time.

正在清理

为了避免将来因关注本文而创建的资源产生成本,请删除以下内容:

  1. 我的 GPU 使用情况 CloudWatch 控制面板
  2. Cloudwatch 代理配置系统管理器参数
  3. Cloudwatch 代理角色 IAM 角色

结论

通过关注这篇文章,您在支持 GPU 的 EC2 实例上部署和配置了 CloudWatch 代理,以便在不暂停正在进行的实验和模型训练的情况下跟踪 GPU 利用率。然后,您使用 CloudWatch 控制面板可视化工作负载的 GPU 利用率,以更好地了解工作负载的 GPU 使用情况,并做出更明智的扩展和成本决策。有关亚马逊 CloudWatch 可以改善组织运营洞察力的其他方式,请参阅 亚马逊 Cloud Watch 文档