モデル量子化:NVIDIA TensorRT で FP8 チェックポイントを高性能推論エンジンに変換する方法
NVIDIA は、FP8 で量子化された CLIP チェックポイントを ONNX を経由して TensorRT エンジンに変換する具体的なワークフローと、FP16 ベースラインとの比較による実測速度向上の成果を公開した。
キーポイント
FP8 チェックポイントから TensorRT エンジンの構築プロセス
NVIDIA Model Optimizer で生成された高品質な FP8-量子化 CLIP チェックポイントを ONNX 形式へエクスポートし、QDQ ノードを含んだ状態で TensorRT エンジンとしてビルドする標準パイプラインを詳述している。
FP16 ベースラインとの実測比較による性能検証
量子化された FP8 TensorRT エンジンのプロファイリングを行い、推論速度のスループット向上と GPU 利用率の効率化という、本格的な量産環境でのメリットを数値で示している。
LLM とマルチモーダルモデルにおけるワークフローの違い
標準的な CLIP モデルの量子化パイプラインと、大規模言語モデル(LLM)向けに TensorRT-LLM を使用する異なるパスを明確に区別し、それぞれの適切な適用範囲を示唆している。
ModelOpt と TensorRT の連携によるエンドツーエンドのワークフロー
PyTorch モデルを ModelOpt で FP8 チェックポイントに量子化し、QDQ ノード付きの ONNX エクスポートを経て、TensorRT エンジンを構築・デプロイする完全な自動化プロセスを実現します。
FP8 量子化による高性能推論の実現
FP8 チェックポイントを活用することで、メモリ使用量を削減しつつ、NVIDIA TensorRT の最適化機能と組み合わせることで高速な推論エンジンとして動作します。
FP8 チェックポイントの ONNX エクスポート
ModelOpt の組み込みヘルパーを使用して FP8-量子化された CLIP チェックポイントを ONNX (opset 20+) 形式に変換し、重み側の量子化・非量子化ペアを FP8 保存の非量子化のみチェーンに折りたたむことでファイルサイズを大幅に削減します。
標準ライブラリとの比較
標準的な `torch.onnx.export` でも対応可能ですが、その場合は独自のコンバージョンスクリプトを実装する必要があるため、ModelOpt の機能を利用する方が効率的です。
影響分析・編集コメントを表示
影響分析
この記事は、AI モデル開発者が理論上の最適化から実際の高速推論へ移行する際の具体的な実装指針を提供しており、FP8 量子化技術の生産性への即時適用を可能にする重要なステップを示しています。特に大規模なマルチモーダルモデルや LLM の展開において、GPU リソースの効率化とコスト削減を実現するための標準的なベストプラクティスを確立する役割を果たします。
編集コメント
FP8 量子化の実装における具体的なツールチェーンと、その効果測定方法が明確に示されており、開発者がすぐに実環境へ適用できる実践的なガイドとなっています。
量子化されたチェックポイントを NVIDIA TensorRT エンジンに変換することは、モデル最適化と本番環境への展開の間のギャップを埋め、大規模な運用において推論速度の向上、スループットの増加、より効率的な GPU 利用を実現します。
以前の投稿では、NVIDIA TensorRT Model Optimizer を用いて高品質な FP8 量子化 Contrastive Language-Image Pretraining (CLIP) チェックポイントを作成しました。
今回の投稿では、その続きとして、チェックポイントを ONNX 形式へエクスポートし、本番環境での推論に備えた NVIDIA TensorRT エンジンへとコンパイルする手順を詳しく解説します。また、量子化モデルがもたらす実際の速度向上を測定するため、生成された FP8 TensorRT エンジンを FP16 ベースラインと比較してプロファイリングを行います。
Figure 1 は、一般的なエンドツーエンドの量子化ワークフローにおける 5 つの段階を示しています。これは量子化された CLIP モデルを展開するための標準的なパイプラインです。量子化された LLM(大規模言語モデル)は TensorRT-LLM を通じて異なる経路をたどりますが、これについてはこの チュートリアル で取り上げられています。
image*Figure 1. ModelOpt と TensorRT を用いたエンドツーエンドの量子化および展開ワークフロー*
モデルを ONNX 形式へエクスポート
最初のステップは、ModelOpt チェックポイントを ONNX 形式へエクスポートすることです。以下の擬似コードは、Modelopt に組み込まれたヘルパー関数を使用して、FP8 で量子化された CLIP チェックポイントを ONNX 形式(FP8 QuantizeLinear/DequantizeLinear が完全にサポートされる opset 20 以上)として出力する処理を示しています。これにより、各重み側の量子化後デ量子化(Q-DQ)ペアが FP8 で保存されたデ量子化のみを行うチェーンに折りたたまれ、ONNX ファイルのサイズが大幅に削減されます。
原則的にはネイティブな torch.onnx.export も使用可能ですが、その場合はカスタム変換スクリプトを記述する必要があります。
import torch
from transformers import CLIPModel, CLIPTokenizer
from transformers.models.clip.modeling_clip import CLIPAttention
import modelopt.torch.opt as mto
import modelopt.torch.quantization as mtq
from modelopt.torch._deploy.utils import OnnxBytes, get_onnx_bytes_and_metadata
from modelopt.torch.quantization.plugins.diffusion.diffusers import _QuantAttention
class TextEncoder(torch.nn.Module):
def __init__(self, m):
super().__init__(); self.m = m
def forward(self, x):
return self.m.get_text_features(x)
class ImageEncoder(torch.nn.Module):
def __init__(self, m):
super().__init__(); self.m = m
def forward(self, x):
return self.m.get_image_features(x)
def prepare_for_fp8_onnx_export(model):
for _, mod in model.named_modules():
if isinstance(mod, _QuantAttention):
mod._disable_fp8_mha = False
if isinstance(mod, CLIPAttention) and getattr(mod, "scale", None) is not None:
mod.scale = None
def export(wrapper, dummy, axis_name, out_name):
onnx_bytes, _ = get_onnx_bytes_and_metadata(
model=wrapper, dummy_input=(dummy,), model_name=out_name,
dynamic_axes={axis_name: {0: "batch"}}, onnx_opset=20, weights_dtype="fp16",
)
OnnxBytes.from_bytes(onnx_bytes).write_to_disk("./onnx_output", clean_dir=False)
mto.enable_huggingface_checkpointing()
mtq.QuantModuleRegistry.register({CLIPAttention: "CLIPAttention"})(_QuantAttention)
model = (
CLIPModel.from_pretrained(modelopt_ckpt, attn_implementation="sdpa", torch_dtype=torch.float16)
.eval().cuda()
)
prepare_for_fp8_onnx_export(model)
tok = CLIPTokenizer.from_pretrained(model_ckpt)
dummy_text = tok(["a photo of a cat"], return_tensors="pt", padding="max_length", max_length=77)["input_ids"].cuda()
export(TextEncoder(model), dummy_text, "text_input", "text_clip_fp8")
dummy_image = torch.randn(16, 3, 224, 224, dtype=torch.float16).cuda()
export(ImageEncoder(model), dummy_image, "image_input", "image_clip_fp8")
****Model componentFP8 Modelopt checkpoint FP16 HuggingFace checkpointSize reduction
CLIP text encoder ONNX156 MB237 MB~34%
CLIP image encoder ONNX292 MB582 MB~50%
*Table 1. CLIP ONNX model size: FP8 vs FP16*
表 1 は、FP8 ModelOpt チェックポイントのエクスポートと元の FP16 HuggingFace チェックポイントのエクスポートにおける ONNX ファイルサイズを比較しています。FP8 チェックポイントエクスポートにより、ONNX ファイルは明らかに小さくなり、テキストエンコーダーでは約 34%、画像エンコーダーでは約 50% 削減されています。
なお、ONNX ファイルの縮小は必須要件ではなく利便性です。TensorRT はエンジン構築時に重み側の Q ノードを FP8 重みに統合します。ModelOpt ONNX エクスポート側では、ディスク上のファイルサイズを小さく保つために、より早期に統合処理を行っています。
NVIDIA Nsight Deep Learning Designer を用いて、エクスポートされた ONNX ファイルを検査できます。これは ONNX モデルの編集、パフォーマンスプロファイリング、TensorRT エンジン構築を効率的に行うためのツールです。
図 2 は、Nsight Deep Learning Designer で可視化されたエクスポートされた ONNX グラフの一部を示しています。グラフには now QuantizeLinear/DequantizeLinear(Q/DQ)ノードが含まれており、FP8 の境界を示しています。
image*図 2. アテンション MatMul 周辺の FP8 ONNX グラフにおける Q/DQ ノード*
エンジン構築中、TensorRT はこれらのノードを隣接するレイヤーと融合させ、推論パフォーマンスを最適化します。この融合により、不要な量子化→非量子化の遷移が排除され、計算に最適化された FP8 カーネルを使用可能になります。
TensorRT で ONNX モデルのプロファイリング
FP8 ONNX モデルのエクスポートが完了したら、次はこれを TensorRT に渡して実行速度を測定します。作業を開始する前に、この チュートリアル を参照して、TensorRT が正しくダウンロードされインストールされていることを確認してください。準備ができたら、trtexec(TensorRT コマンドラインラッパー)を使用して、以下のコマンドで ONNX モデルのベンチマークを行います。
TensorRT 環境の設定
export PATH=<TensorRT-${version}/bin>:$PATH
export LD_LIBRARY_PATH=<TensorRT-${version}/lib>:$LD_LIBRARY_PATH
trtexec を使用して ONNX モデルをベンチマーク
trtexec --onnx=text_clip_fp8.onnx \
--shapes=text_input:128x77 \
--stronglyTyped \
--saveEngine=text_clip_fp8.plan
trtexec --onnx=image_clip_fp8.onnx \
--shapes=image_input:128x3x224x224 \
--stronglyTyped \
--saveEngine=image_clip_fp8.plan
- --onnx は、TensorRT がエンジン構築の元にする入力 ONNX モデルを指定します。
- --shapes は入力形状を固定し、TensorRT がその正確なサイズに最適化されたエンジンを構築できるようにします。
- --stronglyTyped は、ModelOpt が ONNX グラフに埋め込んだ精度注釈を TensorRT に厳守させるよう強制し、FP8 重みと活性化値が実際に FP8 で実行されることを保証します。
- --saveEngine は、構築された TensorRT エンジンをディスクに書き出し、後で使用できるようにします。これはスタンドアロンの TensorRT 推論ランタイム用か、NVIDIA Triton Inference Server を通じたサービング用です(この例を参照してください)。
一つの注意点:ModelOpt のエクスポート機能は、アテンションのスケーリングを FP32 ラウンドトリップでラップしますが、--stronglyTyped はこれを拒否します(Float と Half の型不一致エラーが表示される場合があります)。trtexec ベンチマーク実行前に、これらのスケール定数と Cast 演算子を FP16 にキャストし、クリーンで強く型付けされたエンジンを作成してください。
import numpy as np
import onnx
from onnx import TensorProto, numpy_helper, shape_inference
model = onnx.load("clip_fp8.onnx")
for init in model.graph.initializer:
if init.data_type == TensorProto.FLOAT:
arr = numpy_helper.to_array(init).astype(np.float16)
init.CopyFrom(numpy_helper.from_array(arr, name=init.name))
for node in model.graph.node:
if node.op_type == "Cast":
to_attr = next(a for a in node.attribute if a.name == "to")
if to_attr.i == TensorProto.FLOAT:
to_attr.i = TensorProto.FLOAT16
model = shape_inference.infer_shapes(model, data_prop=True, check_type=False)
onnx.save(model, "clip_fp8_strongtyped.onnx")
あるいは、公式の ユーザーガイド のプロファイリングセクションに従って、Nsight Deep Learning Designer を使用して ONNX モデルを TensorRT でプロファイルすることもできます。
TensorRT 10.16 を使用し、trtexec コマンドでバッチサイズを静的に 128 に設定して、NVIDIA RTX 6000 Ada GPU でベンチマークを実行しました。報告されるレイテンシは、デフォルトの測定ウィンドウ内のすべての推論イテレーションの中央値です。*注意:FP8 は、Ada アーキテクチャ以降(計算能力 8.9 以上)の行列乗算(GEMM: General Matrix Multiplication)のみでサポートされています。どのデータ型がどの GPU でサポートされているかの詳細な内訳については、*TensorRT サポートマトリックス*をご覧ください。*
image*図 3. CLIP FP8 と FP16 の比較:TensorRT エンジンサイズと推論レイテンシ*
図 3 は、TensorRT エンジンのサイズと推論レイテンシの両面で、FP8 量子化が FP16 に比べて持つ利点を示しています。左側の画像エンコーダーは 588 MB から 306 MB に縮小され(48% の削減)、テキストエンコーダーも 238 MB から 156 MB に縮小され(34% の削減)となり、ディスク上の合計フットプリントはほぼ半分にカットされます。同じ節約効果は、推論時の GPU VRAM 使用量にも反映されます。なぜなら、より小さなエンジンにはロードして実行するために必要なメモリが少ないからです。
右側のレイテンシに関する話も同様に魅力的です。画像エンコーダーのレイテンシは 166.2 ms から 119.8 ms に低下し、テキストエンコーダーは 13.2 ms から 9.1 ms に低下します。これにより、画像側で 1.39 倍、テキスト側で 1.45 倍の高速化が実現されています。
image*図 4. Nsight Deep Learning Designer を用いた FP16(左)および FP8(右)における CLIP イメージエンコーダーの層別プロファイリング*
FP8 の高速化は具体的にどこから来るのでしょうか?trtexec が報告する生データの数値を超えて、Nsight Deep Learning Designer はより詳細な視覚的な内訳を提供し、明確な答えを示してくれます。
図 4 では FP16 と FP8 のイメージエンコーダーのプロファイルが並べて表示されており、3 つの相違点が即座に目立ちます。
- GEMM(General Matrix Multiply)のバーは約 1.8 ミリ秒から 0.84 ミリ秒へと低下し、NVIDIA RTX 6000 Ada GPU の FP8 Tensor Core カーネルによって提供される、支配的な行列乗算層において 2 倍以上の高速化が実現されています。
- FP16 プロファイルで確認できた「融合(fusion)」レイヤーカテゴリは、FP8 プロファイルでは消滅しています。これは、TensorRT が現在、アテンションブロック全体を専用の FP8 MHA(Multi-Head Attention)カーネルにルーティングし、より簡素化された実行パスを実現しているためです。
- 精度のドーナツチャートが、主にオレンジ色(FP16)から主に紫色(FP8)へと変化しています。これらのシグナルは、量子化された重みと活性化値が FP8 Tensor Core で動作していることを確認するものであり、まさにここが FP8 の恩恵が生じる場所です。つまり、行列乗算を多用するすべてのステップにおいて、計算スループットが高く、メモリ帯域幅の使用量が低減されているのです。
TensorRT における量子化の仕組み
ONNX モデルをインポートする際、TensorRT は QuantizeLinear / DequantizeLinear(Q/DQ)ノードを検索します。これらは、テンソルが FP8 などのフル精度と低精度データ型の間で遷移するグラフ上のポイントをマークするものです。
内部では、TensorRT は量子化可能な各レイヤーの入力ごとに Q/DQ レイヤーペアを必要とします。エンジン構築時、最適化器はこれらの Q/DQ ノードを隣接するレイヤーに融合し、元のレイヤーを低精度テンソルに対して直接動作する専用カーネルに置き換えます。これにより、量子化→再量子化の往復遷移が排除され、エンジンはより高い計算スループットと低いメモリ帯域幅で実行できるようになります。
図 5 は FP8 GEMM のこの変換を示しています。エクスポートされた ONNX では、活性化値と重みテンソルの両方が QuantizeLinear/DequantizeLinear ペアに囲まれており、TensorRT の最適化器がこれらを融合した後、残るのは FP8-量子化された活性化値と事前保存された FP8 重みテンソルを直接受け取る単一の FP8 GEMM カーネルのみとなります。
image*Figure 5. TensorRT における FP8 GEMM の Q/DQ 融合*
TensorRT の量子化メカニズムについてさらに深く知りたい場合は、ドキュメントをご覧ください。
始め方
本稿では、量子化モデルを展開するための完全な ModelOpt → ONNX → TensorRT ワークフローを概説しました。Q/DQ ノード付きで CLIP チェックポイントを ONNX にエクスポートし、TensorRT エンジンを構築して、trtexec と Nsight Deep Learning Designer の両方を用いて FP16 ベースラインと比較ベンチマークを行いました。
結果から、FP8 量子化は RTX 6000 Ada GPU 上で元の FP16 モデルと比較して、著しい速度向上とメモリ使用量の削減をもたらすことが明らかになりました。また、TensorRT がビルド時に Q/DQ ノードを専用の低精度カーネルに融合させることで、これらの性能向上を実現する仕組みについても簡単に概説しました。
NVIDIA Model Optimizer と NVIDIA TensorRT を試し、モデル量子化がもたらす効率性の向上を探ってみてください。
原文を表示
Converting a quantized checkpoint into an NVIDIA TensorRT engine bridges the gap between model optimization and production deployment, enabling faster inference, higher throughput, and more efficient GPU utilization at scale.
In a previous post, we produced a high-quality FP8-quantized Contrastive Language-Image Pretraining (CLIP) checkpoint with NVIDIA TensorRT Model Optimizer.
This post picks up where we left off, walking through how to export the checkpoint to ONNX and compile it into an NVIDIA TensorRT engine ready for production inference. We also profile the resulting FP8 TensorRT engine against the FP16 baseline to measure the real-world speedup the quantized model delivers.
Figure 1 shows the five stages of a typical end-to-end quantization workflow. This is the standard pipeline for deploying a quantized CLIP model. Quantized LLMs follow a different path through TensorRT-LLM, which is covered in this tutorial.

