PAI-Blade は、最適化されたモデルをデプロイするための C++ SDK を提供します。このトピックでは、PAI-Blade SDK を PyTorch モデルで使用する方法について説明します。
前提条件
-
PAI-Blade を使用して PyTorch モデルが最適化されていること。詳細については、「PyTorch モデルの最適化」をご参照ください。
-
SDK をインストールし、認証トークンを取得済みであること。詳細については、「Blade のインストール」をご参照ください。このトピックでは、pre-cxx11 アプリケーションバイナリインタフェース (ABI) SDK とバージョン 3.7.0 の Debian (DEB) パッケージを使用します。
説明PAI-Blade によって最適化されたモデルを正常に実行するには、対応する SDK が必要です。
環境の準備
このトピックでは、Ubuntu を例として、PAI-Blade SDK を使用して PyTorch モデルをデプロイする方法について説明します。
-
サーバーの準備
このトピックでは、次の構成の Elastic Compute Service (ECS) インスタンスを使用します。
-
インスタンスタイプ: ecs.gn6i-c4g1.xlarge、T4 GPU
-
オペレーティングシステム: Ubuntu 18.04 64 ビット
-
デバイス: CUDA 10.0
-
GPU ドライバー: Driver 440.64.00
-
GPU コンピューティングアクセラレーションパッケージ: cuDNN 7.6.5
-
-
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 のライブラリファイルをリンクするだけで済みます。
-
モデルとテストデータの準備
このトピックでは、デモ用に最適化されたサンプルモデルを使用します。次のコマンドを実行してモデルをダウンロードするか、ご自身の最適化されたモデルを使用できます。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 -
推論コードのダウンロードと表示
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) { // ウォームアップ 10-iter for (int k = 0; k < 10; ++ k) { module.forward(inputs); } auto start = std::chrono::system_clock::now(); // 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 { // torch::jit::load() を使用して、ファイルから ScriptModule をデシリアライズします。 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` という名前のローカルファイルに保存します。
-
コードのコンパイル
コードをコンパイルする際に、関連する 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 が提供する PyTorch for CUDA 10.0 は、GNU Compiler Collection (GCC) 7.5 を使用してコンパイルされています。CXX11 ABI を使用する場合は、GCC のバージョンを確認してください。Pre-CXX11 ABI を使用する場合、この問題は発生しません。
-
-
モデル推論のローカル実行
次のコマンドを実行して、コンパイル済みの実行可能プログラム (torch_app) を使用して、PAI-Blade で最適化されたサンプルモデル (optimized_resnet50.pt) をロードして実行します。
export BLADE_REGION=<region> # リージョン: 例: cn-beijing、cn-shanghai 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 ユーザーグループに参加してください。ユーザーグループの QR コードの詳細については、「トークンの取得」をご参照ください。
-
<token>: 認証トークン。この情報を取得するには、PAI-Blade ユーザーグループに参加してください。ユーザーグループの QR コードの詳細については、「トークンの取得」をご参照ください。
-
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 -