まえがき
R&Dの宮﨑です。FORTNITEの入力を弄るツールであるダブルムーブメント(合法)がRustで書かれているのを見て低レイヤはRustで書くのがセオリーになりつつあるのかと実感している次第です。
今回はTensorRT 8.2.2/8.2.3のリリースノートの内容をメモしました。
気になった内容
明示的な量子化関連の修正
MatMul
のあるONNXモデルでQuantizeLinear/DequantizeLinear
によりその重みを量子化し、重みをpre-transpose
(i.e. 別のTranspose
を使わない)した場合、量子化の処理中に起こるバグにより精度的なエラーを起こすことがありました。この問題は本リリースで修正されました。(8.2.2)- TensorRTはバッチ処理の行列乗算に対する明示的な量子化(i.e.
Q/DQ
)をサポートしていません。今回の修正により行列Bが定数行列であり2次元行列へsqueeze
できるときに量子化されたバッチ処理の行列乗算の特殊なケースへのサポートを導入しました。(8.2.3) - INT8のQATのネットワークで
Q/DQ
とConvolution
レイヤの前に配置されたPadding
レイヤがあるときに最大で20%のパフォーマンス低下がありました。この問題は本リリースで修正されました。(8.2.3)- 明示的な量子化は直接ネットワークを指定するので形成されるネットワークが予測できるのはもちろん、より細かく指定ができます。例えば「精度を維持したいからここは量子化したくない」といった調整ができます。またその際に用いるQ/DQ周辺では自動的にネットワーク最適化が行われますが、今回はそのあたりに強化と修正が入りよりチャレンジしやすくなりました。
PyTorch Multi-head Attention APIを使用してビルドした
transformer
ベースのネットワークの中には、グラフのパターンが異なることによって、他のAPIを使用してビルドした同等のネットワークに比べ最大45%の速度低下が起きうる問題がありました。この問題は本リリースで修正されました。(8.2.2)- 近年注目されている
Transformer
において処理の中心とも言えるMulti-head Attention
ですが、TensorRTでは最大45%の速度低下を起こす大きな問題がありました。それがとうとうTensorRT 8.2.2で修正されました。
- 近年注目されている
既知の問題が多くあります。ワークアラウンドが記載されているものもあるので遭遇している問題がないかチェックしてみると良いかもしれません。
意訳
- TensorRT 8.2.2/8.2.3で重複している内容が多かったので合わせて記載します。
これはTensorRT 8.2.2/8.2.3のリリースノートで、x86のLinuxとWindows、ARM®ベースのCPUコアを組み込んだLinuxのユーザー向けです。 これらのリリースノートは、特に(Jetsonプラットフォームには適用されません)と付記されていない限り、ワークステーション、サーバー、およびNVIDIA JetPack™のユーザー向けに記載されています。
このリリースには、以前のTensorRT 8.x.xリリースからのいくつかの修正と、以下の追加変更が含まれています。以前のTensorRTのドキュメントについては、NVIDIA TensorRT Archived Documentationを参照してください。
互換性(TensorRT 8.2.2/8.2.3)
- TensorRT 8.2.2 / 8.2.3 は以下でテストされています。
- このリリースでは以下のCUDAのバージョンをサポートしています。
- TensorRTはFeatures For Platforms And SoftwareセクションにあるcuDNNとcuBLASのバージョン含めテスト済みのソフトウェアスタックで使用することが推奨されています。他の意味的に互換性のあるcuDNNやcuBLASも使用できますが、性能が上下する可能性があります。またまれに機能的に後退するかもしれません。
修正された問題(TensorRT 8.2.2)
- pip wheelファイルを使用してTensorRTをインストールするにはpipのバージョンが20未満である必要がありました。TensorRTが依存するCUDA 11.4 wheel metaパッケージの問題へのワークアラウンドにより古いバージョンのpipが必要でしたが、本リリースで修正されました。
samples
ディレクトリの下にdeserializeTimer
という空のディレクトリが誤って残っていた問題がありましたが、本リリースで修正されました。- PyTorch Multi-head Attention APIを使用してビルドした
transformer
ベースのネットワークの中には、グラフのパターンが異なることによって、他のAPIを使用してビルドした同等のネットワークに比べ最大45%の速度低下が起きうる問題がありました。この問題は本リリースで修正されました。 IShuffleLayer
をIConstantLayer
の出力とした際に、定数がkFLOAT
型ではない場合不正に変換されビルドに失敗することがありました。この問題は本リリースで修正されました。MatMul
のあるONNXモデルでQuantizeLinear/DequantizeLinear
によりその重みを量子化し、重みをpre-transpose
(i.e. 別のTranspose
を使わない)した場合、量子化の処理中に起こるバグにより精度的なエラーを起こすことがありました。この問題は本リリースで修正されました。
修正された問題(TensorRT 8.2.3)
- TensorRT 8で導入されたカスタムアロケータとアロケーションリサイズが
p.second failure
に関するアサートを引き起こす既知の問題がありました。これはアプリケーションがリアロケーションのルーチンでTensorRTへ全く同じポインタを渡すことが原因でした。このアサーションが有効なユースケースになるように修正しました。 Pooling
レイヤーをConcatenate
レイヤーの前後に配置したネットワークでは、最大で15%のパフォーマンス低下が発生します。この問題は本リリースで修正されました。- INT8のQATのネットワークで
Q/DQ
とConvolution
レイヤの前に配置されたPadding
レイヤがあるときに最大で20%のパフォーマンス低下がありました。この問題は本リリースで修正されました。 - TensorRTはバッチ処理の行列乗算に対する明示的な量子化(i.e.
Q/DQ
)をサポートしていません。今回の修正により行列Bが定数行列であり2次元行列へsqueeze
できるときに量子化されたバッチ処理の行列乗算の特殊なケースへのサポートを導入しました。具体的には、サポートされた構成では行列A(データ)はBS
がバッチサイズのとき(BS, M, K)
の形状を持つことができ、行列B(重み)は(1, K, N)
の形状を持つことができます。重みがバッチの次元でブロードキャストされて演算されることにより出力は(BS, M, N)
の形状を持ちます。量子化されたバッチ処理の行列乗算は入力データと重みを量子化する二組のQ/DQ
ノードを持ちます。 - モデルのビルド時に2つの
transpose
演算の不正な融合がアサーションを引き起こすことがありました。この問題は本リリースで修正されました。
既知の問題(TensorRT 8.2.2/8.2.3)
- 機能
- TensorRTはGPUのメモリアロケーションの失敗を補足し、メモリ不足エラーを引き起こすメモリ要求を持ったプロファイリング戦略を回避します。しかし、プラットフォームによってはGPUメモリアロケーションの失敗はCUDAによって体よく扱えず回復不能なアプリケーションステータスを引き起こします。もしこの問題が起こった場合は、ワークスペースのサイズが大きい場合は下げたり、大量のGPUメモリを要求する戦略を回避するために
IAlgorithmSelector
インターフェースを使用することをご検討ください。 - Azure VMのT4で
TopK
レイヤがあるネットワークを走らせるとTensorRTが不安定になることがあります。この問題へのワークアラウンドは、CUBLAS_LT kernels
を--tacticSources=-CUBLAS_LT (setTacticSources)
で無効化することです。- TensorRT 8.2.3ではワークアラウンドの記載が削除されています。8.2.3でもこのワークアラウンドを実施すること自体はできるので、効果なしなことが判明したのか単なる書き忘れか・・・
- WSL2の特定の条件下で、エンジンのビルド時に
Concat
レイヤの前に水平に融合され得るConvolution
レイヤーのあるINetwork
は、アプリケーションをクラッシュさせる内部エラー起きることがあります。ワークアラウンドはWSL2の代わりにLinuxでそのネットワークをビルドすることです。 - ダイナミックシェイプでONNXモデルを動作させる際、同じであることが予測される入力の次元名が異なる場合に精度の問題が起きる場合があります。例えば、もしモデルが2つの2次元入力を持ち、その次元セマンティクスが
batch
とseqlen
で、ONNXモデル上では2つの入力の次元名が異なったとき、ダイナミックシェイプで動作させると精度の問題が起きる場合があります。フレームワークからONNXモデルをエクスポートする際は次元セマンティクスが一致することをお確かめください。 - WSLプラットフォーム上で
ILoop
レイヤのあるネットワークにおいて機能的な問題があります。コンパイル時にCUDAエラーを起こします。 - CUDA 10.xのSM 3.xを持つデバイスでは
cuBLASLt
は選択できません。もし選択した場合はcuBLAS
にフォールバックされます。(Jetsonプラットフォームには適用されません) - 重みと活性化のデータが莫大なネットワークの中には、
DLA
がsubgraph
をコンパイルすることに失敗し、subgraph
がGPUへフォールバックされることがあります。 - 条件によっては、TensorRT 8.0ではTensorRT 7.2よりも
RNNv2Layer
が大きなワークスペースサイズを要求するかもしれません。これはサポートする全ての戦略を実行するためです。ワークスペースサイズを増やすことをご検討ください。 CUDA graph capture
は11.xかつ11.1以上のドライバ(455以上)でビルドした時のみ、inputConsumed
とプロファイライベントをキャプチャします。- 統合GPUにおいて、TensorRT 8.0の利用可能なメモリ量を人為的に制限するメモリトラッキングの問題は修正されました。その副作用としてTensorRTの
optimizer
がより多くのメモリを使用するレイヤの実装を選べるようになりました。それによりこれまではOOM Killer
を起こさなかったネットワークでOOM Killer
を起こすようになってしまいました。この問題へのワークアラウンドとして、IAlgorithmSelector
インターフェースを使用して大量のメモリを要求するレイヤの実装を回避するか、layer precision API
を使用して大きなテンソルの精度を下げた上でSTRICT_TYPES
を使用するか、バッチや他のより高い次元を減らすことによってbuilder
への入力テンソルのサイズを減らすことが考えられます。 - TensorRTはあるバージョンの
libnvptxcompiler_static.a
をlibnvinfer_static.a
の中にバンドルします。アプリケーションがTensorRTのビルド時に使用したバージョンと異なるバージョンのPTXJIT
でリンクするとシンボルの競合や望ましくない動作を起こす可能性があります。 cuda-compat-11-4
をインストールすると、CUDAの拡張された互換性に干渉し、ドライバがr465
でもTensorRTで失敗することがあります。ワークアラウンドとしては、cuda-compat-11-4
パッケージを削除するか、ドライバをr470
にアップグレードすることです。(Jetsonプラットフォームには適用されません)- TensorFlow 1.xはPython 3.9に対応していません。TensorFlow 1.xに依存するPythonサンプルは、Python 3.9で実行できません。
- TensorRTは
IConstantLayer
とIShuffleLayer
の融合を限定的にサポートしています。明示的な量子化モードではConvolutions
とFully-Connected
レイヤの重みは融合しなくてはいけません。従って、重みシャッフルがサポートされていない場合、レイヤーの量子化に失敗するかもしれません。 DLA
のネットワークの中でconvolution
レイヤがNHWCなネットワークの入力を受け付ける場合、convolution
レイヤの演算精度は入力テンソルのデータ型と一致する必要があります。- 混合精度は
Pooling
レイヤをサポートしていません。入力と出力のテンソルにおけるデータ型はレイヤの精度と一致させるべきです。 Jetson TX2
でCPU版のPyTorchを使用し、engine_refit_mnist
、network_api_pytorch_mnist
、onnx_packnet
のPythonサンプルを実行するとIllegal instruction (core dumped)
に遭遇するかもしれません。ワークアラウンドはサンプルのREADMEに従いGPU対応版のPyTorchをインストールすることです。- WSL2上のINT8精度での
sample_mnist
では断続的な精度の問題が観測されています。 debian
とRPM
パッケージ(Pythonバインディング、UFF、GraphSurgeon、ONNX-GraphSurgeon)のwheelは自動的に依存解決しません。pipを使い手動でインストールするか、代わりにwheelをインストールするようにしてください。- ネットワークにあるレポジトリからTensorRTをインストールした際に以下のようなエラーを見るかもしれません。
Could not load library libcudnn_ops_infer.so.8. Error: libcublas.so.11: cannot open shared object file: No such file or directory
cuDNN
はRPM依存のlibcublas.so.11()(64bit)
に依存していますが、この依存インストールは最新版リリースのCUDAにあるcuBLAS
ではなくCUDA 11.0にあるcuBLAS
をインストールします。このライブラリのサーチパスは正しく設定されずcuDNN
はcuBLAS
ライブラリを見つけられなくなります。ワークアラウンドは手動で最新版のlibcublas-11-x
パッケージをインストールすることです。 - WindowsのPythonサンプル
uff_ssd
では、freezeしたTensorFlowグラフをUFFに変換する際に起こる既知の問題があります。ワークアラウンドとしては、Linuxやコンテナ上でUFFモデルを生成してコピーすることです。生成したUFFファイルを\path\to\samples\python\uff_ssd\models\ssd_inception_v2_coco_2017_11_17\frozen_inference_graph.uff
にコピーしてください。
- TensorRTはGPUのメモリアロケーションの失敗を補足し、メモリ不足エラーを引き起こすメモリ要求を持ったプロファイリング戦略を回避します。しかし、プラットフォームによってはGPUメモリアロケーションの失敗はCUDAによって体よく扱えず回復不能なアプリケーションステータスを引き起こします。もしこの問題が起こった場合は、ワークスペースのサイズが大きい場合は下げたり、大量のGPUメモリを要求する戦略を回避するために
- パフォーマンス
NVIDIA Jetson AGX Xavier™
でFP16モードにしたResNeXt
ネットワークではTensorRT 8.0.1.6と比較して、最大で7.5%のパフォーマンス低下が発生しました。Pooling
レイヤーをConcatenate
レイヤーの前後に配置したネットワークでは、最大で15%のパフォーマンス低下が発生します。- TensorRT 8.2.3でこの問題は修正されました
- 活性化とバイアスの処理で
FullyConnected
が支配的なネットワークの中には、TensorRT 7.1と比較してパフォーマンスの低下が見られる。- FP32モードで最大12%です。これは将来のリリースで修正される予定です。
NVIDIA Maxwell®/Pascal GPUs
のFP16モードでは最大10%です。
- NVIDIA Jetson Nano™上でVGG16のような
FullyConnected
の処理が重いネットワークにはTensorRT 7.1と比較し最大8%のパフォーマンス低下が見られます。 - Xavierでは最大10-11%のパフォーマンス低下が見られます。
ResNet-152
のバッチサイズ2、FP16でのTensorRT 7.2.3との比較ResNeXt
ネットワークの1か2の少ないバッチサイズ、FP32でのTensorRT 6との比較
- Xavier上では、大きなカーネルサイズの
deconv
を使ったネットワークにおいて、このレイヤに対するエンジンビルドの時間が大きく増大することがあります。またJetson Nano/TX1
でもまたthe launch timed out and was terminated
というエラーメッセージが表示されることがあります。 P100
とV100
上でCUDA 11.3を使用した時、TensorRT 7.2.3と比較し最大40%のパフォーマンス低下が見られます。CUDA 11.0では発生しません。(Jetsonプラットフォームには適用されません)ElementWise ADD
レイヤの入力におけるdynamic ranges
が異なるとき、NVIDIA DLA
上のResNet
ライクなネットワークをJetPack 4.5で実行した際、TensorRT 7.2.3と比較し最大10%のパフォーマンス低下があります。これはDLAのバグであるElementWise ADD
レイヤの2番目の入力に対するdynamic range
を無視する問題を修正したことによるものです。何らかの精度の問題を引き起こします。- DLAでは精度を保つためにINT8の
LeakyReLU
レイヤをFP16へ自動的に変換します。そのためReLU
のような別の活性化関数を使った同等のネットワークに対してレイテンシが悪化することがあります。これを軽減するためにDLA
ではLeakyreLU
レイヤを無効にできます。 - ビルダーはエンジンをビルドするために最大60%より多くのメモリを要求することがあります。
- 並行して
DLA
のConvNets
を他のDLA
、Xavier
プラットフォーム上のiGPU
と実行した場合、DLA
単独で実行した場合と比較して最大126%のパフォーマンス低下が見られます。 NVIDIA Volta GPUs
上のSSD-Inception2
ネットワークではTensorRT 8.0と比較し最大21%のパフォーマンス低下が見られます。- FP16でスパース性を使ったネットワークでは最大5%のパフォーマンス低下があります。
InstanceNorm
プラグインを使ったネットワークでは最大25%のパフォーマンス低下があります。3d_unet
のような3D convolution
を使ったネットワークではエンジンのビルド時間がTensorRT 8.0と比較し最大で500%長くなります。これは多くの高速カーネルが追加されためで、プロファイリング時間が増大しました。
最後に
今回はTensorRT 8.2.2/8.2.3のリリースノートの内容についてご紹介しました。 オプティムは常にリリースノートを追跡しプログラムの改善を行うエンジニアを募集しています。