すべてのプロダクト
Search
ドキュメントセンター

Function Compute:画像処理のベストプラクティス

最終更新日:Sep 09, 2024

Function Computeコンソール、SDK、またはServerless Devsを使用して、GPU高速化インスタンスのベストプラクティスを体験できます。 このトピックでは、Serverless DevsまたはFunction Computeコンソールを使用して、関数コードを使用してエッジ検出を実行してrawイメージを処理する方法について説明します。 このトピックでは、Pythonを例として使用します。

シナリオと利点

このセクションでは、Function ComputeにGPUアクセラレーションがないインスタンスと比較した、GPUアクセラレーションインスタンスの利点について説明します。

  • リアルタイムおよび準リアルタイムのアプリケーションシナリオ

    • GPU高速化されたインスタンスは、グラフィックスとイメージを数倍高速に処理し、より効率的な方法でプロダクションコンテンツをユーザーにプッシュできます。

  • コスト優先の画像処理シナリオ

    • ビジネス要件に基づいてGPU高速化インスタンスを予約します。 このように、Function ComputeのGPU高速化インスタンスは、自作GPUクラスターよりもはるかに高いコスト効率を提供します。

    • GPU仮想化テクノロジを使用して、1/2モードまたは排他モードでGPUリソースを使用します。 このようにして、GPU高速化インスタンスをきめ細かく構成できます。

  • 効率優先の画像処理シナリオ

    • ドライバーとCUDAのバージョン管理、マシンの運用管理、欠陥のあるGPU管理など、GPUクラスターでO&Mを実行することなく、コード開発とビジネス目標に焦点を当てます。

GPU高速化インスタンスの詳細については、「インスタンスタイプとインスタンスモード」をご参照ください。

チュートリアルの説明

次の表は、Function Computeでソースイメージ (左) でエッジ検出を実行して新しいイメージ (右) を生成する例を示しています。

ソースイメージ

新しい画像エッジ検出

image_processing_example

image_processing_result_example

準備

  • OpenCVをコンパイルします。

    OpenCVは、GPUアクセラレーションを使用する前にコンパイルする必要があります。 次の項目では、OpenCVのコンパイル方法について説明します。

    • (推奨) Dockerを使用してコンパイル済みOpenCVを使用する。 ダウンロードアドレス: opencv-cuda-dockerまたはcuda-opencv

    • OpenCVを手動でコンパイルします。 詳細については、「コンパイルガイド」をご参照ください。

  • 処理するオーディオおよびビデオリソースを、GPUアクセラレーションインスタンスが配置されているリージョンのObject Storage Service (OSS) バケットにアップロードします。 バケット内のオブジェクトに対する読み取りおよび書き込み権限があることを確認してください。 オーディオおよびビデオリソースをアップロードする方法の詳細については、「オブジェクトのアップロード」をご参照ください。 権限の詳細については、「バケットのACLの変更」をご参照ください。

Serverless Devsを使用してGPUアプリケーションをデプロイする

あなたが始める前に

