本文介绍如何通过Serverless Devs工具基于异步任务调用GPU函数,并将调用结果自动回调至配置的异步目标函数。
背景信息
GPU实例
随着机器学习,特别是深度学习的广泛应用,大量向量、矩阵、张量运算所产生的算力需求,包括训练场景对高精度计算的需求,以及推理场景对低精度计算的需求,传统CPU俨然已无法胜任。2007年英伟达推出可编程通用计算平台CUDA框架,大量的科研人员和开发者将大量算法进行改写,从而获得几十至几千倍的加速效果。在机器学习的趋势来临后,GPU更是成为各类工具、算法、框架的基础底层设施之一。
2021年云栖大会,阿里云函数计算正式推出基于Turing架构的GPU实例,使得Serverless开发者可以将AI训练与推理的业务负载下沉到GPU硬件加速,从而加快模型训练、推理服务的效率。
异步任务
函数计算提供异步任务的分发、执行和观测的全栈能力,使得您只需要专注于任务处理逻辑的编写,创建任务处理函数,然后提交任务。函数计算不但提供异步任务日志、指标以及各个处理阶段耗时统计等丰富的可观测能力,也提供实例自动弹性伸缩、任务去重、指定任务终止以及批量任务暂停、恢复和删除等功能。更多信息,请参见异步任务。
应用场景
在面向非实时、偏离线的AI推理场景、AI训练场景和音视频生产场景,基于异步任务调用GPU函数,使得开发者可以聚焦于业务本身,缩短业务达成路径。具体实现如下。
提供GPU虚拟化,支持以1/8、1/4、1/2或独占方式使用GPU,允许业务以更精细化的方式配置GPU实例。
提供异步管理、任务去重、任务监控、任务重试、事件触发、结果回调和任务编排等一系列成熟的异步任务处理能力。
屏蔽运维GPU集群的繁重负担,包括驱动以及CUDA版本管理、机器运行管理和GPU坏卡管理等,使得开发者专注于代码开发,聚焦于业务目标的达成。
实现原理
本文以部署一个GPU函数tgpu_basic_func
、异步调用成功回调函数async-callback-succ-func
和异步调用失败回调函数async-callback-fail-func
为例,介绍异步调用GPU函数并实现结果回调的功能原理。函数具体信息,如下表所示。
函数名称 | 函数说明 | 运行环境 | 实例类型 | 触发类型 |
tgpu_basic_func | 基于函数计算的GPU实例,运行AI准实时任务、AI离线任务等。 | Custom Container | GPU实例 | HTTP函数 |
async-callback-succ-func | 任务执行成功后的目标回调函数。 | Python 3 | CPU实例 | 事件函数 |
async-callback-fail-func | 任务执行失败后的目标回调函数。 | Python 3 | CPU实例 | 事件函数 |
实现原理简单概括如下图。
前提条件
步骤一:部署成功回调函数
初始化项目。
s init devsapp/start-fc-event-python3 -d async-succ-callback
创建的项目目录如下所示。
├── async-succ-callback │ ├── code │ │ └── index.py │ └── s.yaml
进入项目所在目录。
cd async-succ-callback
按照实际情况修改目录文件中的参数配置。
编辑
s.yaml
文件。示例如下。edition: 1.0.0 name: hello-world-app # access是当前应用所需要的密钥信息配置: # 密钥配置请参见:https://www.serverless-devs.com/serverless-devs/command/config # 密钥使用请参见:https://www.serverless-devs.com/serverless-devs/tool access: "default" vars: # 全局变量 region: "cn-shenzhen" services: helloworld: # 业务名称/模块名称 component: fc props: region: ${vars.region} service: name: "async-callback-service" description: 'async callback service' # logConfig配置文档:https://gitee.com/devsapp/fc/blob/main/docs/zh/yaml/service.md#logconfig logConfig: project: tgpu-prj-sh # 建议配置,用于查看请求日志,需要在SLS日志服务中提前创建相应的project logstore: tgpu-logstore-sh # 建议配置,用于查看请求日志,需要在SLS日志服务中提前创建相应的logstore enableRequestMetrics: true enableInstanceMetrics: true logBeginRule: DefaultRegex function: name: "async-callback-succ-func" description: 'async callback succ func' runtime: python3 codeUri: ./code handler: index.handler memorySize: 128 timeout: 60
编辑
index.py
文件。示例如下:# -*- coding: utf-8 -*- import logging # To enable the initializer feature # please implement the initializer function as below: # def initializer(context): # logger = logging.getLogger() # logger.info('initializing') def handler(event, context): logger = logging.getLogger() logger.info('hello async callback succ') return 'hello async callback succ'
部署代码至函数计算。
s deploy
您可以在函数计算控制台查看部署成功的函数。
本地调用调试函数。
s invoke
调用完成后,返回结果
hello async callback succ
。
步骤二:部署失败回调函数
初始化项目。
s init devsapp/start-fc-event-python3 -d async-fail-callback
创建的项目目录如下所示。
├── async-fail-callback │ ├── code │ │ └── index.py │ └── s.yaml
进入项目所在目录。
cd async-fail-callback
按照实际情况修改目录文件中的参数配置。
编辑
s.yaml
文件。示例如下:edition: 1.0.0 name: hello-world-app # access是当前应用所需要的密钥信息配置: # 密钥配置请参见:https://www.serverless-devs.com/serverless-devs/command/config # 密钥使用请参见:https://www.serverless-devs.com/serverless-devs/tool access: "default" vars: # 全局变量 region: "cn-shenzhen" services: helloworld: # 业务名称/模块名称 component: fc props: region: ${vars.region} service: name: "async-callback-service" description: 'async callback service' # logConfig配置文档:https://gitee.com/devsapp/fc/blob/main/docs/zh/yaml/service.md#logconfig logConfig: project: tgpu-prj-sh # 建议配置,用于查看请求日志,需要在SLS日志服务中提前创建相应的project logstore: tgpu-logstore-sh # 建议配置,用于查看请求日志,需要在SLS日志服务中提前创建相应的logstore enableRequestMetrics: true enableInstanceMetrics: true logBeginRule: DefaultRegex function: name: "async-callback-fail-func" description: 'async callback fail func' runtime: python3 codeUri: ./code handler: index.handler memorySize: 128 timeout: 60
编辑
index.py
文件。示例如下:# -*- coding: utf-8 -*- import logging # To enable the initializer feature # please implement the initializer function as below: # def initializer(context): # logger = logging.getLogger() # logger.info('initializing') def handler(event, context): logger = logging.getLogger() logger.info('hello async callback fail') return 'hello async callback fail'
部署代码至函数计算。
s deploy
您可以在函数计算控制台查看部署成功的函数。
本地调用调试函数。
s invoke
调用完成后,返回结果
hello async callback fail
。
步骤三:部署GPU函数
创建项目目录。
mkdir fc-gpu-async-job&&cd fc-gpu-async-job
按照以下目录结构创建文件并根据实际情况修改文件中的参数配置。
目录结构如下所示。
├── fc-gpu-async-job ├── code │ ├── app.py │ └── Dockerfile └── s.yaml
编辑s.yaml文件。示例如下:
edition: 1.0.0 name: gpu-container-demo # access是当前应用所需要的密钥信息配置: # 密钥配置请参见:https://www.serverless-devs.com/serverless-devs/command/config # 密钥使用顺序请参见:https://www.serverless-devs.com/serverless-devs/tool access: default vars: region: cn-shenzhen services: customContainer-demo: component: devsapp/fc props: region: ${vars.region} service: name: tgpu_basic_service internetAccess: true # logConfig配置文档:https://gitee.com/devsapp/fc/blob/main/docs/zh/yaml/service.md#logconfig logConfig: project: aliyun**** # 建议配置,用于查看请求日志,需要在SLS日志服务中提前创建相应的project logstore: func**** # 建议配置,用于查看请求日志,需要在SLS日志服务中提前创建相应的logstore enableRequestMetrics: true enableInstanceMetrics: true logBeginRule: DefaultRegex function: name: tgpu_basic_func description: test gpu basic handler: not-used timeout: 600 caPort: 9000 # 业务可根据实际显存占用,选择合适的GPU实例规格;如下例子展示1/8 GPU虚拟化规格 instanceType: fc.gpu.tesla.1 gpuMemorySize: 2048 cpu: 1 memorySize: 4096 diskSize: 512 instanceConcurrency: 1 runtime: custom-container customContainerConfig: # 填写您的镜像信息。需要提前创建ACR个人版或企业版实例,并创建相应的命名空间与镜像仓库 image: registry.cn-shenzhen.aliyuncs.com/my****/my**** # 开启镜像加速,对于GB级别镜像有非常好的冷启动优化效果 accelerationType: Default codeUri: ./code # 异步配置 # 详细见:https://gitee.com/devsapp/fc/blob/main/docs/zh/yaml/function.md#asyncconfiguration asyncConfiguration: destination: # 填写您创建的失败回调函数的ARN onFailure: "acs:fc:cn-shenzhen:164901546557****:services/async-callback-service.LATEST/functions/async-callback-fail-func" # 填写您创建的成功回调函数的ARN onSuccess: "acs:fc:cn-shenzhen:164901546557****:services/async-callback-service.LATEST/functions/async-callback-succ-func" statefulInvocation: true triggers: - name: httpTrigger type: http config: authType: anonymous methods: - GET
编辑Dockerfile文件。示例如下:
FROM nvidia/cuda:11.0-base FROM ubuntu WORKDIR /usr/src/app RUN apt-get update RUN apt-get install -y python3 COPY . . CMD [ "python3", "-u", "/usr/src/app/app.py" ] EXPOSE 9000
编辑app.py文件。示例如下:
# -*- coding: utf-8 -*- # python2 and python3 from __future__ import print_function from http.server import HTTPServer, BaseHTTPRequestHandler import json import sys import logging import os import time host = ('0.0.0.0', 9000) class Resquest(BaseHTTPRequestHandler): def do_GET(self): print("simulate long execution scenario, sleep 10 seconds") time.sleep(10) print("show me GPU info") msg = os.popen("nvidia-smi -L").read() data = {'result': msg} self.send_response(200) self.send_header('Content-type', 'application/json') self.end_headers() self.wfile.write(json.dumps(data).encode()) if __name__ == '__main__': server = HTTPServer(host, Resquest) print("Starting server, listen at: %s:%s" % host) server.serve_forever()
部署代码至函数计算。
s deploy
您可以在函数计算控制台查看部署成功的GPU函数,以及该函数的异步配置。
本地调用调试函数。
s invoke
调用完成后,返回结果
Hello, World!
。提交异步任务。
查看GPU函数的镜像加速准备状态。
建议镜像加速准备状态为可用后,再发起异步任务,否则可能会引起链路超时等异常问题。
登录函数计算控制台,找到已创建的GPU函数
tgpu_basic_func
,在异步任务列表页签,单击提交任务。
执行完成后,任务状态为执行成功。
此时,您可以找到配置的成功回调函数
async-callback-succ-func
,依次选择 页签,然后找到本次异步请求结果行,查看调用结果是否为调用成功。
更多信息
更多关于GPU函数的最佳实践,请参见Serverless GPU应用模板案例。