文档

实时推理场景

更新时间:

本文介绍如何使用GPU预留实例,以及如何基于GPU预留实例构建延迟敏感的实时推理服务。

背景信息

场景介绍

在实时推理应用场景中,工作负载具有以下一个或多个特征。

  • 低延迟

    单次请求的处理时效性要求高,RT(Response Time)延迟要求严格,90%的长尾延时普遍在百毫秒级别。

  • 主链路

    普遍位于业务核心链路,推理成功率要求高,不接受长时间重试。示例如下。

    • 开屏广告推荐/首页产品推荐:根据用户的行为喜好,在应用开屏时进行用户行为的推荐,并实时地展现在用户终端上。

    • 实时流程媒体生产:在互动连麦、直播带货、超低延时播放等场景下,音视频流均需要以极低的延迟在端到端之间进行传播,AI视频超分、AI视频识别的实时性需要保证。

  • 峰波峰谷

    业务流量具有明显的潮汐特征,普遍与终端用户使用习惯高度相关。

  • 资源利用率

    由于GPU资源规划普遍根据业务高峰评估,峰谷时存在较大资源浪费,资源利用率普遍低于30%。

功能优势

函数计算为实时推理工作负载提供以下功能优势。

  • 预留GPU实例

    函数计算平台提供了默认的按量GPU实例之外的另一种GPU使用方式——预留GPU实例。如果您希望消除冷启动延时的影响,满足实时推理业务低延迟响应的要求,可以通过配置预留GPU实例来实现。更多关于预留模式的信息,请参见实例类型及使用模式

  • 预留GPU实例的弹性伸缩策略(推荐)

    函数计算平台为预留GPU实例提供了多种指标的弹性伸缩策略,包括预留实例并发利用率、GPU SM利用率、GPU显存利用率、GPU 硬件编码器利用率和GPU 硬件解码器利用率,以及按时弹性伸缩策略,以满足实时推理业务在不同峰波峰谷下对GPU实例算力的供给要求,从而降低整体部署成本。

  • 服务质量优先,服务成本次优

    预留GPU实例的计费周期不同于按量GPU实例,预留GPU实例是以实例存活生命周期进行计费,因此,相较于按量GPU实例,总体使用成本较高。但相较于长期自建GPU集群,降本幅度达50%以上。并且预留GPU实例支持闲置模式,开启闲置模式后,预留的实例无请求时,平台会自动冻结其GPU资源,使其进入闲置状态,此时闲置GPU将按照更低的单价进行计费。

  • 规格最优

    函数计算平台提供的GPU实例规格,允许您根据自己的工作负载选择不同的卡型,独立配置CPU/GPU/MEM/DISK。最小GPU规格小至1 GB显存/算力,将为您提供最贴合业务的实例规格。

  • 突发流量支撑

    函数计算平台提供充足的GPU资源供给,当业务遭遇突发流量时,函数计算将以秒级弹性供给海量GPU算力资源,避免因GPU算力供给不足、GPU算力弹性滞后导致的业务受损。

功能原理

当GPU函数部署完成后,您可以通过配置预留GPU实例的弹性伸缩策略开启预留GPU实例,以提供实时推理应用场景所需的基础设施能力。函数计算平台将根据您配置的伸缩指标进行预留GPU实例的HPA,客户请求将优先分配至预留GPU实例进行推理服务,平台完全遮蔽冷启动,业务保持低延迟响应。

image

实时推理场景基本信息

容器支持

函数计算GPU场景下,当前仅支持以Custom Container(自定义容器运行环境)进行交付。关于Custom Container的使用详情,请参见Custom Container简介

Custom Container函数要求在镜像内携带Web Server,以满足执行不同代码路径、通过事件或HTTP触发函数的需求。适用于AI学习推理等多路径请求执行场景。

GPU实例规格

您可以在推理应用场景下,根据业务需要,特别是算法模型所需要的CPU算力、GPU算力与显存、内存、磁盘,选择不同的GPU卡型与GPU实例规格。关于GPU实例规格的详细信息,请参见实例规格

部署方式

您可以使用多种方式将您的模型部署在函数计算。

更多部署示例,请参见start-fc-gpu

预留模式的弹性伸缩

reserved-instance-elastic-scaling

定时修改弹性伸缩策略

函数计算支持使用定时修改弹性伸缩策略。具体操作,请参见配置预留实例。在实时推理场景中,如果您的流量波形呈现为较规律的潮汐流量,您可以在流量高峰来临前的若干分钟,进行预留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里的业务逻辑来进行模型服务预热。更多信息,请参见函数实例生命周期回调

  1. 在您构建的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"
  2. 在函数详情页面,选择配置 > 生命周期,然后单击编辑,配置实例生命周期回调信息。

    image.png

配置实时推理的弹性伸缩

通过Serverless Devs工具配置GPU弹性伸缩

前提条件

