TensorRT 6 でさらに快適な高速推論

はじめに

オプティムの R&D チームで Deep な画像解析をやっている奥村です。

2019/09/17 の Tweet で TensorRT 6 のリリースを発見しました。TensorRT 5.1.5 のリリースから約四ヶ月ぶりのリリースとなります。今回は RC がなく、いきなり GA となっています。気になった内容がいくつかあったので、TensorRT 6.0.1 のリリースノートをベースに、意訳(直訳)したものをメモしました。公式情報ではないので参考程度にしてください。TensorRT については特にここでは触れませんが、 TensorRT で物体検出・姿勢推定はどれくらい速くなる? - OPTiM TECH BLOG で少し触れていますので興味があれば参照してみてください。

気になった内容

Dynamic Shapes

従来の TensorRT では、ネットワークに入力するテンソルのサイズを固定にする必要性がありました。ネットワークを Fully Convolutional Network として構成できると入力サイズに適した処理がやりやすいのですが、従来の TensorRT ではこれができず、入力するテンソルのサイズごとにモデルをコンパイルする必要があり、デプロイ時の課題として感じていました。TensorRT 6 では Dynamic Shapes がサポートされ、実行時までテンソルの次元の指定を遅延させることができるようになったので、ある程度解消されると思われます。特に、Semantic Segmentation では Fully Convolutional Network が多いので、恩恵が大きいと思われます。

具体的な手順は TensorRT Developer Guide の Working With Dynamic Shapes を参照するといいでしょう。

IResizeLayer

Nearest Neighbor と Bilinear によるテンソルのリサイズができる IResizeLayer が追加されました。出力テンソルの次元か入力テンソルに対する拡大縮小率でリサイズの大きさを指定できます。align_corners にも対応しています。同等の機能を自前で用意する必要がなくなるので便利になると思います。

3D Convolution

ボリューム画像の推論もいけるようになりそうです。行動認識で使われる 3D-ResNets もやりやすくなるかもしれません。

tech-blog.optim.co.jp

sampleUffMaskRCNN

みんな大好き(?) Mask R-CNN が TensorRT で実行できるサンプルが追加されました。FP32 および FP16 で実行できる手順が紹介されています。

Mask R-CNN でどんなことができるかは、過去にいくつか紹介していますので興味があれば参照してみてください。

tech-blog.optim.co.jp tech-blog.optim.co.jp

意訳

TensorRT 6.0.1.5 GA

これは Linux と Windows ユーザー向けの TensorRT 6.0.1 のリリースノートです。このリリースには、以前の TensorRT 5.x.x リリースからの修正と、以下の追加の変更を含みます。

以前リリースされたバージョンについては TensorRT Documentation Archives を参照してください。

主要な機能と改善

新しいレイヤー

IResizeLayer

IResizeLayer は、入力テンソルのリサイズ操作を実装します。詳細は IResizeLayer: TensorRT APIIResizeLayer: TensorRT Developer Guide を参照してください。

IShapeLayer

IShapeLayer は、テンソルの shape を取得します。詳細は IShapeLayer: TensorRT APIIShapeLayer: TensorRT Developer Guide を参照してください。

PointWise fusion

性能向上のため、複数の隣接する pointwise layer を単一の pointwise layer に融合できます。詳細は TensorRT Best Practices Guide を参照してください。

新しいオペレーター

3D Convolution

5D テンソルに対して 3D フィルタで Convolution 操作を実行します。詳細は TensorRT API の addConvolutionNdTensorRT Developer Guide の IConvolutionalLayer を参照してください。

3D Deconvolution

5D テンソルに対して 3D フィルタで Deconvolution 操作を実行します。詳細は TensorRT API の addDeconvolutionNdTensorRT Developer Guide の IDeconvolutionalLayer を参照してください。

3D Pooling

5D テンソルに対して 3D フィルタで Pooling 操作を実行します。詳細は TensorRT API の addPoolingNdTensorRT Developer Guide の IPoolingLayer を参照してください。

新しいプラグイン

Persistent LSTM プラグイン (可変シーケンス長をサポートする半精度 Persistent LSTM プラグイン) が追加されます。このプラグインは、双方向、初期の hidden/cell 値の設定、最終的な hidden/cell 値の格納、複数レイヤーもサポートしています。PluginV2 インターフェースから利用可能で、小さいバッチサイズでよりよい性能を達成しますが、現在は Linux でのみサポートされています。詳細は、TensorRT Developer Guide の Persistent LSTM Plugin を参照してください。