Export model to ONNX format
The first step is to export the ModelOpt checkpoint to ONNX. The following pseudo-code does this for the FP8-quantized CLIP checkpoint using a built-in helper from Modelopt (the export targets ONNX opset 20+, where FP8 QuantizeLinear/DequantizeLinear is fully supported). It folds each weight-side quantize-then-dequantize (Q-DQ) pair into an FP8-stored DQ-only chain, noticeably shrinking the ONNX file.
In principle native torch.onnx.export works too, but requires us to write a custom conversion script.
import torch
from transformers import CLIPModel, CLIPTokenizer
from transformers.models.clip.modeling_clip import CLIPAttention
import modelopt.torch.opt as mto
import modelopt.torch.quantization as mtq
from modelopt.torch._deploy.utils import OnnxBytes, get_onnx_bytes_and_metadata
from modelopt.torch.quantization.plugins.diffusion.diffusers import _QuantAttention
class TextEncoder(torch.nn.Module):
def __init__(self, m):
super().__init__(); self.m = m
def forward(self, x):
return self.m.get_text_features(x)
class ImageEncoder(torch.nn.Module):
def __init__(self, m):
super().__init__(); self.m = m
def forward(self, x):
return self.m.get_image_features(x)
def prepare_for_fp8_onnx_export(model):
for _, mod in model.named_modules():
if isinstance(mod, _QuantAttention):
mod._disable_fp8_mha = False
if isinstance(mod, CLIPAttention) and getattr(mod, "scale", None) is not None:
mod.scale = None
def export(wrapper, dummy, axis_name, out_name):
onnx_bytes, _ = get_onnx_bytes_and_metadata(
model=wrapper, dummy_input=(dummy,), model_name=out_name,
dynamic_axes={axis_name: {0: "batch"}}, onnx_opset=20, weights_dtype="fp16",
)
OnnxBytes.from_bytes(onnx_bytes).write_to_disk("./onnx_output", clean_dir=False)
mto.enable_huggingface_checkpointing()
mtq.QuantModuleRegistry.register({CLIPAttention: "CLIPAttention"})(_QuantAttention)
model = (
CLIPModel.from_pretrained(modelopt_ckpt, attn_implementation="sdpa", torch_dtype=torch.float16)
.eval().cuda()
)
prepare_for_fp8_onnx_export(model)
tok = CLIPTokenizer.from_pretrained(model_ckpt)
dummy_text = tok(["a photo of a cat"], return_tensors="pt", padding="max_length", max_length=77)["input_ids"].cuda()
export(TextEncoder(model), dummy_text, "text_input", "text_clip_fp8")
dummy_image = torch.randn(16, 3, 224, 224, dtype=torch.float16).cuda()
export(ImageEncoder(model), dummy_image, "image_input", "image_clip_fp8")
Table 1 compares the ONNX file sizes of the FP8 ModelOpt checkpoint export against the original FP16 HuggingFace checkpoint export. The FP8 checkpoint export produces noticeably smaller ONNX files, ~34% smaller for the text encoder and ~50% smaller for the image encoder.
Note that shrinking the ONNX file is a convenience, not a requirement. TensorRT folds the weight-side Q node into the FP8 weight at engine-build time. ModelOpt ONNX exporter folds earlier on the ONNX side to keep the on-disk file smaller.
We can inspect the exported ONNX file with the NVIDIA Nsight Deep Learning Designer, an efficient tool for ONNX model editing, performance profiling, and TensorRT engine building.
Figure 2 shows a portion of the exported ONNX graph visualized in Nsight Deep Learning Designer. We can see that the graph now contains QuantizeLinear/ DequantizeLinear (Q/DQ) nodes, marking the FP8 boundaries.

