全部產品
Search
文件中心

Platform For AI:Triton Inference Server鏡像部署

更新時間:Aug 03, 2024

Triton Inference Server是一個適用於深度學習與機器學習模型的推理服務引擎,支援將TensorRT、TensorFlow、PyTorch或ONNX等多種AI架構的模型部署為線上推理服務,並支援多模型管理、自訂backend等功能。本文為您介紹如何通過鏡像部署的方式部署Triton Inference Server模型服務。

部署服務:單模型

  1. 在OSS儲存空間中建立模型儲存目錄,並根據模型儲存目錄格式要求配置模型檔案與設定檔。具體操作請參見管理目錄

    每個模型目錄下都至少包含一個模型版本目錄和一個模型設定檔:

    • 模型版本目錄:包含模型檔案,且必須以數字命名,作為模型版本號碼,數字越大版本越新。

    • 模型設定檔:用於提供模型的基礎資訊,通常命名為config.pbtxt

    假設模型儲存目錄在oss://examplebucket/models/triton/路徑下,模型儲存目錄的格式如下:

    triton
    └──resnet50_pt
        ├── 1
        │   └── model.pt
        ├── 2
        │   └── model.pt
        ├── 3
        │   └── model.pt
        └── config.pbtxt

    其中:config.pbtxt 為設定檔,檔案內容樣本如下:

    name: "resnet50_pt"
    platform: "pytorch_libtorch"
    max_batch_size: 128
    input [
      {
        name: "INPUT__0"
        data_type: TYPE_FP32
        dims: [ 3, -1, -1 ]
      }
    ]
    output [
      {
        name: "OUTPUT__0"
        data_type: TYPE_FP32
        dims: [ 1000 ]
      }
    ]
    
    # 使用GPU推理
    # instance_group [
    #   { 
    #     kind: KIND_GPU
    #   }
    # ]
    
    # 模型版本配置
    # version_policy: { all { }}
    # version_policy: { latest: { num_versions: 2}}
    # version_policy: { specific: { versions: [1,3]}}

    config.pbtxt檔案中關鍵配置說明如下:

    參數

    是否必選

    描述

    name

    預設為模型儲存目錄名。如果指定了名稱,也必須與模型儲存目錄名稱保持一致。

    platform/backend

    platform與backend至少配置一項:

    • platform:用於指定模型架構。常用的模型架構套件含:tensorrt_plan、onnxruntime_onnx、pytorch_libtorch、tensorflow_savedmodel、tensorflow_graphdef等。

    • backend:用於指定模型架構或使用Python代碼自訂推理邏輯。

      • 可指定的模型架構與platform完全一樣,只是設定的名稱不同,架構套件含:tensorrt、onnxruntime、pytorch、tensorflow等。

      • 使用Python代碼自訂推理邏輯,具體操作,請參見部署服務:使用backend

    max_batch_size

    用於指定模型請求批處理的最大數量,若不開啟批處理功能,則將該項設定為0。

    input

    用於指定以下屬性:

    • name:輸入資料的名稱。

    • data_type:資料類型。

    • dims:維度。

    output

    用於指定以下屬性:

    • name:輸入資料的名稱。

    • data_type:資料類型。

    • dims:維度。

    instance_group

    當資源配置中有GPU資源時,預設使用GPU進行模型推理,否則預設使用CPU。您也可以通過配置instance_group參數,來顯式指定模型推理使用的資源,配置格式如下:

    instance_group [
       { 
         kind: KIND_GPU
       }
     ]

    其中kind可配置為KIND_GPUKIND_CPU

    version_policy

    用於指定模型版本,配置樣本如下:

    version_policy: { all { }}
    version_policy: { latest: { num_versions: 2}}
    version_policy: { specific: { versions: [1,3]}}
    • 不配置該參數:預設載入版本號碼最大的模型版本。樣本中resnet50_pt模型會載入模型版本3。

    • all{}:表示載入該模型所有版本。樣本中resnet50_pt會載入模型版本1、2和3。

    • latest{num_versions:}:例如配置為num_versions: 2,樣本中resnet50_pt會載入最新的2個模型版本,即版本2和3。

    • specific{versions:[]}:表示載入指定版本。樣本中resnet50_pt會載入模型版本1和3。

  2. 部署Triton Inference Server服務。

    Triton Inference Server支援配置以下兩種連接埠,在情境化模型部署中,系統預設使用8000連接埠,若您需要使用8001連接埠,則需要執行步驟e,否則忽略步驟e即可。

    • 8000(連接埠):支援HTTP請求,在8000連接埠啟動HTTP服務。

    • 8001:支援gRPC請求,在8001連接埠啟動gRPC服務。

    具體操作步驟如下:

    1. 進入模型線上服務(EAS)頁面。

      1. 登入PAI控制台

      2. 在左側導覽列單擊工作空間列表,在工作空間列表頁面中單擊待操作的工作空間名稱,進入對應工作空間內。

      3. 在工作空間頁面的左側導覽列選擇模型部署>模型線上服務(EAS),進入模型線上服務(EAS)頁面。image

    2. 模型線上服務(EAS)頁面,單擊部署服務

    3. 情境化模型部署地區,單擊Triton部署

    4. Triton部署頁面,配置以下關鍵參數,其他參數配置說明,請參見服務部署:控制台

      參數

      描述

      服務名稱

      自訂佈建服務名稱。

      模型配置

      在本方案中,配置類型選擇按Object Storage Service,將OSS配置為步驟1中已準備的模型所在的OSS儲存路徑,例如oss://example/models/triton/

    5. (可選)單擊頁面右側的切換為自訂部署,修改模型服務資訊地區的運行命令,將連接埠號碼修改為8001,同時您需要在對應配置編輯中添加以下配置。

      說明

      服務預設在8000連接埠啟動HTTP服務,支援HTTP請求。若您需要該服務支援gRPC請求,您需要將連接埠號碼修改為8001,系統會在8001連接埠啟動gRPC服務。

      "metadata": {
          "enable_http2": true
      },
      "networking": {
          "path": "/"
      }
    6. 參數配置完成後,單擊部署

