您可以通過Function Compute控制台、SDK或Serverless Devs來體驗GPU執行個體的最佳實務。本文以Python語言為例,說明如何使用Serverless Devs開發工具或通過控制台,將原始映像經過函數代碼處理,實現邊緣檢測。
應用情境與優勢
在不同的應用情境下,Function Compute提供的GPU執行個體與CPU相比所具備的優勢如下。
即時、准即時的應用情境
提供數倍於CPU的圖形影像處理效率,從而快速將生產內容推向終端使用者。
成本優先的影像處理情境
提供彈性預留模式,從而按需為客戶保留GPU工作執行個體,對比自建GPU叢集擁有較大成本優勢。
提供GPU共用虛擬化,支援以1/2、獨佔方式使用GPU,允許業務以更精細化的方式配置GPU執行個體。
效率優先的影像處理情境
屏蔽營運GPU叢集的繁重負擔(驅動/CUDA版本管理、機器運行管理、GPU壞卡管理),使得開發人員專註於代碼開發、聚焦營運目標的達成。
GPU執行個體的更多資訊,請參見執行個體類型及使用模式。
教程樣本說明
如下表所示,左列為原圖,右列是經過部署在Function Compute的邊緣檢測函數代碼處理後,所產生的圖片。
原始映像 | 邊緣檢測結果 |
準備工作
編譯OpenCV。
OpenCV需要自行編譯以使用GPU加速,編譯方式如下:
(推薦)通過Docker使用已編譯好的OpenCV。下載地址:opencv-cuda-docker或cuda-opencv
自行編譯。具體步驟,請參見官網編譯手冊。
將需處理的音視頻資源上傳至在GPU執行個體所在地區的OSS Bucket中,且您對該Bucket中的檔案有讀寫權限。具體步驟,請參見控制台上傳檔案。許可權相關說明,請參見修改儲存空間讀寫權限。
通過ServerlessDevs部署GPU應用
前提條件
在GPU執行個體所在地區,完成以下操作:
建立Container Registry的企業版執行個體或個人版執行個體,推薦您建立企業版執行個體。具體操作步驟,請參見建立企業版執行個體。
建立命名空間鏡像倉庫。具體操作步驟,請參見步驟二:建立命名空間和步驟三:建立鏡像倉庫。
操作步驟
建立專案。
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 # 專案配置:包含了鏡像如何部署在Function Compute
進入專案所在目錄。
cd fc-gpu-prj
按實際情況修改目錄檔案的參數配置。
編輯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 instanceType: fc.gpu.tesla.1 gpuMemorySize: 8192 cpu: 4 memorySize: 16384 diskSize: 512 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
部署代碼至Function Compute。
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
通過Function Compute控制台部署GPU應用
部署鏡像。
建Container Registry的企業版執行個體或個人版執行個體。
推薦您建立企業版執行個體。具體操作步驟,請參見建立企業版執行個體。
建立命名空間和鏡像倉庫。
具體操作步驟,請參見步驟二:建立命名空間和步驟三:建立鏡像倉庫。
在Container Registry控制台,根據介面提示完成Docker相關操作步驟。然後將上述樣本app.py和Dockerfile推送至執行個體鏡像倉庫,檔案資訊,請參見通過ServerlessDevs部署GPU應用時/code目錄中的app.py和Dockerfile。
建立服務。具體操作步驟,請參見建立服務。
建立函數。具體操作步驟,請參見建立Custom Container函數。
說明執行個體類型選擇GPU執行個體,請求處理常式類型選擇處理 HTTP 要求。
修改函數的執行逾時時間。
單擊目標服務下目標函數右側操作列的配置。
在環境資訊地區,修改執行逾時時間,然後單擊儲存。
說明CPU轉碼耗時會超過預設的60s,因此建議您修改執行逾時時間為較大的值。
配置GPU預留執行個體。
在函數詳情頁面,單擊彈性管理頁簽,然後單擊建立規則。
在建立Auto Scaling限制規則頁面,按需配置參數,預留GPU執行個體,然後單擊建立。
關於配置預留執行個體的具體操作,請參見配置Auto Scaling規則。
配置完成後,您可以在規則列表查看預留的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
本網域名稱僅為樣本,需以實際情況為準。