Cheif Research Officerの西鳥羽 (Jiro Nishitoba (@jnishi) | Twitter ) です。
前回 はONNX runtimeを利用した高速化を紹介いたしました。今回はさらなる高速化をしたいと思います。
NVIDIA 社のTensorRT およびIntel 社のOpenVINO を利用します。
onnxruntimeのインストール
OpenVINOやTensorRTを用いる場合*1 、onnxruntimeをソースからビルドしてインストールします。なお、OpenVINOやTensorRTは既にインストールされているものとします。これらのインストールはOpenVINOのinstallation instruction やTensorRTのInstallation Guide を参考にしてください。
以下のコマンドでonnxruntimeの取得とビルドを行います。詳しくはBuild ONNX Runtime for inferencing 及びBuild ONNX Runtime with Execution Providers を参考にしてください。
git clone --recursive git@github.com:microsoft/onnxruntime.git
cd onnxruntime
source /opt/intel/openvino_2021/bin/setupvars.sh # OpenVINOの有効化
./build.sh --use_cuda --cuda_home /usr/local/cuda --cudnn_home /usr/lib/x86_64-linux-gnu --use_tensorrt --tensorrt_home /usr --use_openvino CPU_FP32 --config RelWithDebInfo --build_shared_lib --use_openmp --build_wheel --parallel
なお、--cuda_home
--cudnn_home
--tensorrt_home
で指定しているディレクト リはUbuntu 20.04にてDeb パッケージでインストールした際のデフォルトのパスになります。ご自身の環境に合わせて変更してください。
OpenVINOを用いたCPUでの推論の高速化
CPUのモデルの推論をOpenVINOを利用して高速化します。OpenVINOはIntel 社がオープンソース で提供している推論用ライブラリです。Intel のCPU、GPU およびFPGA 上での計算に特化して高速な推論を行います。
OpenVINOを用いる場合には providers
に ["OpenVINOExecutionProvider"]
を指定します。
前回のブログ でCUDAの指定を行っていた部分を以下のように変更します。
session = InferenceSession(args.onnx_path, providers=["OpenVINOExecutionProvider" ])
以上でOpenVINOを用いた推論が行われます。
以下に速度比較を行っています。前回のブログと同じように事前学習済みモデルとして cl-tohoku/bert-large-japanese を利用し、livedoorニュース コーパス の記事を学習データ:評価データを4:1に分割し、カテゴリ推定でファインチューニングを行いました。Hugging Face Transformersのモデル、ONNXのCPU実行、ONNXのOpenVINO実行における推論時間を測定しています。評価データ全件に対して推論を行いその1件当たりの平均時間で比較しています。なおOpenVINOでの推論において、8秒近く時間のかかっている推論が4件あり、それらは異常値として平均からは取り除いています。
CPUにおける推論時間の比較
Hugging Face Transformersでの実行よりもOpenVINOによる実行の方が高速ですが、ONNXのCPU実行よりも速度が低下しています。8秒以上かかる例も含めてOpenVINOをうまく扱えてないような感じがします。
TensorRTを用いたGPU での推論の高速化
GPU モデルの推論をTensorRTを利用して高速化します。TensorRTはNVIDIA 社がオープンソース で提供しているGPU 上での推論ライブラリです。INT8やFP16への量子化 やNeural Networkの最適化などを行い、GPU 上での推論を高速化します。
TensorRTを用いる場合には providers
に ["TensorRTExecutionProvider"]
を指定します。
前回のブログ でCUDAの指定を行っていた部分を以下のように変更します。
session = InferenceSession(args.onnx_path, providers=["TensorRTExecutionProvider" ])
以上でTensorRTでの推論が行われます。注意点としては session
を用いた推論の初回実行時にはTensorRT向けのモデルのビルドが行われるため、実行に数十秒くらいの時間がかかります。2回目以降の推論は高速に行われます*2 。
以下に速度比較を行っています。こちらも同じように事前学習済みモデルとして cl-tohoku/bert-large-japanese を利用し、livedoorニュース コーパス の記事を学習データ:評価データを4:1に分割し、カテゴリ推定でファインチューニングを行いました。Hugging Face Transformersのモデル、ONNXのCUDA実行、ONNXのTensorRT実行における推論時間を測定しています。評価データ全件に対して推論を行いその1件当たりの平均時間で比較しています。なおTensorRTでの推論において、1秒以上時間のかかっている推論は推論だけでなくモデルのビルドが行われていると思われるので平均からは取り除いています。
GPU における推論時間の比較
Hugging Face TransformersのモデルとONNX CUDAでの実行を比較すると、前回のブログでもふれたとおり約2.4倍の高速化となっています。TensorRTを用いるとCUDAでの実行から更に1.35倍の高速化となっています。Neural Networkの最適化が行われるタイミングを管理しないといけない課題はありますが、効果は出ているようです。
まとめ
CPUのメーカーおよびGPU のメーカーが公開している高速化ライブラリを通じて推論がどれだけ早くなるかを試してみました。NVIDIA 社のTensorRTを利用したところ初回や、何度も実行していると偶にビルドで時間がかかる時があるものの、CUDA実行と比較して1.35倍の高速化となりました。Intel 社のOpenVINOの方は処理が速くはなりませんでしたが、こちらはうまく扱えていない様子なので今後何かわかりましたら続報を上げたいと思います。