1.部署函数

  1. 执行以下命令,克隆工程。

    git clone https://github.com/devsapp/start-fc-gpu.git
  2. 执行以下命令,进入项目目录。

    cd /root/start-fc-gpu/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
  3. 执行以下命令,通过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 builddocker push命令。

  4. 编辑s.yaml文件。

    edition: 3.0.0
    name: container-demo
    access: default
    vars:
      region: cn-shanghai
    resources:
      gpu-best-practive:
        component: fc3
        props:
          region: ${vars.region}
          description: This is the demo function deployment
          handler: not-used
          timeout: 1200
          memorySize: 8192
          cpu: 2
          gpuMemorySize: 8192
          diskSize: 512
          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
            port: 9000
          internetAccess: true
          logConfig:
            enableRequestMetrics: true
            enableInstanceMetrics: true
            logBeginRule: DefaultRegex
            project: z****
            logstore: log****
          functionName: gpu-porn-detection
          gpuConfig:
            gpuMemorySize: 8192
            gpuType: fc.gpu.tesla.1
          triggers:
            - triggerName: httpTrigger
              triggerType: http
              triggerConfig:
                authType: anonymous
                methods:
                  - GET
                  - POST
  5. 执行以下命令,部署函数。

    sudo s deploy --skip-push true -t s.yaml

    执行成功后,在执行输出中返回一个URL地址,格式如https://gpu-poretection-****.cn-shanghai.fcapp.run,复制此地址用于后续测试函数。

2.测试函数并查看监控结果

  1. 执行Curl命令调用函数,格式如下,其中域名为上一步获取的URL。

    curl https://gpu-poretection-gpu-****.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-index-changes

3.配置弹性预留策略

  1. 在s.yaml文件所在目录下,创建弹性配置的模板provison.json

    示例如下。该模板使用了实例并发度作为追踪指标,最小实例数为2,最大实例数为30。

    {
      "targetTrackingPolicies": [
        {
          "name": "scaling-policy-demo",
          "startTime": "2024-07-01T16:00:00.000Z",
          "endTime": "2024-07-30T16:00:00.000Z",
          "metricType": "ProvisionedConcurrencyUtilization",
          "metricTarget": 0.3,
          "minCapacity": 2,
          "maxCapacity": 30
        }
      ]
    }
  2. 执行以下命令,进行弹性策略的部署。

    sudo s provision put --target 1 --targetTrackingPolicies ./provision.json --qualifier LATEST -t s.yaml -a {access}
  3. 执行sudo s provision list进行验证,可以看到如下输出。其中targetcurrent的数值相等,表示预留实例正确拉起,弹性规则部署正确。

    [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:                 1
        current:                1
        scheduledActions:       null
        targetTrackingPolicies:
          -
            name:         scaling-policy-demo
            startTime:    2024-07-01T16:00:00.000Z
            endTime:      2024-07-30T16:00:00.000Z
            metricType:   ProvisionedConcurrencyUtilization
            metricTarget: 0.3
            minCapacity:  2
            maxCapacity:  30
        currentError:
        alwaysAllocateCPU:      true

    在预留实例拉起成功后,您的模型已成功部署并准备好进行服务。

  4. 释放函数预留实例。

    1. 执行以下命令关闭弹性规则,将预留实例配置为0。

      sudo s provision put --target 0 --qualifier LATEST -t s.yaml -a {access}
    2. 执行以下命令确认当前函数的弹性伸缩策略已被关闭。

      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函数。具体操作,请参见创建Custom Container函数

操作步骤

  1. 登录函数计算控制台,左侧导航栏选择函数,选择地域,找到目标函数,开启目标函数的实例级别指标。

    image

  2. 在函数详情页面,选择配置 > 触发器,获取HTTP触发器的URL用于后续测试函数。

    image

  3. 执行Curl命令测试函数,然后在函数详情页面,选择监控 > 实例指标,查看GPU相关指标的变化。

    curl https://gpu-poretection****.cn-shanghai.fcapp.run/invoke -H "Content-Type: text/plain" --data "Nice to meet you"
  4. 在函数详情页面,选择配置 > 预留实例,然后单击创建预留实例数策略开始配置弹性预留策略。

    image

    设置完成后,您可以在目标函数的详情页,选择监控 > 函数指标,查看函数预留实例数的变化。

重要

后续如果没有使用预留模式GPU实例的需求,请及时删除添加的预留实例。

执行压测

配置完弹性伸缩策略后,您可以通过压测的方式查看弹性伸缩的效果。您可以使用常用的压测工具对HTTP函数进行压测,例如Apache Bench压测工具,也可以使用阿里云的性能测试 PTS产品进行测试。使用PTS产品进行压测,将产生额外费用,具体信息,请参见计费概述

压测结束后,在函数计算控制台,找到目标函数,然后在函数详情页选择监控 > 函数指标,查看压测结果。根据指标详情,您可以看到在压测过程中函数预留实例数进行了自动扩容,并在压测结束后自动缩容,如下图所示。

pressure-test

常见问题

使用函数计算实时推理场景的成本如何计算?

关于函数计算的计费详情,请参见计费概述。预留模式区别于按量模式,请注意您的账单详情。

为什么我配置了弹性伸缩策略,还是可以看到性能毛刺?

可以考虑使用更为激进的弹性伸缩策略,提前弹出节点来规避突发请求带来的性能挤兑。

为什么我所追踪的指标已经上涨超过所配置的弹性策略水位,但是没有看到实例数增长?

函数计算统计的指标是分钟级别,水位需要上涨并维持一段时间后,才会触发扩容机制。