手順

  1. プロジェクトを作成します。

    s init devsapp/start-fc-custom-container-event-python3.9 -d fc-gpu-prj

    次のサンプルコードは、作成されたプロジェクトのディレクトリを示しています。

    fc-gpu-prj
    ├── code
    │   ├── app.py        # Function code.
    │   └── Dockerfile    # Dockerfile: The image Dockerfile that contains the code.
    ├── README.md
    └── s.yaml            # Project configurations, which specify how the image is deployed in Function Compute

    でのイメージのデプロイ方法を指定するプロジェクト設定

  2. プロジェクトディレクトリに移動します。

    cd fc-gpu-prj
  3. ビジネス要件に基づいてディレクトリファイルの設定を変更します。

    • 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. Make sure that the namespace:demo namespace and the repo:gpu-opencv-canny_s repository are created in advance in Alibaba Cloud Container Registry. 
                #2. Change the tag from v0.1 to v0.2 when you update the function later and run s build && s deploy again. 
                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"
      
              # Use the path of the OSS object in your Alibaba Cloud account. You must have the read and write permissions on the object. 
              # Download the source image from your 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)
              # Use the path of the OSS object in your Alibaba Cloud account. You must have the read and write permissions on the object. 
              # Upload the new image after edge detection to the OSS bucket. Note that the name of the new image cannot be the same as the name of the source image. 
              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
  4. イメージを作成します。

    s build --dockerfile ./code/Dockerfile
  5. コードをFunction Computeにデプロイします。

    s deploy
    説明

    上記のコマンドを繰り返し実行し、サービス名と関数名を変更しない場合は、use localコマンドを実行してローカル設定を使用します。

  6. プロビジョニング済みインスタンスの設定

    s provision put --target 1 --qualifier LATEST
  7. プロビジョニング済みインスタンスの準備ができているかどうかを確認します。

    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: []
  8. 関数を呼び出します。

    • オンライン版を見る

      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 # View the file to check the result of edge detection. 
      FC Invoke Result:
      {"result": "CUDA-capable device supported | process image ok!"}
  9. GPU高速化インスタンスをリリースします。

    s provision put --target 0 --qualifier LATEST

Function Computeコンソールを使用してGPUアプリケーションをデプロイする

  1. イメージを展開します。

    1. Container Registry Enterprise EditionインスタンスまたはContainer Registry Personal Editionインスタンスを作成します。

      Enterprise Editionインスタンスを作成することを推奨します。 詳細については、「Container Registry Enterprise Editionインスタンスの作成」をご参照ください。

    2. 名前空間とイメージリポジトリを作成します。

      詳細については、「Container Registry Enterprise Editionインスタンスを使用してイメージを構築する」トピックの「手順2: 名前空間の作成」および手順3: イメージリポジトリの作成」をご参照ください。

    3. Container Registryコンソールのプロンプトに従って、Dockerで操作を実行します。 次に、前述のサンプルapp.pyDockerfileをインスタンスイメージリポジトリにプッシュします。 ファイルの詳細については、Serverless Devsを使用してGPUアプリケーションをデプロイする場合、/codeディレクトリのapp.pyおよびDockerfileをご参照ください。

      db-acr-docker

  2. サービスを作成します。 詳細については、「サービスの管理」セクションの「サービスの作成」セクションをご参照ください。

  3. 関数を作成します。 詳細については、「カスタムコンテナー関数の作成」をご参照ください。

    説明

    [インスタンスタイプ][GPUインスタンス][リクエストハンドラタイプ][HTTPリクエストの処理] を選択します。

  4. 関数の実行タイムアウト時間を変更します。

    1. 管理する機能を見つけてクリックします設定で、アクション列を作成します。

    2. では、環境変数セクションの値を変更します。実行タイムアウト期間をクリックし、保存をクリックします。

      db-gpu-time

    説明

    CPUを使用したトランスコード時間は、デフォルト値の60秒を超えています。 したがって、[実行タイムアウト期間] の値をより大きな値に設定することを推奨します。

  5. プロビジョニングされたGPU高速化インスタンスを設定します。

    1. 関数の詳細ページで、自動スケーリングタブをクリックし、ルールの作成をクリックします。

    2. 表示されるページで、次のパラメーターを設定してGPUアクセラレーションインスタンスをプロビジョニングし、作成をクリックします。

      プロビジョニング済みインスタンスの設定方法の詳細については、「プロビジョニング済みインスタンスと自動スケーリングルールの設定」をご参照ください。db-fc-yuliu

    設定が完了したら、プロビジョニングされたGPUアクセラレーションインスタンスの準備ができているかどうかをルールリストで確認できます。 具体的には、Current Reserved Instancesの値が指定されたプロビジョニング済みインスタンスの数であるかどうかを確認します。

  6. cURLを使用して関数をテストします。

    1. 関数の詳細ページで、トリガータブでトリガー設定を表示し、トリガーエンドポイントを取得します。

    2. CLIで次のコマンドを実行して、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

このドメイン名は例として使用されます。 実際のドメイン名が優先されます。