During engine building, TensorRT fuses these nodes with adjacent layers to optimize inference performance. This fusion eliminates unnecessary quantize-then-dequantize transitions, enabling the use of optimized FP8 kernels for computation.
Profile ONNX model with TensorRT
With the FP8 ONNX model exported, the next step is to pass it to TensorRT and measure how fast it runs. Before we begin, make sure TensorRT is properly downloaded and installed by following this tutorial. Once ready, we will use trtexec (TensorRT command-line wrapper) to benchmark the ONNX model with the following command:
# Set up the TensorRT environment
export PATH=<TensorRT-${version}/bin>:$PATH
export LD_LIBRARY_PATH=<TensorRT-${version}/lib>:$LD_LIBRARY_PATH
# Benchmark the ONNX model with trtexec
trtexec --onnx=text_clip_fp8.onnx \
--shapes=text_input:128x77 \
--stronglyTyped \
--saveEngine=text_clip_fp8.plan
trtexec --onnx=image_clip_fp8.onnx \
--shapes=image_input:128x3x224x224 \
--stronglyTyped \
--saveEngine=image_clip_fp8.plan
- --onnx specifies the input ONNX model that TensorRT will build the engine from.
- --shapes pins the input shape so TensorRT can build an optimized engine for that exact size.
- --stronglyTyped forces TensorRT to respect the precision annotations that ModelOpt baked into the ONNX graph, ensuring our FP8 weights and activations actually execute in FP8.
- --saveEngine writes the built TensorRT engine to disk for later reuse, either for standalone TensorRT inference runtime or for serving through NVIDIA Triton Inference Server (see this example).
One caveat: ModelOpt’s exporter wraps the attention scaling in an FP32 round-trip, which --stronglyTyped rejects (you may see a Float vs Half type mismatch error). Before trtexec benchmarking, we cast these scale constants and Cast ops back to FP16 to get a clean, strongly typed engine.
import numpy as np
import onnx
from onnx import TensorProto, numpy_helper, shape_inference
model = onnx.load("clip_fp8.onnx")
for init in model.graph.initializer:
if init.data_type == TensorProto.FLOAT:
arr = numpy_helper.to_array(init).astype(np.float16)
init.CopyFrom(numpy_helper.from_array(arr, name=init.name))
for node in model.graph.node:
if node.op_type == "Cast":
to_attr = next(a for a in node.attribute if a.name == "to")
if to_attr.i == TensorProto.FLOAT:
to_attr.i = TensorProto.FLOAT16
model = shape_inference.infer_shapes(model, data_prop=True, check_type=False)
onnx.save(model, "clip_fp8_strongtyped.onnx")
Alternatively, we can also profile the ONNX model with TensorRT using Nsight Deep Learning Designer by following the profiling section in the official user guide.
We run the benchmark on an NVIDIA RTX 6000 Ada GPU with TensorRT 10.16 using the trtexec command, with a static batch size of 128. Each reported latency is the median across all inference iterations within the default measurement window. *Note that FP8 is only supported for matrix multiplications (GEMM) on Ada and later architectures (compute capability 8.9 or above). For a detailed breakdown of which data types are supported on which GPUs, see the *TensorRT support matrix*.*

