### **概述**
随着生成式 AI 的大力发展,越来越多的企业纷纷在开发自己的生成式 AI 应用,为了优化生成式 AI 的效果,微调是一种常用的方式,但由于高性能 GPU 的紧缺,阻碍了研发速度。
Amazon p5.48xlarge 实例类型采用 NVIDIA H100 GPU,具有 8 个 GPU 单元,每个单元包含 80GB 显存,具有优秀的性能,相比上一代 Amazon p4d 实例(采用 8 个 NVIDIA A100 GPU),加速了 4 倍以上的训练时间,也减少了 40% 的训练成本。
**本文将介绍采用 Amazon P5 Spot 实例,进行 大语言模型(LLM)的微调任务**。对于参数量较少的 LLM,比如 13B 以下,一般可以采用单机多卡的方式,这种场景可容错且比较灵活,适用 Spot 实例。同时与按需实例价格相比 Spot 实例具有巨大的成本优势。
Spot 实例存在的问题是可能被中断回收,影响正常的任务运行。
Spot 实例说明:
* [Amazon EC2 ](https://aws.amazon.com/cn/ec2/?trk=cndc-detail)Spot 实例是利用空闲的 [Amazon EC2 ](https://aws.amazon.com/cn/ec2/?trk=cndc-detail)容量,与按需实例是相同的基础架构。
* 与按需实例价格相比,Spot 实例最高可以节省 90% 的成本,Spot 价格基于 [Amazon EC2 ](https://aws.amazon.com/cn/ec2/?trk=cndc-detail)实例的长期供需趋势逐步调整,无需竞价更易预测。
* Spot 实例和按需实例之间的唯一区别是,当 [Amazon EC2 ](https://aws.amazon.com/cn/ec2/?trk=cndc-detail)需要收回 Spot 容量时,Spot 实例可能会中断并提前两分钟发出通知。
* Spot 实例在容量可用时可运行,对于短期运行的应用程序或者可以中断的应用程序,Spot 实例是经济实惠之选。例如,Spot 实例非常适合数据分析、批处理作业、后台处理和[机器学习](https://aws.amazon.com/cn/machine-learning/?trk=cndc-detail)等任务。
* Spot 实例不能保证可以运行足够长的时间以完成工作任务。Spot 实例也不能保证可以立即得到想要的计算容量,或者不能保证始终可以获得请求的总容量。此外,Spot 实例中断和容量的状况可能会随着时间的推移而发生变化,因为 Spot 实例可用性会根据供需关系而发生变化。
**[Amazon EC2 ](https://aws.amazon.com/cn/ec2/?trk=cndc-detail)Spot 容量和中断处理最佳实践的根本原则是灵活性,从实例灵活(不同实例家族/代系/Size)、时间灵活、地区灵活(不同可用区/区域)三个方面丰富 Spot 容量池,提高灵活度,降低 Spot 中断率。**
在使用 P5 Spot 实例之前,首先在 Service Quotas 中修改 [Amazon EC2 ](https://aws.amazon.com/cn/ec2/?trk=cndc-detail)的 All P5 Spot Instance Requests 参数,提高可启动的 P5 Spot 实例限额。
下面介绍一个参考架构,管理 [Amazon EC2 ](https://aws.amazon.com/cn/ec2/?trk=cndc-detail)P5 Spot 实例,尽可能降低 Spot 容量不足和中断产生的影响。

架构图说明:
1. Amazon Management System 将接收用户请求,创建和管理 Spot 实例。
2. [Amazon DynamoDB](https://aws.amazon.com/cn/dynamodb/?trk=cndc-detail) 数据库保存 Spot 实例的状态和用户请求信息。
3. Jumpserver 将供用户 SSH 登陆。
4. Spot Instance 是 P5 Spot 实例,用户通过 Jumpserver 登陆,进行 LLM 微调的任务。
5. [Amazon S3](https://aws.amazon.com/cn/s3/?trk=cndc-detail) 保存用户的训练数据,将利用 Mountpoint for [Amazon S3](https://aws.amazon.com/cn/s3/?trk=cndc-detail) 插件,将 [Amazon S3](https://aws.amazon.com/cn/s3/?trk=cndc-detail) 桶 mount 到 P5 Spot 实例。用户在使用 P5 Spot 实例时,可以先将 [Amazon S3](https://aws.amazon.com/cn/s3/?trk=cndc-detail) 数据拷贝到本地存储,以加速访问数据的速度;也可以将微调任务的结果和日志放到 [Amazon S3](https://aws.amazon.com/cn/s3/?trk=cndc-detail) 桶中,用于长期保存和下载。
6. [Amazon SNS](https://aws.amazon.com/cn/sns/?trk=cndc-detail) 将通知用户关于实例状态和任务状态的信息,可以通过邮件或调用接口等方式;另外通过 [Amazon SNS](https://aws.amazon.com/cn/sns/?trk=cndc-detail) 的 Subscription filter policy 可以过滤接收到的消息,发给指定的接收方。
7. [Amazon EventBridge](https://aws.amazon.com/cn/eventbridge/?trk=cndc-detail) 可配置 Rule,接收和处理实例状态改变等的事件,比如实例创建、销毁和中断。
8. Fault Injection Service 可以模拟 Spot 实例中断,用来测试系统功能。
**Amazon Management System 可以采用 Serverless 的方式实现,比如利用 Amazon Lambda、[Amazon API Gateway](https://aws.amazon.com/cn/api-gateway/?trk=cndc-detail)、Amazon Step Functions 和 [Amazon DynamoDB](https://aws.amazon.com/cn/dynamodb/?trk=cndc-detail)。下面是参考的流程图。**

### **参考架构中涉及到的接口和示例**
以下的接口示例采用 Amazon CLI 命令行工具完成,其他语言程序开发也可以借鉴 Amazon CLI 的命令。
- [Amazon CLI 安装参考](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html?trk=cndc-detail)
下面示例的资源部署在 Ohio Region(us-east-2),为保障命令的顺利执行,可以采用具有 Admin 权限的 IAM User。
#### 1、定义环境变量
```js
export AWS_ACCOUNT_ID=***
export MY_EMAIL_ADDRESS=***@example.com
```
修改上面的参数值。
#### 2、创建 Amazon S3 Bucket
```js
aws s3 mb s3://p5-spot-test --region us-east-2
```
#### 3、创建 Amazon SNS Topic
[Amazon SNS](https://aws.amazon.com/cn/sns/?trk=cndc-detail) 将通知用户关于实例状态和任务状态的信息,可以通过邮件通知或调用接口等方式。
下面示例将创建 [Amazon SNS](https://aws.amazon.com/cn/sns/?trk=cndc-detail) Topic,创建 email 的订阅,在 access policy 中添加 [Amazon EventBridge](https://aws.amazon.com/cn/eventbridge/?trk=cndc-detail) 的消息发布权限。
操作命令如下:
```js
aws sns create-topic --name p5-spot-test --region us-east-2
aws sns subscribe \\
--topic-arn arn:aws:sns:us-east-2:\${AWS_ACCOUNT_ID}:p5-spot-test \\
--protocol email \\
--notification-endpoint \${MY_EMAIL_ADDRESS} \\
--region us-east-2
cat <<EOF > sns-access-policy.json
{
"Version": "2008-10-17",
"Id": "__default_policy_ID",
"Statement": [
{
"Sid": "__default_statement_ID",
"Effect": "Allow",
"Principal": {
"AWS": "*"
},
"Action": [
"SNS:GetTopicAttributes",
"SNS:SetTopicAttributes",
"SNS:AddPermission",
"SNS:RemovePermission",
"SNS:DeleteTopic",
"SNS:Subscribe",
"SNS:ListSubscriptionsByTopic",
"SNS:Publish"
"Sid": "events",
"Effect": "Allow",
"Principal": {
"Service": "events.amazonaws.com"
},
"Action": "sns:Publish",
"Resource": "arn:aws:sns:us-east-2:\${AWS_ACCOUNT_ID}:p5-spot-test"
}
]
}
EOF
aws sns set-topic-attributes \\
--topic-arn arn:aws:sns:us-east-2:\${AWS_ACCOUNT_ID}:p5-spot-test \\
--attribute-name 'Policy' \\
--attribute-value file://sns-access-policy.json \\
--region us-east-2
```
邮箱将收到订阅的确认邮件,需确定订阅。
#### 4、启动 Spot 实例
1)查看 Spot 实例的历史价格:
```js
aws ec2 describe-spot-price-history --instance-types p5.48xlarge --product-description "Linux/UNIX (Amazon VPC)" --region us-east-2 --start-time 2025-01-01T00:00:00
```
由于 [Amazon EC2 ](https://aws.amazon.com/cn/ec2/?trk=cndc-detail)P5 Spot 实例在各个区域和可用区的价格是不同的,且相差较大,可以通过该命令获得较低价格的可用区,在保障容量的前提下,优先使用性价比高的区域和可用区。
**注:Start Time 参数设定为未来日期时,将返回一条最近的 Spot 实例价格。*
2)设定需要的实例数量,查看 [Spot Placement score(SPS)](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/spot-placement-score.html?trk=cndc-detail)。
操作指令:
```js
aws ec2 get-spot-placement-scores --instance-types p5.48xlarge --target-capacity 1 --target-capacity-unit-type units --single-availability-zone
```
返回的结果如下:
```js
{
"SpotPlacementScores": [
{
"Region": "us-west-2",
"AvailabilityZoneId": "usw2-az2",
"Score": 1
},
{
"Region": "us-east-1",
"AvailabilityZoneId": "use1-az5",
"Score": 1
},
{
"Region": "us-east-2",
"AvailabilityZoneId": "use2-az2",
"Score": 3
},
{
"Region": "us-west-2",
"AvailabilityZoneId": "usw2-az1",
"Score": 1
}
]
}
```
从命令的返回结果中,可以发现在 3 个区域 us-east-1,us-west-2 和 us-east-2 中有 4 个可用区支持 P5 Spot,其中 use2-az2 可用区的 SPS 相对较高,可优先尝试启动 use2-az2 的 P5 Spot 实例。
Spot 容量会发生波动,所以无法确保始终获得所需的容量。SPS 表示 Spot 请求在某个区域或可用区中获得成功的可能性,分数越高可能性越大。
3)获得 use2-az2 对应的 Subnet。
```js
aws ec2 describe-subnets --region us-east-2 --query 'Subnets[?AvailabilityZoneId==`use2-az2`]'
```
4)创建 IAM Role,给 Spot Instance 访问 [Amazon S3](https://aws.amazon.com/cn/s3/?trk=cndc-detail) Bucket、[Amazon SNS](https://aws.amazon.com/cn/sns/?trk=cndc-detail) 和 Amazon SSM 的权限。
```js
cat <<EOF > trust-policy.json
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "ec2.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
EOF
aws iam create-role --role-name p5-spot-test \\
--assume-role-policy-document file://trust-policy.json
cat <<EOF > s3-policy.json
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "1",
"Effect": "Allow",
"Action": [
"s3:ListBucket"
],
"Resource": [
"arn:aws:s3:::p5-spot-test"
]
},
{
"Sid": "2",
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:PutObject",
"s3:AbortMultipartUpload",
"s3:DeleteObject"
],
"Resource": [
"arn:aws:s3:::p5-spot-test/*"
]
}
]
}
EOF
aws iam put-role-policy --role-name p5-spot-test --policy-name s3-policy --policy-document file://s3-policy.json
cat <<EOF > sns-policy.json
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "1",
"Effect": "Allow",
"Action": [
"sns:Publish"
],
"Resource": [
"arn:aws:sns:us-east-2:\${AWS_ACCOUNT_ID}:p5-spot-test"
]
}
]
}
EOF
aws iam put-role-policy --role-name p5-spot-test --policy-name sns-policy --policy-document file://sns-policy.json
aws iam attach-role-policy --role-name p5-spot-test --policy-arn arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore
aws iam create-instance-profile --instance-profile-name p5-spot-test
aws iam add-role-to-instance-profile --instance-profile-name p5-spot-test --role-name p5-spot-test
```
5)启动 P5 Spot Instance。
下面采用 [run-instances 命令启动 Spot 实例](https://docs.aws.amazon.com/cli/latest/reference/ec2/run-instances.html?trk=cndc-detail)。
对于 LLM 的微调任务,image-id 可以采用下面的两种 AMI:
- Deep Learning Base OSS Nvidia Driver GPU AMI (Ubuntu 22.04)
- Deep Learning OSS Nvidia Driver AMI GPU PyTorch 2.2.0 (Ubuntu 20.04)
run-instances 命令的参考示例:
```js
aws ec2 run-instances \\
--image-id ami-*** \\
--instance-type p5.48xlarge \\
--region *** \\
--count 1 \\
--key-name *** \\
--security-group-ids sg-*** \\
--subnet-id subnet-*** \\
--iam-instance-profile Name= *** \\
--tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value='***'}]' \\
--block-device-mappings 'DeviceName=/dev/xvda,Ebs={VolumeType=gp3,VolumeSize=***,DeleteOnTermination=true}' \\
--instance-market-options 'MarketType=spot'
```
请按照自身环境配置,修改 *** 的部分,其中 AMI 采用 Deep Learning OSS Nvidia Driver AMI GPU PyTorch 2.2.0 (Ubuntu 20.04) 做测试。
当执行 run-instances 命令返回 Instance 信息时,表示成功启动 Spot Instance,记录 InstanceId 和 PrivateIpAddress。
#### 5、操作 Spot Instance
1)登陆到 Jumpserver,通过 Spot Instance 的 PrivateIpAddress 和 ubuntu 用户,再登陆到 Spot Instance 上。
2)[安装 Mountpoint for Amazon S3](https://docs.aws.amazon.com/AmazonS3/latest/userguide/mountpoint.html?trk=cndc-detail)。
操作步骤如下:
```js
sudo apt update
sudo apt install libfuse2
wget https://s3.amazonaws.com/mountpoint-s3-release/latest/x86_64/mount-s3.deb
sudo apt install ./mount-s3.deb
mount-s3 --version
mkdir ~/s3
mount-s3 --allow-delete --allow-overwrite p5-spot-test ~/s3
```
将 [Amazon S3](https://aws.amazon.com/cn/s3/?trk=cndc-detail) Bucket(p5-spot-test)mount 到本地~/s3目录。
3)访问 [Amazon S3](https://aws.amazon.com/cn/s3/?trk=cndc-detail) 数据。
```js
cd ~/s3
echo "555" > test.txt
ls
cp test.txt ../
ls -l ../
```
4)可以通过 [Amazon SNS](https://aws.amazon.com/cn/sns/?trk=cndc-detail) 发消息,用于通知任务执行完成的状态。
```js
aws sns publish --topic-arn arn:aws:sns:us-east-2:\${AWS_ACCOUNT_ID}:p5-spot-test --region us-east-2 --message "任务已完成"
```
邮箱将收到通知邮件。
5)终止 Spot Instance。
在 Linux 环境中,执行下列的命令:
```js
sudo shutdown -h now
```
6)Amazon AMI 环境介绍。
本文示例采用 Amazon Deep Learning AMI,包含了 NVIDIA CUDA 和 NVIDIA cuDNN,也包含流行的深度学习框架。
比如 Amazon AMI(Deep Learning OSS Nvidia Driver AMI GPU PyTorch 2.2.0 (Ubuntu 20.04) )包含一个 Conda 环境,部署了 NVIDIA Driver R535, CUDA(12.1.1), cuDNN(8.9.5),NCCL(2.19.4),和EFA(1.31.0)。Amazon AMI 中的软件可能会在未来升级和更新。
在 Ubuntu 上的指令操作演示:
```js
conda --version
conda env list
source activate pytorch
conda list
nvcc --version
python3 --version
nvidia-smi
```
7)Elastic Fabric Adapter(EFA)。
EFA 是一种网络设备,附加在 [Amazon EC2 ](https://aws.amazon.com/cn/ec2/?trk=cndc-detail)实例上,可以获得较低的时延和更高的吞吐量,加速 HPC 任务和 ML 应用。
P5 实例类型具有 3200 Gbps 的网络带宽,使用 32 个 EFA 网卡。在多机多卡的训练环境中,需要[配置 EFA](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/efa-acc-inst-types.html?trk=cndc-detail),加速 [Amazon EC2 ](https://aws.amazon.com/cn/ec2/?trk=cndc-detail)实例之间的通讯。
#### 6、创建 EventBridge Rule
1)添加 Rule,响应 [Amazon EC2 ](https://aws.amazon.com/cn/ec2/?trk=cndc-detail)Spot 中断事件。
```js
aws events put-rule --name p5-spot-test-instance --event-pattern "{\\"source\\":[\\"aws.ec2\\"],\\"detail-type\\":[\\"EC2 Instance State-change Notification\\"]}" --region us-east-2
aws events put-targets --rule p5-spot-test-instance --targets "Id"="1","Arn"="arn:aws:sns:us-east-2:\${AWS_ACCOUNT_ID}:p5-spot-test" --region us-east-2
```
#### 7、配置 Fault Injection Service
创建 Resilience Hub 的 Experiment templates,可以模拟中断 Spot Instance。
按照下面的参数进行配置。
```js
Action:aws:ec2:send-spot-instance-interruptions
Target:
Resource type: aws:ec2:spot-instance
Target method: Resouce tags, filters and parameters
Resource tags: Key=Name, Value=***
***为Spot实例的名称。
```
成功创建 Experiment template 之后,可以点击右上角 Start experiment 按钮,进行 Spot 中断模拟。
邮箱将收到 Spot Instance 中断的信息。
### **总结**
**文章中介绍了启动和管理 [Amazon EC2 ](https://aws.amazon.com/cn/ec2/?trk=cndc-detail)P5 Spot 实例的方法,P5 实例是亚马逊云科技新的[机器学习](https://aws.amazon.com/cn/machine-learning/?trk=cndc-detail)训练机型,有强大的性能和显存容量,可以更好地支持 LLM 的微调任务**。开发者可以参考文中提供的 Amazon CLI 命令,根据自身需求,开发完整 Spot 管理系统,利用 [Amazon EC2 ](https://aws.amazon.com/cn/ec2/?trk=cndc-detail)P5 Spot 实例完成低成本高算力的[机器学习](https://aws.amazon.com/cn/machine-learning/?trk=cndc-detail)任务。
**参考资料**
- https://aws.amazon.com/ec2/spot/?trk=cndc-detail
- https://aws.amazon.com/blogs/aws/new-amazon-ec2-p5-instances-powered-by-nvidia-h100-tensor-core-gpus-for-accelerating-generative-ai-and-hpc-applications/?trk=cndc-detail
- https://aws.amazon.com/ec2/instance-types/p5/?trk=cndc-detail
- https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/spot-placement-score.html?trk=cndc-detail
- https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/spot-instance-termination-notices.html?trk=cndc-detail
- https://docs.aws.amazon.com/AmazonS3/latest/userguide/mountpoint.html?trk=cndc-detail
- https://docs.aws.amazon.com/dlami/latest/devguide/appendix-ami-release-notes.html?trk=cndc-detail
- https://docs.aws.amazon.com/cli/latest/reference/ec2/run-instances.html?trk=cndc-detail
- https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/spot-best-practices.html?trk=cndc-detail
- https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-spot-limits.html?trk=cndc-detail
- https://docs.aws.amazon.com/dlami/latest/devguide/what-is-dlami.html?trk=cndc-detail
- https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/p5-efa.html?trk=cndc-detail