部署服務:多模型

EAS部署多模型服務的方式與部署單模型服務相同,您只需建立如下所示的多個模型儲存目錄即可,服務會載入所有的模型,並部署在同一個服務中。具體部署方式請參見部署服務:單模型

triton
├── resnet50_pt
|   ├── 1
|   │   └── model.pt
|   └── config.pbtxt
├── densenet_onnx
|   ├── 1
|   │   └── model.onnx
|   └── config.pbtxt
└── mnist_savedmodel
    ├── 1
    │   └── model.savedmodel
    │       ├── saved_model.pb
    |       └── variables
    |           ├── variables.data-00000-of-00001
    |           └── variables.index
    └── config.pbtxt

部署服務:使用backend

backend是模型推理計算的具體實現部分,它既可以調用現有的模型架構(如TensorRT、ONNX Runtime、PyTorch、TensorFlow等),也可以自訂模型推理邏輯(如模型預先處理、後處理)。

backend支援 C++、Python兩種語言,與C++相比, Python使用起來更加靈活方便,因此以下內容主要介紹Python backend的使用方式。

  1. 更新模型目錄結構

    以PyTorch為例,使用Python backend自訂模型的計算邏輯,模型目錄結構樣本如下:

    resnet50_pt
    ├── 1
    │   ├── model.pt
    │   └── model.py
    └── config.pbtxt

    與常規的模型目錄結構相比,backend需要在模型版本目錄下新增一個model.py檔案,用於自訂模型的推理邏輯,並且設定檔config.pbtxt內容也需要做相應修改。

    • 自訂推理邏輯

      model.py檔案需要定義名為TritonPythonModel的類,並實現initialize、execute、finalize三個關鍵的介面函數。該檔案內容樣本如下:

      import json
      import os
      import torch
      from torch.utils.dlpack import from_dlpack, to_dlpack
      
      import triton_python_backend_utils as pb_utils
      
      
      class TritonPythonModel:
          """必須以 "TritonPythonModel" 為類名"""
      
          def initialize(self, args):
              """
              初始化函數,可選實現,在載入模型時被調用一次,可用於初始化與模型屬性、模型配置相關的資訊。
              Parameters
              ----------
              args : 字典類型,其中keys和values都為string 類型,具體包括:
                * model_config:JSON格式模型配置資訊。
                * model_instance_kind:裝置型號。
                * model_instance_device_id:裝置ID。
                * model_repository:模型倉庫路徑。
                * model_version:模型版本。
                * model_name:模型名。
              """
      
              # 將JSON字串類型的模型配置內容轉為Python的字典類型。
              self.model_config = model_config = json.loads(args["model_config"])
      
              # 擷取模型設定檔中的屬性。
              output_config = pb_utils.get_output_config_by_name(model_config, "OUTPUT__0")
      
              # 將Triton types轉為numpy types。
              self.output_dtype = pb_utils.triton_string_to_numpy(output_config["data_type"])
      
              # 擷取模型倉庫的路徑。
              self.model_directory = os.path.dirname(os.path.realpath(__file__))
      
              # 擷取模型推理使用的裝置,本例中使用GPU。
              self.device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
              print("device: ", self.device)
      
              model_path = os.path.join(self.model_directory, "model.pt")
              if not os.path.exists(model_path):
                  raise pb_utils.TritonModelException("Cannot find the pytorch model")
              # 通過.to(self.device)將pytorch模型載入到GPU上。
              self.model = torch.jit.load(model_path).to(self.device)
      
              print("Initialized...")
      
          def execute(self, requests):
              """
              模型執行函數,必須實現;每次請求推理都會調用該函數,若設定了 batch 參數,還需由使用者自行實現批處理功能
              Parameters
              ----------
              requests : pb_utils.InferenceRequest類型的請求列表。
      
              Returns
              -------
              pb_utils.InferenceResponse 類型的返回列表。列表長度必須與請求列表一致。
              """
      
              output_dtype = self.output_dtype
      
              responses = []
      
              # 遍曆request列表,並為每個請求都建立對應的response。
              for request in requests:
                  # 擷取輸入tensor。
                  input_tensor = pb_utils.get_input_tensor_by_name(request, "INPUT__0")
                  # 將Triton tensor轉換為Torch tensor。
                  pytorch_tensor = from_dlpack(input_tensor.to_dlpack())
      
                  if pytorch_tensor.shape[2] > 1000 or pytorch_tensor.shape[3] > 1000:
                      responses.append(
                          pb_utils.InferenceResponse(
                              output_tensors=[],
                              error=pb_utils.TritonError(
                                  "Image shape should not be larger than 1000"
                              ),
                          )
                      )
                      continue
      
                  # 在GPU上進行推理計算。
                  prediction = self.model(pytorch_tensor.to(self.device))
      
                  # 將Torch output tensor轉換為Triton tensor。
                  out_tensor = pb_utils.Tensor.from_dlpack("OUTPUT__0", to_dlpack(prediction))
      
                  inference_response = pb_utils.InferenceResponse(output_tensors=[out_tensor])
                  responses.append(inference_response)
      
              return responses
      
          def finalize(self):
              """
              模型卸載時調用,可選實現,可用於模型清理工作。
              """
              print("Cleaning up...")
      
      重要
      • 如果使用GPU進行推理計算,此時在模型設定檔config.pbtxt中指定instance_group.kind為GPU的方式無效,需要通過model.to(torch.device("cuda")) 將模型載入到GPU,並在請求計算時調用pytorch_tensor.to(torch.device("cuda"))將模型輸入Tensor分配到GPU。您只需要在部署服務時配置GPU資源,即可使用GPU進行推理計算。

      • 如果使用批處理功能,此時在模型設定檔config.pbtxt中設定max_batch_size參數的方式無效,您需要自行在execute函數中實現請求批處理的邏輯。

      • request與response必須一一對應,每一個request都要返回一個對應的response。

    • 更新設定檔

      設定檔config.pbtxt內容樣本如下:

      name: "resnet50_pt"
      backend: "python"
      max_batch_size: 128
      input [
        {
          name: "INPUT__0"
          data_type: TYPE_FP32
          dims: [ 3, -1, -1 ]
        }
      ]
      output [
        {
          name: "OUTPUT__0"
          data_type: TYPE_FP32
          dims: [ 1000 ]
        }
      ]
      
      parameters: {
          key: "FORCE_CPU_ONLY_INPUT_TENSORS"
          value: {string_value: "no"}
      }

      其中關鍵參數說明如下,其餘配置與之前保持一致即可。

      • backend:需指定為python。

      • parameters:可選配置,當模型推理使用GPU時,可將FORCE_CPU_ONLY_INPUT_TENSORS參數設定為no,來避免推理計算時輸入Tensor在CPU與GPU之間來回拷貝產生不必要的開銷。

  2. 部署服務。

    使用Python backend必須設定共用記憶體,最後通過如下配置建立模型服務,即可實現自訂模型推理邏輯。關於如何使用用戶端建立模型服務,請參見服務部署:EASCMD或DSW

    {
      "metadata": {
        "name": "triton_server_test",
        "instance": 1,
      },
      "cloud": {
            "computing": {
                "instance_type": "ml.gu7i.c8m30.1-gu30",
                "instances": null
            }
        },
      "containers": [
        {
          "command": "tritonserver --model-repository=/models",
          "image": "eas-registry-vpc.<region>.cr.aliyuncs.com/pai-eas/tritonserver:23.02-py3",
          "port": 8000,
          "prepare": {
            "pythonRequirements": [
              "torch==2.0.1"
            ]
          }
        }
      ],
      "storage": [
        {
          "mount_path": "/models",
          "oss": {
            "path": "oss://oss-test/models/triton_backend/"
          }
        },
        {
          "empty_dir": {
            "medium": "memory",
            // 配置共用記憶體為1 GB。
            "size_limit": 1
          },
          "mount_path": "/dev/shm"
        }
      ]
    }

    其中:

    • name:需要自訂模型服務名稱。

    • storage.oss.path:更新為您的模型儲存目錄所在的OSS Bucket路徑。

    • containers.image:將<region>替換為當前地區,例如:華東2(上海)為cn-shanghai。