Figure 3 shows the benefits of FP8 quantization over FP16 across both TensorRT engine size and inference latency. On the left, the image encoder shrinks from 588 MB to 306 MB (a 48% reduction) and the text encoder from 238 MB to 156 MB (a 34% reduction), cutting the combined on-disk footprint nearly in half. The same savings carry over to GPU VRAM usage at inference time because smaller engines require less memory to load and run.
On the right, the latency story is just as compelling. The image encoder drops from 166.2 ms to 119.8 ms and the text encoder from 13.2 ms to 9.1 ms, delivering a 1.39x speedup on the image side and 1.45x on the text side.

Where exactly does the FP8 speedup come from? Beyond the raw numbers trtexec reports, Nsight Deep Learning Designer offers a richer visual breakdown to give us a clear answer.
Figure 4 places the FP16 and FP8 image encoder profiles side by side, and three differences immediately stand out.
- The GEMM bar drops from roughly 1.8 ms to 0.84 ms, more than a 2x speedup on the dominant matmul layer, delivered by NVIDIA RTX 6000 Ada GPUs’ FP8 Tensor Core kernels.
- The “fusion” layer category visible in the FP16 profile is gone in the FP8 profile because TensorRT now routes the entire attention block through a specialized FP8 MHA kernel and yields a more streamlined execution path.
- The precision donut shifts from a mostly orange (FP16) plot to a mostly purple (FP8) one. These signals confirm that our quantized weights and activations are running on FP8 Tensor Cores, which is exactly where FP8’s gains come from—higher computational throughput and lower memory bandwidth usage in every matmul-heavy step.
How quantization works in TensorRT
When importing an ONNX model, TensorRT looks for QuantizeLinear / DequantizeLinear (Q/DQ) nodes, which mark the points in the graph where a tensor transitions between full- and low-precision data types such as FP8.
Internally, TensorRT requires a Q/DQ layer pair on each input of every quantizable layer. At engine build time, the optimizer fuses these Q/DQ nodes into their adjacent layers and replaces the original layer with a specialized kernel that operates directly on the low-precision tensors. This eliminates the round-trip quantize-then-dequantize transitions and lets the engine execute with higher compute throughput and lower memory bandwidth.
Figure 5 shows this transformation for an FP8 GEMM. In the exported ONNX, both the activation and the weight tensor are wrapped in a QuantizeLinear/DequantizeLinear pair, and after TensorRT’s optimizer fuses them, what remains is a single FP8 GEMM kernel that takes the FP8-quantized activation and a pre-stored FP8 weight tensor directly.

