您可以通过函数计算控制台、SDK或Serverless Devs来体验GPU实例的最佳实践。本文以Python语言为例,说明如何使用Serverless Devs开发工具或通过控制台,将原始图像经过函数代码处理,实现边缘检测。
应用场景与优势
在不同的应用场景下,函数计算提供的GPU实例与CPU相比所具备的优势如下:
- 实时、准实时的应用场景
- 提供数倍于CPU的图形图像处理效率,从而快速将生产内容推向终端用户。
- 成本优先的图像处理场景
- 提供弹性预留模式,从而按需为客户保留GPU工作实例,对比自建GPU集群拥有较大成本优势。
- 提供GPU共享虚拟化,支持以1/2、独占方式使用GPU,允许业务以更精细化的方式配置GPU实例。
- 效率优先的图像处理场景
GPU实例的更多信息,请参见实例类型及使用模式。
教程示例说明
如下表所示,左列为原图,右列是经过部署在函数计算的边缘检测函数代码处理后,所生成的图片。
原始图像 |
边缘检测结果 |
 |
 |
准备工作
- 为了确保您的业务正常进行,请加入钉钉用户群(钉钉群号:11721331),申请GPU实例的使用权限,同时提供以下信息。
- 组织名称,例如您所在的公司名称。
- 您的阿里云账号ID。
- 您期望使用GPU实例的地域,例如华南1(深圳)。
- 联系方式,例如您的手机号、邮箱或钉钉账号等。
- 您的镜像大小。
- 编译OpenCV。
OpenCV需要自行编译以使用GPU加速,编译方式如下:
- 将需处理的音视频资源上传至在GPU实例所在地域的OSS Bucket中,且您对该Bucket中的文件有读写权限。具体步骤,请参见上传文件。权限相关说明,请参见修改存储空间读写权限。
通过ServerlessDevs部署GPU应用
前提条件
操作步骤
- 创建项目。
s init devsapp/start-fc-custom-container-event-python3.9 -d fc-gpu-prj
创建的项目目录如下所示。
fc-gpu-prj
├── code
│ ├── app.py # 函数代码
│ └── Dockerfile # Dockerfile:将代码打包成镜像的Dockerfile
├── README.md
└── s.yaml # 项目配置:包含了镜像如何部署在函数计算
- 进入项目所在目录。
- 按实际情况修改目录文件的参数配置。
- 编辑s.yaml文件。
YAML文件的参数详解,请参见YAML规范。
edition: 1.0.0
name: container-demo
access: default
vars:
region: cn-shenzhen
services:
customContainer-demo:
component: devsapp/fc
props:
region: ${vars.region}
service:
name: tgpu_opencv_service
internetAccess: true
function:
name: tgpu_opencv_func
description: test gpu for opencv
handler: not-used
timeout: 600
caPort: 9000
memorySize: 16384
gpuMemorySize: 8192
instanceType: g1
runtime: custom-container
customContainerConfig:
# 1. 请检查阿里云ACR容器镜像仓库已提前创建相应的命名空间(namespace:demo)与仓库(repo:gpu-opencv-canny_s)。
# 2. 后续更新函数时,请修改此处的tag,由v0.1修改为v0.2后,重新执行s build && s deploy。
image: registry.cn-shenzhen.aliyuncs.com/demo/gpu-opencv-canny_s:v0.1
codeUri: ./code
triggers:
- name: httpTrigger
type: http
config:
authType: anonymous
methods:
- GET
- 编辑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 numpy as np
import cv2
import urllib.request
class MyRequest(BaseHTTPRequestHandler):
def download(self, url, path):
print("enter download:", url)
f = urllib.request.urlopen(url)
with open(path, "wb") as local_file:
local_file.write(f.read())
def upload(self, url, path):
print("enter upload:", url)
headers = {
'Content-Type': 'application/octet-stream',
'Content-Length': os.stat(path).st_size,
}
req = urllib.request.Request(url, open(path, 'rb'), headers=headers, method='PUT')
urllib.request.urlopen(req)
def core(self):
msg = ""
mode = ""
if not cv2.cuda.getCudaEnabledDeviceCount():
msg = "No CUDA-capable device is detected |"
mode = "Mat"
else:
msg = "CUDA-capable device supported |"
mode = "UMat"
# 需替换为您个人阿里云账号下的OSS,且您有可读写的权限。
# 此处是从OSS Bucket中下载您已存储的原始图片。
path = "/tmp/target.jpg"
self.download("https://your_public_oss/f.png", path)
img = cv2.imread(path)
if mode=='UMat':
img = cv2.UMat(img)
img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
img = cv2.GaussianBlur(img, (7, 7), 1.5)
img = cv2.Canny(img, 0, 50)
if type(img) == 'cv2.UMat':
img = cv2.UMat.get(img)
cv2.imwrite(path, img)
# 需替换为您个人阿里云账号下的OSS,且您有可读写的权限。
# 此处是向OSS Bucket中上传经过处理后的边缘检测结果图片,请注意图片名称与原图名称不能重合。
self.upload("https://your_public_oss/target.jpg", path)
msg = msg + " process image ok!"
data = {'result': msg}
self.send_response(200)
self.send_header('Content-type', 'application/json')
self.end_headers()
self.wfile.write(json.dumps(data).encode())
def pong(self):
data = {"function":"opencv_edge_canny"}
self.send_response(200)
self.send_header('Content-type', 'application/json')
self.end_headers()
self.wfile.write(json.dumps(data).encode())
def dispatch(self):
mode = self.headers.get('RUN-MODE')
if mode == "ping":
self.pong()
elif mode == "normal":
self.core()
else:
self.pong()
def do_GET(self):
self.dispatch()
def do_POST(self):
self.dispatch()
if __name__ == '__main__':
host = ('0.0.0.0', 9000)
server = HTTPServer(host, MyRequest)
print("Starting server, listen at: %s:%s" % host)
server.serve_forever()
- 编辑Dockerfile文件。
示例如下:
FROM registry.cn-shanghai.aliyuncs.com/serverless_devs/opencv-cuda:cuda-10.2-opencv-4.2
WORKDIR /usr/src/app
RUN apt-get install -y build-essential
RUN apt-get install -y python3
COPY . .
CMD [ "python3", "-u", "/usr/src/app/app.py" ]
EXPOSE 9000
- 构建镜像。
s build --dockerfile ./code/Dockerfile
- 部署代码至函数计算。
s deploy
说明 服务名称和函数名称不变,重复执行以上命令时,请选择本地配置,即use local
。
- 配置预留模式的实例。
s provision put --target 1 --qualifier LATEST
- 查询预留模式的实例是否就绪。
s provision get --qualifier LATEST
如果查询到current
参数为1,则说明GPU实例的预留模式已就绪,示例如下。
[2021-11-01T13:43:28.308] [INFO ] [S-CLI] - Start ...
[2021-11-01T13:43:28.521] [INFO ] [FC] - Getting provision: tgpu_opencv_service.LATEST/tgpu_opencv_func
customContainer-demo:
serviceName: tgpu_opencv_service
functionName: tgpu_opencv_func
qualifier: LATEST
resource: 188077086902****#tgpu_opencv_service#LATEST#tgpu_opencv_func
target: 1
current: 1
scheduledActions: []
targetTrackingPolicies: []
- 调用函数。
- 查看线上版本
FC Invoke Result:
{"function": "opencv_edge_canny"}
- 执行图片边缘检测
s invoke -e '{"method":"GET","headers":{"RUN-MODE":"normal"}}'
enter download: https://your_public_oss/c1.png
enter upload: https://your_public_oss/target.jpg # 查看该文件确认边缘检测结果。
FC Invoke Result:
{"result": "CUDA-capable device supported | process image ok!"}
- 释放GPU实例。
s provision put --target 0 --qualifier LATEST
通过函数计算控制台部署GPU应用
- 部署镜像。
- 建容器镜像服务的企业版实例或个人版实例。
- 创建命名空间和镜像仓库。
- 在容器镜像服务控制台,根据界面提示完成Docker相关操作步骤。然后将上述示例app.py和Dockerfile推送至实例镜像仓库,文件信息,请参见通过ServerlessDevs部署GPU应用时/code目录中的app.py和Dockerfile。
- 创建服务。具体操作步骤,请参见创建服务。
- 创建函数。具体操作步骤,请参见创建Custom Container函数。
说明 实例类型选择GPU实例,请求处理程序类型选择处理 HTTP 请求。
- 修改函数的执行超时时间。
- 单击目标服务下目标函数右侧操作列的配置。
- 在环境信息区域,修改执行超时时间,然后单击保存。
说明 CPU转码耗时会超过默认的60s,因此建议您修改执行超时时间为较大的值。
- 配置GPU预留实例。
- 在函数详情页面,单击弹性管理页签,然后单击创建规则。
- 在创建弹性伸缩限制规则页面,按需配置参数,预留GPU实例,然后单击创建。
配置完成后,您可以在规则列表查看预留的GPU实例是否就绪。即当前预留实例数是否为设置的预留实例数。
- 使用cURL测试函数。
- 在函数详情页面,单击触发器管理页签,查看触发器的配置信息,获取触发器的访问地址。
- 在命令行执行如下命令,调用GPU函数。
- 查看线上函数版本
curl "https://tgpu-op-console-tgpu-op-console-ajezokddpx.cn-shenzhen.fcapp.run"
{"function": "opencv_edge_canny"}
- 执行图片边缘检测
curl "https://tgpu-op-console-tgpu-op-console-ajezokddpx.cn-shenzhen.fcapp.run" -H "RUN-MODE: normal"
{"result": "CUDA-capable device supported | process image ok!"}
执行结果
您可通过在浏览器中访问以下域名,查看经过边缘检测处理后的图片:https://cri-zfen7xhpsx******-registry.oss-cn-shenzhen.aliyuncs.com/cats2.png
本域名仅为示例,需以实际情况为准。