新しいオペレーター

  1. TensorFlow で ResizeBilinearResizeNearest が追加されます。
  2. ONNX で Resize が追加されます。

詳細は Support Matrix の Supported Ops にある完全なリストを参照してください。

新しいサンプル

sampleDynamicReshape

ONNX MNIST モデルにとっての正しいサイズに入力を動的に整形するためのエンジンを作ることで、TensorRT で動的な入力次元の使い方をデモする sampleDynamicReshape が追加されました。詳細は、TensorRT Developer Guide にある Working With Dynamic Shapes、TensorRT Samples Support Guide にある Digit Recognition With Dynamic ShapesGitHub の ../samples/opensource/sampleDynamicReshape ディレクトリ を参照してください。

sampleNvmedia

※ GitHub にサンプルが見当たらないので省略しました。

sampleReformatFreeIO

※ 細かいので省略しました。

sampleUffPluginV2Ext

※ 細かいので省略しました。

sampleNMT

※ NMT に疎いので省略しました。

sampleUffMaskRCNN

TensorRT で Mask R-CNN ネットワークの推論を実行するサンプルです。Mask R-CNN は Mask R-CNN の論文に基づいており、画像に対して物体検出と物体のマスク予測のタスクを実行します。このサンプルのモデルは Mask R-CNN の Keras 実装に基づいており、その訓練のフレームワークは Mask R-CNN Github レポジトリ にあります。詳細は TensorRT Sample Support Guide にある sampleUffMaskRCNN を参照してください。

sampleUffFasterRCNN

NVIDIA Transfer Learning Toolkit SDK にある Faster R-CNN の UFF TensorRT サンプルです。このサンプルは、Transfer Learning Toolkit にある学習済みの Faster R-CNN を TensorRT で推論する方法のデモです。詳細は TensorRT Sample Support Guide にある sampleUffFasterRCNN を参照してください。

新しい最適化

Dynamic shapes

テンソルのサイズを実行時に可変にできます。IShuffleLayerISliceLayer、そして新しい IResizeLayer は、実行時に次元を指定することができるオプションの入力を持っています。IShapeLayer は実行時のテンソルの次元を取得可能で、いくつかのレイヤーは新しい次元を計算できます。詳細は、TensorRT Developer Guide にある Working With Dynamic ShapesTensorRT Layers、TensorRT Samples Support Guide にある Digit Recognition With Dynamic ShapesGitHub: ../samples/opensource/sampleDynamicReshape を参照してください。

Reformat free I/O

ネットワーク I/O テンソルは、リニアな FP32 以外にもできます。ネットワーク I/O テンソルの形式を明示的に指定する API が追加されました。再フォーマットの削除は多くのアプリケーションにとって有益で、特にメモリトラフィック時間をかなり節約します。詳細は、Working With Reformat-Free Network I/O TensorsTensorRT Developer Guide の Example 4: Add A Custom Layer With INT8 I/O Support Using C++ を参照してください。

Layer optimizations

入力テンソルが shuffle レイヤーでのみ使用され、このレイヤーの入力テンソルと出力テンソルがそのネットワークの入力テンソルや出力テンソルではない場合、基となるデータに対して identify 操作と同等な shuffle 操作は省略されます。このような操作に対して、TensorRT は追加のカーネルやメモリコピーの実行を行いません。詳細は、TensorRT Developer Guide の How Does TensorRT Work を参照してください。

New INT8 calibrator

MinMaxCalibrator は、NLP タスクの推奨キャリブレータです。活性化ごとのテンソルのスケーリングをサポートします。テンソルごとに絶対最大値を使用してスケールを計算します。詳細は INT8 Calibration Using C++ を参照してください。

Explicit precision

TensorRT で明示的な精度のネットワークを主導で構成できるようになります。この機能は、明示的な量子化や逆量子化スケールレイヤーを持つ事前量子化済みモデルを TensorRT にインポートできるようにします。ネットワークが明示的な精度を持っているという設定をすると、ネットワーク内のすべての入力テンソルと出力テンソルの精度を設定することになります。このとき、TensorRT はより低い精度で実行される場合にも、レイヤーの重みを量子化しません。その代わり、重みは単純に必要な精度にキャストされます。詳細は、Working With Explicit Precision Using C++TensorRT Developer Guide の Working With Explicit Precision Using Python を参照してください。

インストール

PowerPC ユーザー向けに、RPM と Debian パッケージのサポートが追加されました。

互換性

このリリースでは CUDA 9.0CUDA 10.0CUDA 10.1 update 2 をサポートしています。