For a deeper dive into TensorRT quantization mechanics, see the documentation.
Get started
In this post, we walked through the full ModelOpt → ONNX → TensorRT workflow for deploying a quantized model. We exported a CLIP checkpoint to ONNX with Q/DQ nodes, built a TensorRT engine, and benchmarked it against the FP16 baseline with both trtexec and Nsight Deep Learning Designer.
The results revealed that FP8 quantization delivers significant speed and memory footprint improvements compared to the original FP16 models on an RTX 6000 Ada GPU. We also gave a brief overview of how TensorRT realizes those gains by fusing Q/DQ nodes into specialized low-precision kernels at build time.
Try NVIDIA Model Optimizer and NVIDIA TensorRT and explore the efficiency gains that model quantization can deliver.
関連記事
Stable Diffusion 3.5モデル、TensorRT最適化によりNVIDIA RTX GPUで性能2倍向上・メモリ使用量40%削減を実現
Stability AIがNVIDIAと協力し、Stable Diffusion 3.5モデルをTensorRTで最適化した。これにより、NVIDIA RTX GPUでの画像生成速度が最大2.3倍向上し、VRAM使用量が40%削減された。
TensorRT最適化版Stable Diffusion 3.5、NVIDIA RTX GPUで2倍高速・VRAM40%削減
Stability AIとNVIDIAは、TensorRTで最適化したStable Diffusion 3.5モデルを公開した。これにより、NVIDIA RTX GPU上で最大2.3倍の高速生成とVRAM使用量の40%削減を実現し、幅広いGPUでの商用・非商用利用が可能となった。
AI モデル推論パイプラインの摩擦を解消する方法
NVIDIA は、訓練済み AI モデルを実環境へ展開する際のボトルネック解消法を提示し、モデルのエクスポートや最適化プロセスにおける課題解決策を解説している。
今日のまとめ
AI日報で今日の重要ニュースをまとめ読み