本文介绍如何使用GPU预留实例,以及如何基于GPU预留实例构建延迟敏感的实时推理服务。
背景信息
场景介绍
在实时推理应用场景中,工作负载具有以下一个或多个特征。
低延迟
单次请求的处理时效性要求高,RT(Response Time)延迟要求严格,90%的长尾延时普遍在百毫秒级别。
主链路
普遍位于业务核心链路,推理成功率要求高,不接受长时间重试。示例如下。
开屏广告推荐/首页产品推荐:根据用户的行为喜好,在应用开屏时进行用户行为的推荐,并实时地展现在用户终端上。
实时流程媒体生产:在互动连麦、直播带货、超低延时播放等场景下,音视频流均需要以极低的延迟在端到端之间进行传播,AI视频超分、AI视频识别的实时性需要保证。
峰波峰谷
业务流量具有明显的潮汐特征,普遍与终端用户使用习惯高度相关。
资源利用率
由于GPU资源规划普遍根据业务高峰评估,峰谷时存在较大资源浪费,资源利用率普遍低于30%。
功能优势
函数计算为实时推理工作负载提供以下功能优势。
预留GPU实例
函数计算平台提供了默认的按量GPU实例之外的另一种GPU使用方式——预留GPU实例。如果您希望消除冷启动延时的影响,满足实时推理业务低延迟响应的要求,可以通过配置预留GPU实例来实现。更多关于预留模式的信息,请参见弹性管理(含预留模式)。
预留GPU实例的弹性伸缩策略(推荐)
函数计算平台为预留GPU实例提供了多种指标的弹性伸缩策略,包括并发度、GPU SM利用率、GPU显存利用率、GPU Encoder利用率和GPU Decoder利用率,以及按时弹性伸缩策略,以满足实时推理业务在不同峰波峰谷下对GPU实例算力的供给要求,从而降低整体部署成本。
服务质量优先,服务成本次优
预留GPU实例的计费周期不同于按量GPU实例,预留GPU实例是以实例存活生命周期进行计费,而不考虑实例的活跃与闲置(不按请求计费)。因此,相较于按量GPU实例,总体使用成本较高,但相较于长期自建GPU集群,降本幅度达50%以上。
规格最优
函数计算平台提供的GPU实例规格,允许您根据自己的工作负载选择不同的卡型,独立配置CPU/GPU/MEM/DISK。最小GPU规格小至1 GB显存/算力,将为您提供最贴合业务的实例规格。
突发流量支撑
函数计算平台提供充足的GPU资源供给,当业务遭遇突发流量时,函数计算将以秒级弹性供给海量GPU算力资源,避免因GPU算力供给不足、GPU算力弹性滞后导致的业务受损。
功能原理
当GPU函数部署完成后,您可以通过配置预留GPU实例的弹性伸缩策略开启预留GPU实例,以提供实时推理应用场景所需的基础设施能力。函数计算平台将根据您配置的伸缩指标进行预留GPU实例的HPA,客户请求将优先分配至预留GPU实例进行推理服务,平台完全遮蔽冷启动,业务保持低延迟响应。
实时推理场景基本信息
容器支持
函数计算GPU场景下,当前仅支持以Custom Container(自定义容器运行环境)进行交付。关于Custom Container的使用详情,请参见Custom Container简介。
GPU实例规格
您可以在推理应用场景下,根据业务需要,特别是算法模型所需要的CPU算力、GPU算力与显存、内存、磁盘,选择不同的GPU卡型与GPU实例规格。关于GPU实例规格的详细信息,请参见实例规格。
模型部署方式
您可以使用多种方式将您的模型部署在函数计算。
通过函数计算控制台部署。具体操作,请参见在控制台创建函数。
通过调用SDK部署。更多信息,请参见API概览。
通过Serverless Devs工具部署。更多信息,请参见Serverless Devs操作命令。
更多部署示例,请参见start-fc-gpu。
预留模式的弹性伸缩
定时修改弹性伸缩策略
函数计算支持使用定时修改弹性伸缩策略。具体操作,请参见定时修改限制。在实时推理场景中,如果您的流量波形呈现为较规律的潮汐流量,您可以在流量高峰来临前的若干分钟,进行预留GPU实例数量的修改;在流量水位下降后,再进行缩容操作,协调最佳的成本和最优的性能。
根据指标的弹性伸缩策略
函数计算针对GPU函数提供以下五种可追踪指标,您可以根据业务的特性选择所需要追踪的指标,来指导动态的弹性策略。
实时推理应用场景中,推荐使用ProvisionedConcurrencyUtilization
并发度指标作为HPA指标。因为并发度/QPS更偏向业务指标,GPU资源利用率更偏向资源指标,业务指标变化会影响资源指标,使用更偏向业务的并发度/QPS指标,可以更及时地触发预留GPU实例扩缩容行为,从而优先保障业务服务质量。
指标名称 | 描述 | 取值范围 |
ProvisionedConcurrencyUtilization | 预留实例的并发利用率。用于统计该函数预留实例正在响应的请求并发值与该函数所有预留实例最大可响应并发值的占比。 | [0, 1],对应利用率为0%~100% |
GPUSmUtilization | GPU SM利用率。用于统计多个实例GPU SM利用率的最大值。 | |
GPUMemoryUtilization | GPU显存利用率。用于统计多个实例GPU显存利用率的最大值。 | |
GPUDecoderUtilization | GPU硬件解码器利用率。用于统计多个实例GPU硬件解码器利用率的最大值。 | |
GPUEncoderUtilization | GPU硬件编码器利用率。用于统计多个实例GPU硬件编码器利用率的最大值。 |
模型服务预热
为了解决模型上线后初次请求耗时较长的问题,函数计算为您提供了模型预热的功能。模型预热的目的是使模型上线后即可进入正常的服务状态。
函数计算推荐您配置实例的initialize
生命周期回调功能来实现模型预热,函数计算会在您的实例启动后自动执行initialize
里的业务逻辑来进行模型服务预热。更多信息,请参见函数实例生命周期回调。
您可以通过以下操作使用模型预热。
在实例的
initialize
生命周期回调功能中加入模型预热逻辑。在您构建的HTTP Server中添加POST方法的
/initialize
的调用Path,并将模型预热的逻辑放在/initialize
的Path下。通常可以让模型服务来执行简单的推理来实现预热的效果。下面是Python语言的示例代码。def prewarm_inference(): res = model.inference() @app.route('/initialize', methods=['POST']) def initialize(): request_id = request.headers.get("x-fc-request-id", "") print("FC Initialize Start RequestId: " + request_id) # Prewarm model and perform naive inference task. prewarm_inference() print("FC Initialize End RequestId: " + request_id) return "Function is initialized, request_id: " + request_id + "\n"
在函数配置页面配置实例生命周期回调信息。
在对应的函数详情页面的函数配置页签下,单击实例生命周期回调区域的编辑,在实例生命周期回调面板配置Initializer回调信息。
配置弹性伸缩并验证
本文为您介绍两种配置GPU实例的弹性伸缩策略的方法,分别为:
配置完弹性伸缩策略后,您可以通过压测的方式查看弹性伸缩的效果,具体请参见执行压测。
通过Serverless Devs工具配置GPU实例的弹性伸缩策略
前提条件
在GPU实例所在地域,完成以下操作:
创建容器镜像服务的企业版实例或个人版实例,推荐您创建企业版实例。具体操作步骤,请参见创建企业版实例。
创建命名空间镜像仓库。具体操作步骤,请参见步骤二:创建命名空间和步骤三:创建镜像仓库。
操作步骤
执行以下命令,克隆工程。
git clone https://github.com/devsapp/start-fc-gpu.git
部署项目。
执行以下命令,进入项目目录。
cd fc-http-gpu-inference-paddlehub-nlp-porn-detection-lstm/src/
项目结构如下所示。
. ├── hook │ └── index.js └── src ├── code │ ├── Dockerfile │ ├── app.py │ ├── hub_home │ │ ├── conf │ │ ├── modules │ │ └── tmp │ └── test │ └── client.py └── s.yaml
执行以下命令,通过Docker构建镜像,并向您的镜像仓库进行推送。
export IMAGE_NAME="registry.cn-shanghai.aliyuncs.com/fc-gpu-demo/paddle-porn-detection:v1" # sudo docker build -f ./code/Dockerfile -t $IMAGE_NAME . # sudo docker push $IMAGE_NAME
重要由于PaddlePaddle框架自身体积较大,首次构建镜像耗时较久,约1个小时,因此,此处为您提供一个VPC地址的公共镜像供您直接使用。使用公共镜像时,无需执行上述docker build和docker push命令。
编辑s.yaml文件。
edition: 1.0.0 name: container-demo access: {access} vars: region: cn-shanghai services: gpu-best-practive: component: devsapp/fc props: region: ${vars.region} service: name: gpu-best-practive-service internetAccess: true logConfig: enableRequestMetrics: true enableInstanceMetrics: true logBeginRule: DefaultRegex project: log-ca041e7c29f2a47eb8aec48f94b**** # 替换为您创建的日志服务项目名称 logstore: config***** # 替换为您创建的日志库名称 role: acs:ram::143199913651****:role/aliyunfcdefaultrole function: name: gpu-porn-detection description: This is the demo function deployment handler: not-used timeout: 1200 caPort: 9000 memorySize: 8192 # 8 GB内存配置 cpu: 2 gpuMemorySize: 8192 # 8 GB显存配置 diskSize: 512 instanceType: fc.gpu.tesla.1 # 部署Tesla卡型的GPU实例 instanceConcurrency: 1 runtime: custom-container environmentVariables: FCGPU_RUNTIME_SHMSIZE : '8589934592' customContainerConfig: image: registry.cn-shanghai.aliyuncs.com/serverless_devs/gpu-console-supervising:paddle-porn-detection # 此处以公共镜像为例,您可以根据实际情况替换为您的镜像名称 accelerationType: Default triggers: - name: httpTrigger type: http config: authType: anonymous methods: - GET - POST
执行以下命令,部署函数。
sudo s deploy --skip-push true -t s.yaml
执行成功后,在执行输出中返回一个URL地址,获取此地址用于后续测试函数。
测试函数,并登录函数计算控制台查看监控结果。
执行Curl命令测试函数,使用上一步获取的URL。
curl https://gpu-poretection-gpu-bes-service-gexsgx****.cn-shanghai.fcapp.run/invoke -H "Content-Type: text/plain" --data "Nice to meet you"
返回以下结果,表示测试通过。
[{"text": "Nice to meet you", "porn_detection_label": 0, "porn_detection_key": "not_porn", "porn_probs": 0.0, "not_porn_probs": 1.0}]%
在函数计算控制台,选择 ,依次单击步骤2部署的服务和函数,然后单击实例指标页签,查看GPU相关指标的变化。
配置弹性预留策略。
创建弹性配置的模板provision.json。
示例如下。该模板使用了实例并发度作为追踪指标,最小实例数为2,最大实例数为30。
{ "target": 2, "targetTrackingPolicies": [ { "name": "scaling-policy-demo", "startTime": "2023-01-01T16:00:00.000Z", "endTime": "2024-01-01T16:00:00.000Z", "metricType": "ProvisionedConcurrencyUtilization", "metricTarget": 0.3, "minCapacity": 2, "maxCapacity": 30 } ] }
执行以下命令,进行弹性策略的部署。
sudo s provision put --config ./provision.json --qualifier LATEST -t s.yaml -a {access}
执行
sudo s provision list
进行验证,可以看到如下输出。其中target
和current
的数值相等,表示预留实例正确拉起,弹性规则部署正确。[2023-05-10 14:49:03] [INFO] [FC] - Getting list provision: gpu-best-practive-service gpu-best-practive: - serviceName: gpu-best-practive-service qualifier: LATEST functionName: gpu-porn-detection resource: 143199913651****#gpu-best-practive-service#LATEST#gpu-porn-detection target: 2 current: 2 scheduledActions: null targetTrackingPolicies: - name: scaling-policy-demo startTime: 2023-01-01T16:00:00.000Z endTime: 2024-01-01T16:00:00.000Z metricType: ProvisionedConcurrencyUtilization metricTarget: 0.3 minCapacity: 2 maxCapacity: 30 currentError: alwaysAllocateCPU: true
在预留实例拉起成功后,您的模型已成功部署并准备好进行服务。
释放函数预留实例。
执行以下命令关闭弹性规则,将预留实例配置为0。
sudo s provision put --target 0 --qualifier LATEST -t s.yaml -a {access}
执行以下命令确认当前函数的弹性伸缩策略已被关闭。
s provision list -a {access}
返回以下执行结果,表示弹性伸缩策略已成功关闭。
[2023-05-10 14:54:46] [INFO] [FC] - Getting list provision: gpu-best-practive-service End of method: provision
通过函数计算控制台配置GPU实例的弹性伸缩策略
前提条件
已创建函数计算的服务和GPU函数。具体操作,请参见创建服务和创建GPU函数。
操作步骤
- 登录函数计算控制台,在左侧导航栏,单击服务及函数。
开启目标服务的实例级别指标。具体操作,请参见配置实例级别指标。
开启实例级别指标后,您可以在函数计算控制台的函数可观测页面查看到函数调用所消耗的GPU相关资源。
单击目标函数,然后单击触发器管理(URL)页签,获取HTTP触发器的URL用于后续测试函数。
测试函数,并登录函数计算控制台查看监控结果。
执行Curl命令测试函数,使用上一步获取的URL。
curl https://gpu-poretection-gpu-bes-service-gexsgx****.cn-shanghai.fcapp.run/invoke -H "Content-Type: text/plain" --data "Nice to meet you"
返回以下结果,表示测试通过。
[{"text": "Nice to meet you", "porn_detection_label": 0, "porn_detection_key": "not_porn", "porn_probs": 0.0, "not_porn_probs": 1.0}]%
在函数计算控制台,选择 ,依次单击步骤2部署的服务和函数,然后单击实例指标页签,查看GPU相关指标的变化。
在函数详情页面的弹性管理页签,单击创建规则。
在创建弹性伸缩限制规则页面,按需设置以下配置项,然后单击创建。
设置版本和最小实例数,其他配置项保持默认值即可。
在根据指标修改限制区域,单击+添加配置,然后设置相关策略配置。
示例如下。
设置完成后,您可以在目标函数的
,查看函数预留实例数的变化。
后续如果没有使用预留模式GPU实例的需求,请及时删除添加的预留实例。
执行压测
您还可以使用常用的压测工具对HTTP函数进行压测,例如Apache Bench压测工具。也可以使用阿里云的性能测试 PTS产品进行测试。使用PTS产品进行压测,将产生额外费用,具体信息,请参见计费概述。
压测结束后,在函数计算控制台,找到目标服务下的目标函数,然后在函数详情页选择 ,查看压测结果。根据指标详情,您可以看到在压测过程中函数预留实例数进行了自动扩容,并在压测结束后自动缩容,如下图所示。
常见问题
使用函数计算实时推理场景的成本如何计算?
关于函数计算的计费详情,请参见计费概述。预留模式区别于按量模式,请注意您的账单详情。
为什么我配置了弹性伸缩策略,还是可以看到性能毛刺?
可以考虑使用更为激进的弹性伸缩策略,提早弹出节点来规避突发请求带来的性能挤兑。
为什么我所追踪的指标已经上涨超过所配置的弹性策略水位,但是没有看到实例数增长?
函数计算统计的指标是分钟级别,水位需要上涨并维持一段时间后,才会触发扩容机制。