全部產品
Search
文件中心

Platform For AI:使用SDK部署PyTorch模型推理

更新時間:Jul 13, 2024

PAI-Blade提供了C++ SDK協助您部署最佳化後的模型。本文以PyTorch模型為例,介紹PAI-Blade的SDK的使用方法。

前提條件

  • 已使用PAI-Blade對PyTorch模型進行了最佳化,詳情請參見最佳化PyTorch模型

  • 已安裝SDK並擷取鑒權Token,詳情請參見安裝Blade。因為本文使用pre-cxx11 ABI的SDK,3.7.0版本的DEB包。

    說明

    經過PAI-Blade最佳化的模型,必須依賴對應的SDK才能正常運行。

準備環境

本文以Ubuntu為例,介紹如何使用PAI-Blade的SDK部署PyTorch模型。

  1. 準備伺服器。

    本文使用如下配置的ECS執行個體:

    • 執行個體規格:ecs.gn6i-c4g1.xlarge,T4 GPU

    • 作業系統:Ubuntu 18.04 64位

    • 裝置:CUDA 10.0

    • 顯卡驅動:Driver 440.64.00

    • GPU計算加速包:CUDNN 7.6.5

  2. 安裝Python 3。

    # 更新pip版本。
    python3 -m pip install --upgrade pip
    
    # 安裝virtualenv,在虛擬環境中安裝PyTorch。
    pip3 install virtualenv==16.0
    python3 -m virtualenv venv
    
    # 啟用virtualenv。
    source venv/bin/activate

部署模型推理

通過PAI-Blade的SDK載入並部署最佳化後的模型推理,您無需修改原代碼邏輯,只需要在編譯時間連結上PAI-Blade的SDK中的庫檔案。

  1. 準備模型及測試資料。

    本文使用已經最佳化好的樣本模型進行示範,通過如下命令即可下載該模型。您也可以使用自己的最佳化模型,關於如何使用PAI-Blade最佳化模型,詳情請參見最佳化PyTorch模型

    # 下載最佳化好的樣本模型。
    wget http://pai-blade.oss-cn-zhangjiakou.aliyuncs.com/demo/sdk/pytorch/optimized_resnet50.pt
    # 下載對應的測試資料。
    wget http://pai-blade.oss-cn-zhangjiakou.aliyuncs.com/demo/sdk/pytorch/inputs.pth
  2. 下載並查看推理代碼。

    通過PAI-Blade最佳化後的模型,其執行過程與常規PyTorch模型相同,無需編寫額外代碼或配置額外資訊。本文使用的推理代碼如下所示。

    #include <torch/script.h>
    #include <torch/serialize.h>
    #include <chrono>
    #include <iostream>
    #include <fstream>
    #include <memory>
    
    int benchmark(torch::jit::script::Module &module,
                 std::vector<torch::jit::IValue> &inputs) {
      // warmup 10-iter
      for (int k = 0; k < 10; ++ k) {
        module.forward(inputs);
      }
      auto start = std::chrono::system_clock::now();
      // run 20-iter
      for (int k = 0; k < 20; ++ k) {
        module.forward(inputs);
      }
      auto end = std::chrono::system_clock::now();
      std::chrono::duration<double> elapsed_seconds = end-start;
      std::time_t end_time = std::chrono::system_clock::to_time_t(end);
    
      std::cout << "finished computation at " << std::ctime(&end_time)
                << "\nelapsed time: " << elapsed_seconds.count() << "s"
                << "\navg latency: " << 1000.0 * elapsed_seconds.count()/20 << "ms\n";
      return 0;
    }
    
    torch::Tensor load_data(const char* data_file) {
      std::ifstream file(data_file, std::ios::binary);
      std::vector<char> data((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
      torch::IValue ivalue = torch::pickle_load(data);
      CHECK(ivalue.isTensor());
      return ivalue.toTensor();
    }
    
    int main(int argc, const char* argv[]) {
      if (argc != 3) {
        std::cerr << "usage: example-app <path-to-exported-script-module> <path-to-saved-test-data>\n";
        return -1;
      }
    
      torch::jit::script::Module module;
      try {
        // Deserialize the ScriptModule from a file using torch::jit::load().
        module = torch::jit::load(argv[1]);
        auto image_tensor = load_data(argv[2]);
    
        std::vector<torch::IValue> inputs{image_tensor};
        benchmark(module, inputs);
        auto outputs = module.forward(inputs);
      }
      catch (const c10::Error& e) {
        std::cerr << "error loading the model" << std::endl << e.what();
        return -1;
      }
    
      std::cout << "ok\n";
    }

    請將上述範例程式碼儲存到本地的torch_app.cc檔案。

  3. 編譯代碼。

    編譯代碼時,您需要連結libtorch相關庫和SDK /usr/local/lib子目錄下的SO檔案(libtorch_blade.so和libral_base_context.so)。編譯命令如下所示。

    TORCH_DIR=$(python3 -c "import torch; import os; print(os.path.dirname(torch.__file__))")
    g++ torch_app.cc -std=c++14 \
        -D_GLIBCXX_USE_CXX11_ABI=0 \
        -I ${TORCH_DIR}/include \
        -I ${TORCH_DIR}/include/torch/csrc/api/include \
        -Wl,--no-as-needed \
        -L /usr/local/lib \
        -L ${TORCH_DIR}/lib \
        -l torch -l torch_cuda -l torch_cpu -l c10 -l c10_cuda \
        -l torch_blade -l ral_base_context \
        -o torch_app

    您可以根據實際情況修改如下參數:

    • torch_app.cc:推理代碼的檔案名稱。

    • /usr/local/lib:SDK的安裝路徑,通常無需修改。

    • torch_app:編譯產生的可執行程式名。

    在某些版本的系統和編譯器中,需要加上第6行的內容(-Wl,--no-as-needed \),以保證連結生效。

    重要
    • 根據您使用的libtorch ABI版本,正確配置GLIBCXX_USE_CXX11_ABI宏的值。二者的關係請參見安裝Blade的SDK

    • PAI-Blade提供的CUDA 10.0的PyTorch是使用GCC 7.5編譯的。如果使用CXX11 ABI,則務必確認GCC的版本。如果使用 Pre-CXX11 ABI,則不會有問題。

  4. 本地執行模型推理。

    您可以參考如下命令,使用編譯好的可執行程式(torch_app)載入並執行PAI-Blade最佳化好的樣本模型(optimized_resnet50.pt)。

    export BLADE_REGION=<region>    # Region: cn-beijing, cn-shanghai for example.
    export BLADE_TOKEN=<token>
    export LD_LIBRARY_PATH=/usr/local/lib:${TORCH_DIR}/lib:${LD_LIBRARY_PATH}
    ./torch_app  optimized_resnet50.pt inputs.pth                      

    您需要根據實際情況替換以下參數:

    • <region>:PAI-Blade支援的地區,需要加入PAI-Blade使用者群擷取該資訊,使用者群的二維碼詳情請參見擷取Token

    • <token>:鑒權Token,需要加入PAI-Blade使用者群擷取該資訊,使用者群的二維碼詳情請參見擷取Token

    • torch_app:上一步中編譯好的可執行程式。

    • optimized_resnet50.pt:PAI-Blade最佳化好的PyTorch模型,本文使用步驟1中下載的樣本模型。

    • inputs.pth:步驟1中下載的測試資料。

    系統回顯如下類似結果,表示模型已經順利地開始執行了。

    finished computation at Wed Jan 27 20:03:38 2021
    
    elapsed time: 0.513882s
    avg latency: 25.6941ms
    ok