制約事項

  1. 最新バージョンの TensorRT へのアップグレードは、現在インストール済みの TensorRT のバージョンが最新の2つのパブリックリリース以上である場合ののみサポートされます。例えば TensorRT 6.x.x は、TensorRT 5.0.x と TensorRT 5.1.x からのアップグレードをサポートします。
  2. INT8 I/Oテンソルを持つネットワーク向けのキャリブレーションには、FP32 のキャリブレーションデータが必要です。

非推奨機能

  • サンプルの変更
    1. . MNIST サンプル用の PGM ファイルが削除されました。generate_pgms.py というスクリプトが samples/mnist/data に提供されていて、データセットを使って画像を生成します。
    2. . DLA は FP32 や RNN をサポートしていないため、useDLACore=0sampleCharRNN では無効なオプションになりました。サンプルは FP32 でのみ動作するように記述されています。

修正された問題

  1. ログレベル Severity::kVERBOSE が完全にサポートされました。このレベルのログメッセージは、デバッグ情報を含む冗長なメッセージです。
  2. DLA で、stride が 32 より大きい Deconvolution レイヤーがサポートされました。
  3. DLA で、カーネルサイズが 32 より大きい Deconvolution レイヤーがサポートされました。

既知の問題

  1. Ubuntu 14.04 と CentOS 7 で、ONNX と TensorFlow と TensorRT を同じ環境で共存させるには、システムのネイティブコンパイラでソースから ONNX と TensorFlow をビルドする必要があります。特に、pybind11protobuf の互換性の問題を回避するために PowerPC 用の IBM Anaconda チャネルを使うときに、ONNX と TensorFlow をソースからビルドすることが重要です。
  2. SM バージョンが 7.0 未満の場合、性能問題により PointWise fusion が無効化されます。Volta より前のすべての GPU、例えば Pascal、Maxwell、Kepler などが該当します。
  3. TensorRT は、デバイスのすべてのリソースが最適化のために利用可能であると仮定しています。異なるターゲット (例えば DLA0、DLA1、GPU) 用にコンパイルするために、複数の TensorRT のビルダー (例えば、複数の trtexec インスタンス) を同時に使用すると、システムリソースの限界を超え、未定義の動作 (非効率な実行計画、ビルダーの失敗、システムの不安定性) を引き起こす可能性があります。このため、異なるターゲット (DLA と GPU) で個別に --saveEngine 引数を指定して trtexec を使用してプランファイルを保存することを推奨します。プランファイルは、trtexec--loadEngine 引数を仕様するなどしてロードしたり、各ターゲット (DLA0、DLA1、GPU) で複数の推論ジョブを行うために再利用できます。この二段階の手順により、ビルドフェーズ中にシステムリソースが限界を超えにくくなります。また、ビルダーによる干渉を受けずにプランファイルの実行ができます。

Working With Dynamic Shapes

Dynamic shapes は、一部またはすべてのテンソルの次元の指定を実行時まで遅延させる機能です。C++ と Python どちらのインターフェースからでも利用できます。拡張ランタイムが必要になります。

ここでは dynamic shape なエンジンを構築する手順の概要にとどめます。

  1. ネットワーク定義は暗黙的なバッチ次元を持つことができません。
  2. 入力テンソルの次元のうち、実行時の次元にプレースホルダーとして -1 を指定します。
  3. 構築時に1つ以上の最適化プロファイルを指定します。これには、実行時の次元の許容範囲と、自動チューニングによって最適化されるべき次元を指定します。詳細は Optimization Profiles を参照してください。
  4. エンジンを使うための設定を行います。
    1. Dynamic shapes を使わない場合と同様に、エンジンから実行コンテキストを生成します。
    2. 手順 3 で作ったうち、入力次元をカバーする最適化プロファイルの1つを指定します。
    3. 実行コンテキストに入力次元を指定します。入力次元を設定した後は、TensorRT が指定された入力次元に対して計算した出力次元を得られます。
    4. 作業をキューに入れます。

実行時の次元を変更するには、4-2 と 4-3 を繰り返してください。

まとめ

TensorRT はバージョンを重ねるごとに「かゆい」ところが解消されていっています。Dynamic shapes は TensorRT 5.0.0 RC から一年、ついにリリースされたなぁという印象です。気になった内容に関しては、気が向けばベンチマーク結果を出そうと思います。

オプティムでは、こうした技術に興味がある・作ってみたい・既に作っている、というエンジニアを募集しています。興味のある方は、こちらをご覧ください。

www.optim.co.jp