調用服務:發送服務要求

您可以通過用戶端發送請求來使用模型服務,Python程式碼範例如下:

  • 發送HTTP請求

    連接埠號碼配置為8000時,服務支援發送HTTP請求。

    import numpy as np
    import tritonclient.http as httpclient
    
    # url為EAS服務部署後產生的訪問地址。
    url = '1859257******.cn-hangzhou.pai-eas.aliyuncs.com/api/predict/triton_server_test'
    
    triton_client = httpclient.InferenceServerClient(url=url)
    
    image = np.ones((1,3,224,224))
    image = image.astype(np.float32)
    
    inputs = []
    inputs.append(httpclient.InferInput('INPUT__0', image.shape, "FP32"))
    inputs[0].set_data_from_numpy(image, binary_data=False)
    outputs = []
    outputs.append(httpclient.InferRequestedOutput('OUTPUT__0', binary_data=False))  # 擷取 1000 維的向量
    
    # 指定模型名稱、請求Token、輸入輸出。
    results = triton_client.infer(
        model_name="<model_name>",
        model_version="<version_num>",
        inputs=inputs,
        outputs=outputs,
        headers={"Authorization": "<test-token>"},
    )
    output_data0 = results.as_numpy('OUTPUT__0')
    print(output_data0.shape)
    print(output_data0)

    其中關鍵參數配置說明如下:

    參數

    描述

    url

    佈建服務訪問地址,服務訪問地址需要省略http://。您可以在模型線上服務(EAS)頁面,單擊服務名稱,然後在服務詳情頁簽中單擊查看調用資訊,查看公網調用地址。

    model_name

    配置模型目錄名稱,例如resnet50_pt

    model_version

    配置實際的模型版本號碼,每次只能對一個模型版本發送請求。

    headers

    <test-token>替換為服務Token,您可以在公網地址調用頁簽查看Token。

  • 發送gRPC請求

    連接埠號碼配置為8001,並添加gRPC相關配置後,服務支援發送gRPC請求。

    #!/usr/bin/env python
    import grpc
    from tritonclient.grpc import service_pb2, service_pb2_grpc
    import numpy as np
    
    if __name__ == "__main__":
        # 定義服務的訪問地址。
        host = (
            "service_name.115770327099****.cn-beijing.pai-eas.aliyuncs.com:80"
        )
        # 服務Token,實際應用中應使用真實的Token。
        token = "test-token"
        # 模型名稱和版本。
        model_name = "resnet50_pt"
        model_version = "1"
        
        # 建立gRPC中繼資料,用於Token驗證。
        metadata = (("authorization", token),)
    
        # 建立gRPC通道和存根,用於與伺服器通訊。
        channel = grpc.insecure_channel(host)
        grpc_stub = service_pb2_grpc.GRPCInferenceServiceStub(channel)
        
        # 構建推理請求。
        request = service_pb2.ModelInferRequest()
        request.model_name = model_name
        request.model_version = model_version
        
        # 構造輸入張量,對應模型設定檔中定義的輸入參數。
        input = service_pb2.ModelInferRequest().InferInputTensor()
        input.name = "INPUT__0"
        input.datatype = "FP32"
        input.shape.extend([1, 3, 224, 224])
         # 構造輸出張量,對應模型設定檔中定義的輸出參數。
        output = service_pb2.ModelInferRequest().InferRequestedOutputTensor()
        output.name = "OUTPUT__0"
        
        # 建立輸入請求。
        request.inputs.extend([input])
        request.outputs.extend([output])
        # 構造隨機數組並序列化為位元組序列,作為輸入資料。
        request.raw_input_contents.append(np.random.rand(1, 3, 224, 224).astype(np.float32).tobytes()) #數實值型別
            
        # 發起推理請求,並接收響應。
        response, _ = grpc_stub.ModelInfer.with_call(request, metadata=metadata)
        
        # 提取響應中的輸出張量。
        output_contents = response.raw_output_contents[0]  # 假設只有一個輸出張量。
        output_shape = [1, 1000]  # 假設輸出張量的形狀是[1, 1000]。
        
        # 將輸出位元組轉換為numpy數組。
        output_array = np.frombuffer(output_contents, dtype=np.float32)
        output_array = output_array.reshape(output_shape)
        
        # 列印模型的輸出結果。
        print("Model output:\n", output_array)

    其中關鍵參數配置說明如下:

    參數

    描述

    host

    需要配置為服務訪問地址,服務訪問地址需要省略http://並在末尾添加:80。您可以在模型線上服務(EAS)頁面,單擊服務名稱,然後在服務詳情頁簽中單擊查看調用資訊,查看公網調用地址。

    token

    <test-token>替換為服務Token,您可以在公網地址調用頁簽查看Token。

    model_name

    配置模型目錄名稱,例如resnet50_pt

    model_version

    配置實際的模型版本號碼,每次只能對一個模型版本發送請求。

相關文檔

  • 如何基於TensorFlow Serving推理服務引擎部署EAS服務,請參見TensorFlow Serving鏡像部署

  • 您也可以開發自訂鏡像,使用自訂鏡像部署EAS服務。具體操作,請參見服務部署:自訂鏡像

  • 服務部署完成後,您可以通過自動壓測工具,對部署的服務進行壓測,從而瞭解EAS服務的使用效能。詳情請參見服務自動壓測

  • 情境化模型部署成功後,您可以調用該服務來驗證模型效果,詳情請參見EAS使用案例匯總