おすすめ

TensorRT のハードウェアとバージョン互換性対応

Reading Time: 3 minutes

背景

TensorRT で推論を行う為には、推論の為の Engine を予めビルドし、それを推論実行環境にデプロイするというステップが必要です。

TensorRT 8.6 以前は Engine をビルドしたバージョンとハードウェアを合わせないと TensorRT Engine は正しく動作しませんでした。この状況だとバージョンが上がった場合に再ビルドが必要になり、ハードウェアがアップグレードするとその環境で再ビルドが必要になります。

TensorRT 8.6 では一定の制約の元で再ビルドなしで TensorRT Engine を使用できるようになりました。

バージョン互換性

バージョン互換性を理解する為に一例をあげると、TensorRT 8.7 ではビルドした Engine を TensorRT 8.6 もしくは TensorRT 8.8 で動作できるようにすることができるようになります。

複数の runtime ライブラリ

TensorRT は複数の runtime を持っています。

  • Default runtime: 通常使用される runtime
  • Lean runtime: エンジンの実行に必要なホスト コードのみ含まれる runtime
  • Dispatch runtime: Lean runtime をロードし、その呼出にリダイレクトする runtime

Lean runtime

バージョン互換性に関連するのは Lean runtime になります。TensorRT plan の構築時に Lean runtime を含めることで runtime で使用する TensorRT のバージョンに依存しないようになります。

Lean runtime を使用することの制約

  • cuDNN および cuBLAS バックエンドはサポートされていない
  • TensorRT Engine の refit やシリアライズができない
  • バージョンに対応したプランのみ実行可能
    • バージョンごとに Lean runtime を用意する必要がある
  • デフォルトの runtime より若干遅くなる可能性がある

バージョンに対応した Plan の構築

コードを下記のようにすることで Lean runtime のコピーが Plan に追加され、バージョン互換性をもつエンジンを作成できます。

C++

builderConfig.setFlag(BuilderFlag::kVERSION_COMPATIBLE);  IHostMemory* plan =
builder->buildSerializedNetwork(network, config);

Python

builder_config.set_flag(tensorrt.BuilderFlag.VERSION_COMPATIBLE)  
plan = builder.build_serialized_network(network, config)

Lean runtime にはホストのコードが含まれるため、信頼できる Plan だけ読み込むようにしてください。下記が Plan を信頼するコードです。

C++

runtime->setEngineHostCodeAllowed(true);

Python

runtime.engine_host_code_allowed = True

Lean runtime を Plan から除外

Lean runtime を各 Plan でパッケージすることは容量を費やすので、Lean runtime を除外し、後で読み込むことができます。

TensorRT Plan を作成する前に下記フラグを設定する必要があります。

C++

builderConfig.setFlag(BuilderFlag::kEXCLUDE_LEAN_RUNTIME);

Python

builder_config.set_flag(tensorrt.BuilderFlag.EXCLUDE_LEAN_RUNTIME)

Lean runtime を手動でロードする

Lean runrime を含まないバージョン互換 Plan をロードするには Lean runtime の一致するバージョンを手動でロードする必要があります。コードで書くと下記のようになります。

C++

IRuntime* newRuntime = createInferRuntime(logger);
IRuntime* oldShimRuntime = newRuntime->loadRuntime(oldRuntimePath);  
engine = oldShimRuntime->deserializeCudaEngine(oldPlan);

Python

new_runtime = tensorrt.Runtime(logger)
old_shim_runtime = new_runtime.load_runtime(old_runtime_path)  
engine = old_shim_runtime.deserialize_cuda_engine(old_plan)

ベンチマーク結果

A100 で数値精度 FP16 で比較した相対的な推論処理時間の結果です。低い方が良い性能になります。赤い線が Default runtime の性能で緑の線が Lean runtime の性能です。

バージョン互換性の制約

バージョン互換性を適用するのにいくつか制約があります。

  • 8.5 以前のバージョンではバージョン互換の Engine をビルドして実行できない
  • メジャー バージョン内でのサポート
    • 例外的に TensorRT 9.x は TensorRT 8.x を読み込める
  • 最小要件として NVIDIA CUDA 11 以降が必要
  • Volta 以前の GPU アーキテクチャに対応していない
  • Lean runtime はエンジンの refit やシリアライズできない
  • NVIDIA DRIVE OS 製品ではサポートされていない

ハードウェア互換性

通常の TensorRT Engine はハードウェアに特化しているため、異なるハードウェアに対応するには Engine の再構築が必要です。

使用方法は下記のように 1 つのフラグを設定するだけです。

config->setHardwareCompatibilityLevel(HardwareCompatibilityLevel::kAMPERE_PLUS);

ポータブルな ISA である PTX を使用してターゲット デバイス上で JIT PTX を行い、実行可能なコードを生成しています。

ポータブルな PTX を実現するために 2 つの調整をしています。

  • アーキテクチャ固有の命令を使用するカーネルを省く
  • 最低保証量以上のシェアード メモリを使用しているカーネルを省く

カーネルを省略しているためパフォーマンスに影響を与える可能性があり、PTX の JITコンパイルをしているため初期化時間が長くなる可能性もあります。

ベンチマーク結果

A100 の環境でハードウェア互換性のある Engine を作成し、A100、H100 で実行した結果と H100 で通常の Engine を実行した結果です。

ハードウェア互換性のある Engine でも TensorRT とのパフォーマンス差が大きく見られるケースはあまりありませんでした。

注意: 現状はデータ センター GPU のみバージョン、ハードウェア互換性を担保予定になります

まとめ

本記事では、TensorRT 8.6 以降のバージョン互換性とハードウェア互換性について解説しました。TensorRT 8.6 で再ビルド不要で Engine を使用可能になり、Lean runtime を利用してバージョン互換性を実現しました。また、ハードウェア互換性も簡単な設定で実現できます。これらの機能は、開発者の効率向上に役立ちますが、利用時に制約や注意点を把握することが重要です。

関連情報

バージョン互換性とハードウェア互換性について、さらに詳しい情報を確認したい方は下記をご覧ください。

TensorRT のドキュメント、インストールガイド、Docker に関しては下記をご覧ください。

Tags