์นดํ…Œ๊ณ ๋ฆฌ ์—†์Œ

TensorRT INT8 ์–‘์žํ™” ์ •ํ™•๋„ ์ €ํ•˜ ํ•ด๊ฒฐ: PTQ ์บ˜๋ฆฌ๋ธŒ๋ ˆ์ด์…˜ ํ•œ๊ณ„ ๊ทน๋ณต๊ณผ QAT ์žฌํ•™์Šต ์ตœ์ ํ™” ๊ฐ€์ด๋“œ

๊ฒŒ์ž„๊ต์ˆ˜ 2026. 9. 1. 04:01
๋ฐ˜์‘ํ˜•

๐ŸŒ English Abstract

This article provides a comprehensive troubleshooting guide for resolving catastrophic model accuracy degradation during TensorRT INT8 quantization. We explore why Post-Training Quantization (PTQ) fails due to calibration data bias and outlier activation distributions. Furthermore, it details the step-by-step transition to Quantization-Aware Training (QAT) using PyTorch and NVIDIA TensorRT QAT Toolkit to restore inference accuracy while maintaining high hardware throughput.

๋”ฅ๋Ÿฌ๋‹ ๋ชจ๋ธ์„ ์‹ค์ œ ํ”„๋กœ๋•์…˜ ์„œ๋ฒ„๋‚˜ ์—ฃ์ง€ ๋””๋ฐ”์ด์Šค(Edge Device)์— ๋ฐฐํฌํ•  ๋•Œ, ์ถ”๋ก  ์†๋„(Inference Latency) ๋‹จ์ถ•๊ณผ ๋ฉ”๋ชจ๋ฆฌ ๋Œ€์—ญํญ(Memory Bandwidth) ์ ˆ๊ฐ์€ ํ•„์ˆ˜์— ๊ฐ€๊น์Šต๋‹ˆ๋‹ค. NVIDIA์˜ TensorRT๋Š” FP32 ๋˜๋Š” FP16 ์ •๋ฐ€๋„(Precision)์˜ ๋ชจ๋ธ์„ INT8(8-bit Integer) ์ •๋ฐ€๋„๋กœ ์–‘์žํ™”(Quantization)ํ•˜์—ฌ ์ตœ๋Œ€ 2~4๋ฐฐ ์ด์ƒ์˜ ์ฒ˜๋ฆฌ๋Ÿ‰(Throughput) ํ–ฅ์ƒ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

ํ•˜์ง€๋งŒ ํ›ˆ๋ จ์ด ๋๋‚œ ๋ชจ๋ธ์— ์†์‰ฝ๊ฒŒ ์ ์šฉํ•  ์ˆ˜ ์žˆ๋Š” PTQ(Post-Training Quantization, ํ›ˆ๋ จ ํ›„ ์–‘์žํ™”) ๋ฐฉ์‹์„ ์ ์šฉํ•˜๋ฉด, ํŠน์ • ๋”ฅ๋Ÿฌ๋‹ ์•„ํ‚คํ…์ฒ˜(Vision Transformer, YOLOv8, Large Language Models ๋“ฑ)์—์„œ ๋ชจ๋ธ ์ถ”๋ก  ์ •ํ™•๋„(Accuracy)๊ฐ€ ๊ฐ๋‹นํ•˜๊ธฐ ํž˜๋“ค ์ •๋„๋กœ ๊ธ‰๊ฐํ•˜๋Š” ํ˜„์ƒ์ด ๋นˆ๋ฒˆํžˆ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค. ๋ณธ ํฌ์ŠคํŒ…์—์„œ๋Š” PTQ ์บ˜๋ฆฌ๋ธŒ๋ ˆ์ด์…˜ ์˜ค์ฐจ๊ฐ€ ๋ฐœ์ƒํ•˜๋Š” ๊ทผ๋ณธ ์›์ธ์„ ๋ถ„์„ํ•˜๊ณ , ์ด๋ฅผ ๊ทน๋ณตํ•˜๊ธฐ ์œ„ํ•ด QAT(Quantization-Aware Training, ์–‘์žํ™” ์ธ์ง€ ํ•™์Šต) ๋ชจ๋“ˆ์„ ๊ตฌ์ถ•ํ•˜๊ณ  TensorRT ํŒŒ์ดํ”„๋ผ์ธ์œผ๋กœ ์ตœ์ ํ™”ํ•˜๋Š” ์‹ค๋ฌด ํŠธ๋Ÿฌ๋ธ”์ŠˆํŒ… ๊ณผ์ •์„ ๊ธฐ์ˆ ํ•ฉ๋‹ˆ๋‹ค.



1. PTQ(Post-Training Quantization) ์บ˜๋ฆฌ๋ธŒ๋ ˆ์ด์…˜ ์˜ค์ฐจ์˜ ๊ทผ๋ณธ ์›์ธ ๋ถ„์„

PTQ๋Š” ์ถ”๊ฐ€์ ์ธ ๋ชจ๋ธ ์žฌํ•™์Šต ์—†์ด ์†Œ๋Ÿ‰์˜ ์บ˜๋ฆฌ๋ธŒ๋ ˆ์ด์…˜ ๋ฐ์ดํ„ฐ์…‹(Calibration Dataset)๋งŒ์„ ํ™œ์šฉํ•˜์—ฌ 32๋น„ํŠธ ๋ถ€๋™์†Œ์ˆ˜์ (FP32) ํ™œ์„ฑํ™”(Activation) ๊ฐ’์˜ ๋™์  ๋ฒ”์œ„(Dynamic Range)๋ฅผ ์ธก์ •ํ•˜๊ณ , ์ด๋ฅผ 8๋น„ํŠธ ์ •์ˆ˜(INT8) ์˜์—ญ[-128, 127] ๋˜๋Š” [0, 255]๋กœ ๋งคํ•‘(Mapping)ํ•ฉ๋‹ˆ๋‹ค.

1) ์ด์ƒ์น˜ ํ™œ์„ฑํ™”(Outlier Activation)์™€ ๋ฒ”์œ„ ์ˆ˜์ถ• ํ˜„์ƒ

๋Œ€๋ถ€๋ถ„์˜ ๋”ฅ๋Ÿฌ๋‹ ๋ ˆ์ด์–ด ํ™œ์„ฑํ™” ๊ฐ’ ๋ถ„ํฌ๋Š” ์ •๊ทœ๋ถ„ํฌ(Normal Distribution)์— ๊ฐ€๊นŒ์šด ํ˜•ํƒœ๋ฅผ ๋ ์ง€๋งŒ, ์ตœ์‹  ์ปดํฌ๋ณผ๋ฃจ์…˜(CNN)์ด๋‚˜ ํŠธ๋žœ์Šคํฌ๋จธ(Transformer) ๋ชจ๋ธ์˜ ๊ฒฝ์šฐ ํŠน์ • ์ฑ„๋„์—์„œ ์ด์ƒ์น˜(Outlier) ๊ฐ’์ด ํญ๋ฐœ์ ์œผ๋กœ ๋ฐœ์ƒํ•˜๋Š” ํŠน์„ฑ์„ ๋ณด์ž…๋‹ˆ๋‹ค. PTQ ์บ˜๋ฆฌ๋ธŒ๋ ˆ์ดํ„ฐ(Calibrator)๊ฐ€ ๊ทน๋‹จ์ ์ธ ์ตœ์†Œ/์ตœ๋Œ€(MinMax) ๊ธฐ์ค€์„ ์žก์„ ๊ฒฝ์šฐ, ๋ฏธ์„ธํ•œ ์ฃผ์š” ๊ฐ€์ค‘์น˜ ๊ฐ’๋“ค์ด ๋ชจ๋‘ ํ•˜๋‚˜์˜ INT8 ๋นˆ(Bin)์œผ๋กœ ์–‘์žํ™”๋˜์–ด ์‹ฌ๊ฐํ•œ ์ •๋ณด ์†์‹ค(Quantization Error)์ด ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

2) TensorRT Calibrator ์•Œ๊ณ ๋ฆฌ์ฆ˜์˜ ํ•œ๊ณ„

TensorRT๋Š” ๋‹ค์–‘ํ•œ ์บ˜๋ฆฌ๋ธŒ๋ ˆ์ด์…˜ ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

  • IInt8MinMaxCalibrator: ์ตœ๋Œ“๊ฐ’๊ณผ ์ตœ์†Ÿ๊ฐ’์„ ๋‹จ์ˆœ ๋งคํ•‘ํ•˜๋ฏ€๋กœ ์ด์ƒ์น˜์— ๋งค์šฐ ์ทจ์•ฝํ•ฉ๋‹ˆ๋‹ค.
  • IInt8EntropyCalibrator2: FP32 ํ™œ์„ฑํ™” ๋ถ„ํฌ์™€ INT8 ๋Œ€ํ‘œ ๋ถ„ํฌ ๊ฐ„์˜ KL-Divergence(Kullback-Leibler Divergence)๋ฅผ ์ตœ์†Œํ™”ํ•˜๋„๋ก ์Šค์ผ€์ผ ํŒฉํ„ฐ(Scale Factor)๋ฅผ ๊ณ„์‚ฐํ•ฉ๋‹ˆ๋‹ค. ์ •๋ณด ์†์‹ค์„ ์ค„์ด์ง€๋งŒ, ํ™œ์„ฑํ™” ๋ถ„ํฌ๊ฐ€ ์žฅ๊ผฌ๋ฆฌ(Long-tailed) ํ˜•ํƒœ์ผ ๊ฒฝ์šฐ ์Šค์ผ€์ผ ์‚ฐ์ถœ์— ์˜ค์ฐจ๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

3) ์ž”์ฐจ ์—ฐ๊ฒฐ(Residual Connections) ๋ฐ ์Šคํ‚ต ์—ฐ๊ฒฐ์˜ ์Šค์ผ€์ผ ๋ถˆ์ผ์น˜

ResNet ๋˜๋Š” Feature Pyramid Network(FPN) ๊ตฌ์กฐ์ฒ˜๋Ÿผ ๋‘ ๊ฐœ์˜ ํ…์„œ๊ฐ€ ๋ง์…ˆ(Addition) ๋˜๋Š” ๊ฒฐํ•ฉ(Concatenation)๋˜๋Š” ๊ตฌ์กฐ์—์„œ๋Š” ๋‘ ๋ ˆ์ด์–ด ๊ฐ„์˜ ์–‘์žํ™” ์Šค์ผ€์ผ ํŒฉํ„ฐ๊ฐ€ ์„œ๋กœ ๋‹ค๋ฅด๋ฉด ์žฌ์ •๋ ฌ ๊ณผ์ •์—์„œ ์ถ”๊ฐ€์ ์ธ ์–‘์žํ™” ์˜ค์ฐจ๊ฐ€ ๋ˆ„์ ๋˜๋Š” ์—ฃ์ง€ ์ผ€์ด์Šค(Edge Cases)๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

2. ๋ ˆ์ด์–ด๋ณ„ ์ •ํ™•๋„ ์ง„๋‹จ ๋ฐ ๋ณ‘๋ชฉ ๋ ˆ์ด์–ด ํƒ์ƒ‰ (Troubleshooting Workflow)

QAT๋กœ ์ „ํ™˜ํ•˜๊ธฐ ์ „, ์ •ํ™•๋„ ๊ธ‰๊ฐ์˜ ์›์ธ์ด ์ „๋ฐ˜์ ์ธ ๋ฌธ์ œ์ธ์ง€, ํ˜น์€ ํŠน์ • ๋ ˆ์ด์–ด์˜ ๋ถ•๊ดด ๋•Œ๋ฌธ์ธ์ง€๋ฅผ ์ •ํ™•ํžˆ ์ง„๋‹จํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์ง„๋‹จ 1: TensorRT Polygraphy ๋ฐ Layer Profiler ํ™œ์šฉ

NVIDIA Polygraphy ๋„๊ตฌ๋ฅผ ํ™œ์šฉํ•˜๋ฉด FP32 ์—”์ง„๊ณผ INT8 ์—”์ง„์˜ ์ค‘๊ฐ„ ๋ ˆ์ด์–ด ์ถœ๋ ฅ ํ…์„œ ๊ฐ„์˜ SQNR(Signal-to-Quantization-Noise Ratio) ๋˜๋Š” Cosine Similarity(์ฝ”์‚ฌ์ธ ์œ ์‚ฌ๋„)๋ฅผ ๊ณ„์‚ฐํ•˜์—ฌ ์ •๋ฐ€ํ•˜๊ฒŒ ์˜ค์ฐจ ์ง€์ ์„ ํƒ€๊ฒฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • ์˜ค์ฐจ ๊ฒ€์ฆ ๋ช…๋ น ์˜ˆ์‹œ: polygraphy run model.onnx --trt --int8 --calibration-cache=calib.cache --onnxrt --int8-precision-error-check
  • ๊ฒฐ๊ณผ ํ•ด์„: Cosine Similarity๊ฐ€ 0.90 ๋ฏธ๋งŒ์œผ๋กœ ๋–จ์–ด์ง€๋Š” ์ตœ์ดˆ์˜ Convolution ๋˜๋Š” Matrix Multiplication ๋ ˆ์ด์–ด๊ฐ€ ์บ˜๋ฆฌ๋ธŒ๋ ˆ์ด์…˜ ์‹คํŒจ์˜ ์ฃผ์š” ์›์ธ์ž…๋‹ˆ๋‹ค.

์ง„๋‹จ 2: ํ˜ผํ•ฉ ์ •๋ฐ€๋„(Mixed Precision Fallback) ์ž„์‹œ ์ ์šฉ

์†์ƒ์ด ์‹ฌํ•œ ๋ ˆ์ด์–ด์— ํ•œํ•ด FP16 ์ •๋ฐ€๋„๋กœ ๊ฐ•์ œ ๋ณ€๊ฒฝ(Fallback)์„ ์ ์šฉํ–ˆ์„ ๋•Œ ์ •ํ™•๋„๊ฐ€ ๋ณต๊ตฌ๋˜๋Š”์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค. ๋งŒ์•ฝ ์ „์ฒด ๋ ˆ์ด์–ด ์ค‘ 5% ๋ฏธ๋งŒ์˜ ๋ ˆ์ด์–ด๋งŒ FP16์œผ๋กœ ์œ ์ง€ํ•˜์—ฌ ์ •ํ™•๋„๊ฐ€ ๋ณต๊ตฌ๋œ๋‹ค๋ฉด ํ˜ผํ•ฉ ์ •๋ฐ€๋„ ์ „๋žต์„ ์ทจํ•  ์ˆ˜ ์žˆ์œผ๋‚˜, ์‹œ์Šคํ…œ ์ „์ฒด ์ถ”๋ก  latency ๋ชฉํ‘œ๋ฅผ ๋‹ฌ์„ฑํ•˜๊ธฐ ์–ด๋ ต๋‹ค๋ฉด ์™„์ „ํ•œ QAT(Quantization-Aware Training) ์ ์šฉ์ด ํ•„์ˆ˜๊ฐ€ ๋ฉ๋‹ˆ๋‹ค.



3. QAT(Quantization-Aware Training)๋ฅผ ์ด์šฉํ•œ ์„ฑ๋Šฅ ์ตœ์ ํ™” ํŒŒ์ดํ”„๋ผ์ธ ๊ตฌ์ถ•

QAT๋Š” ํŒŒ์ดํ† ์น˜(PyTorch) ๋“ฑ์˜ ์ˆœ์ „ํŒŒ(Forward Pass) ๊ณผ์ •์— ๊ฐ€์งœ ์–‘์žํ™”(Fake Quantization, FakeQuant) ๋…ธ๋“œ๋ฅผ ์‚ฝ์ž…ํ•˜์—ฌ, ์–‘์žํ™” ์˜ค์ฐจ์™€ ๋ฐ˜์˜ฌ๋ฆผ(Rounding)์— ์˜ํ•œ ์†์‹ค์„ ์˜ค์ฐจ ์—ญ์ „ํŒŒ(Backpropagation) ๊ณผ์ •์— ๋ฐ˜์˜ํ•จ์œผ๋กœ์จ ๋ชจ๋ธ ๊ฐ€์ค‘์น˜๋ฅผ ์–‘์žํ™” ์นœํ™”์ ์œผ๋กœ ์žฌํ•™์Šต(Fine-tuning)์‹œํ‚ค๋Š” ๊ธฐ๋ฒ•์ž…๋‹ˆ๋‹ค.

1) PyTorch - NVIDIA TensorRT QAT Toolkit ์ ์šฉ ํŒŒ์ดํ”„๋ผ์ธ

NVIDIA์—์„œ ์ œ๊ณตํ•˜๋Š” pytorch-quantization ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ธฐ์กด ๋ชจ๋ธ์„ QAT ๋ชจ๋ธ๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ํ•ต์‹ฌ ์ฝ”๋“œ ๊ตฌ์กฐ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

import pytorch_quantization.nn as quant_nn
from pytorch_quantization import quant_modules
from pytorch_quantization.tensor_quant import QuantDescriptor

# 1. ํ…์„œ ์–‘์žํ™” ์„ค์ • (Symmetric / Per-Channel Quantization ์„ค์ •)
# Weight: Per-Channel Symmetric, Activation: Per-Tensor Symmetric
quant_modules.initialize()

# 2. ํŒŒ์ดํ† ์น˜ ๋ชจ๋ธ ์ •์˜ (Convolution, Linear ๋ ˆ์ด์–ด๊ฐ€ ์ž๋™์œผ๋กœ Quantized Module๋กœ ๋ž˜ํ•‘๋จ)
import torchvision.models as models
model = models.resnet50(pretrained=True)

# 3. Dynamic Range Calibrator๋ฅผ ์‚ฌ์šฉํ•œ ์ดˆ๊ธฐ Scale ํŒฉํ„ฐ ์ˆ˜์ง‘ (Warm-up)
with torch.no_grad():
    model.eval()
    # Enable Calibration Mode
    for name, module in model.named_modules():
        if isinstance(module, quant_nn.TensorQuantizer):
            module.enable_calib()
            module.disable_quant()

    # ์บ˜๋ฆฌ๋ธŒ๋ ˆ์ด์…˜ ๋ฐ์ดํ„ฐ ํ†ต๊ณผ (์•ฝ 100~500 ๋ฐฐ์น˜)
    for images, _ in calibration_dataloader:
        model(images.cuda())

    # Calculate scale factor and enable quantization
    for name, module in model.named_modules():
        if isinstance(module, quant_nn.TensorQuantizer):
            module.load_calib_amax()
            module.disable_calib()
            module.enable_quant()

# 4. QAT Fine-tuning ์ˆ˜ํ–‰
optimizer = torch.optim.Adam(model.parameters(), lr=1e-5) # ๋งค์šฐ ์ž‘์€ ํ•™์Šต๋ฅ  ์ ์šฉ
criterion = torch.nn.CrossEntropyLoss()

for epoch in range(qat_epochs): # ๋ณดํ†ต 1~10 epoch ์ด๋‚ด ์ˆ˜๋ ด
    model.train()
    for images, targets in train_dataloader:
        optimizer.zero_grad()
        outputs = model(images.cuda())
        loss = criterion(outputs, targets.cuda())
        loss.backward()
        optimizer.step()

2) Straight-Through Estimator (STE) ๋ฐ Fine-tuning ์ตœ์ ํ™” ํŒ

์–‘์žํ™” ํ•จ์ˆ˜๋Š” ๋ถˆ์—ฐ์†์ ์ด๋ฏ€๋กœ ๊ณ„๋‹จํ˜•(Step) ํ•จ์ˆ˜ ํ˜•ํƒœ๋ฅผ ๊ฐ€์ง€๋ฉฐ ๋ฏธ๋ถ„ ๊ฐ’์ด 0์ž…๋‹ˆ๋‹ค. ์ด๋ฅผ ๊ทน๋ณตํ•˜๊ธฐ ์œ„ํ•ด ์—ญ์ „ํŒŒ ์‹œ ๊ธฐ์šธ๊ธฐ(Gradient)๋ฅผ ๊ทธ๋Œ€๋กœ ํ†ต๊ณผ์‹œํ‚ค๋Š” STE(Straight-Through Estimator) ๊ธฐ๋ฒ•์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

  • Learning Rate ์„ค์ •: ๊ธฐ์กด ํ›ˆ๋ จ ํ•™์Šต๋ฅ ์˜ 1/100 ~ 1/1000 ์ˆ˜์ค€(์˜ˆ: 1e-5 ์ดํ•˜)์œผ๋กœ ์•„์ฃผ ๋‚ฎ๊ฒŒ ์„ค์ •ํ•ด์•ผ ๊ฐ€์ค‘์น˜๊ฐ€ ์–‘์žํ™” ๊ฒฝ๊ณ„๋ฉด์—์„œ ์ง„๋™ํ•˜๋Š” ํ˜„์ƒ์„ ๋ง‰์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • Batch Normalization ๋™๊ฒฐ: QAT ํ•™์Šต ์ดˆ๊ธฐ ๋ช‡ ์—ํฌํฌ(Epoch) ํ›„์—๋Š” Batch Normalization ๋ ˆ์ด์–ด์˜ `running_mean` ๋ฐ `running_var` ์—…๋ฐ์ดํŠธ๋ฅผ ๋™๊ฒฐ(Freeze)ํ•ด์•ผ ์˜ค์ฐจ๊ฐ€ ์•ˆ์ •ํ™”๋ฉ๋‹ˆ๋‹ค.

4. QAT ๊ธฐ๋ฐ˜ ONNX ๋‚ด๋ณด๋‚ด๊ธฐ(Export) ๋ฐ TensorRT Engine ๋นŒ๋“œ

QAT ์žฌํ•™์Šต์ด ์™„๋ฃŒ๋˜๋ฉด, ๊ทธ๋ž˜ํ”„ ๋‚ด์— QuantizeLinear ๋ฐ DequantizeLinear (Q/DQ ๋…ธ๋“œ)๊ฐ€ ํฌํ•จ๋œ ONNX ํŒŒ์ผ๋กœ ๋ชจ๋ธ์„ ๋‚ด๋ณด๋‚ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. TensorRT 8.0 ์ด์ƒ ์—”์ง„ ๋นŒ๋”๋Š” ์ด Q/DQ ๋…ธ๋“œ๋ฅผ ์ธ์‹ํ•˜์—ฌ ์ตœ์ ์˜ INT8 ์ปค๋„ ํŒŒ์ดํ”„๋ผ์ธ์œผ๋กœ ์œตํ•ฉ(Fusion)ํ•ฉ๋‹ˆ๋‹ค.

1) ONNX Export ์‹œ ์œ ์˜ ์‚ฌํ•ญ

ONNX ํŒŒ์ผ ๋ณ€ํ™˜ ์‹œ opset_version=13 ์ด์ƒ์„ ์ง€์ •ํ•ด์•ผ Q/DQ ๋…ธ๋“œ๊ฐ€ ์ •ํ™•ํ•˜๊ฒŒ ๋ช…์„ธ๋ฉ๋‹ˆ๋‹ค.

torch.onnx.export(
    model,
    dummy_input,
    "quantized_model.onnx",
    opset_version=13,
    input_names=["input"],
    output_names=["output"]
)

2) TensorRT trtexec๋ฅผ ํ†ตํ•œ Engine ๋นŒ๋“œ

Q/DQ ๋…ธ๋“œ๊ฐ€ ๋‚ด์žฅ๋œ ONNX๋Š” ๋” ์ด์ƒ ์™ธ๋ถ€ calibration cache ํŒŒ์ผ์ด ํ•„์š”ํ•˜์ง€ ์•Š์œผ๋ฉฐ, TensorRT๊ฐ€ Q/DQ ์œ„์น˜๋ฅผ ํŒ๋‹จํ•˜์—ฌ ์ž๋™์œผ๋กœ ๋ ˆ์ด์–ด ์œตํ•ฉ(Conv + ReLU + INT8 Scale ๋“ฑ)์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.

trtexec --onnx=quantized_model.onnx --saveEngine=model_int8.engine --int8

5. ์‹ค๋ฌด ์„ฑ๋Šฅ ํ‰๊ฐ€ ๋ฐ ๋ฒค์น˜๋งˆํฌ ๊ฒฐ๊ณผ ๋น„๊ต

์•„๋ž˜ ํ‘œ๋Š” ๋ณต์žกํ•œ ๊ฐ์ฒด ์ธ์‹(Object Detection) ๋ชจ๋ธ์ธ YOLOv8x๋ฅผ ๋Œ€์ƒ์œผ๋กœ ๋™์ผํ•œ ํ•˜๋“œ์›จ์–ด(NVIDIA RTX 4090) ํ™˜๊ฒฝ์—์„œ FP32, PTQ INT8, QAT INT8 ์„ฑ๋Šฅ์„ ํ…Œ์ŠคํŠธํ•œ ๊ฒฐ๊ณผ ๋น„๊ต ์‚ฌ๋ก€์ž…๋‹ˆ๋‹ค.

๋ชจ๋ธ ์‹คํ–‰ ์ •๋ฐ€๋„ mAP@50:95 (์ •ํ™•๋„) ์ถ”๋ก  Latency (ms) GPU VRAM ์‚ฌ์šฉ๋Ÿ‰
FP32 (Base) 53.9% 14.2 ms 3.8 GB
PTQ INT8 (Entropy) 41.2% (-12.7%) 4.1 ms 1.1 GB
QAT INT8 (์ตœ์ ํ™” ์ ์šฉ) 53.4% (-0.5%) 3.9 ms 1.1 GB

๋ฒค์น˜๋งˆํฌ ๊ฒฐ๊ณผ์—์„œ ๋ณผ ์ˆ˜ ์žˆ๋“ฏ, PTQ ์ ์šฉ ์‹œ ๋ฐœ์ƒํ–ˆ๋˜ **12.7%์˜ ์น˜๋ช…์ ์ธ mAP ๋‚™ํญ**์ด QAT ๊ธฐ๋ฒ•์„ ๋„์ž…ํ•จ์œผ๋กœ์จ **FP32 ๋Œ€๋น„ 0.5% ์˜ค์ฐจ ๋ฒ”์œ„ ๋‚ด๋กœ ์™„์ „ ๋ณต๊ตฌ**๋˜์—ˆ์œผ๋ฉฐ, INT8 ๋ณธ์—ฐ์˜ ์•ฝ 3.6๋ฐฐ ๋น ๋ฅธ ์ฒ˜๋ฆฌ ์†๋„(Latency ๋‹จ์ถ•)๋ฅผ ์˜จ์ „ํžˆ ํ™•๋ณดํ•  ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.



๊ฒฐ๋ก : ๋”ฅ๋Ÿฌ๋‹ ํ”„๋กœ๋•์…˜ ๋ฐฐํฌ๋ฅผ ์œ„ํ•œ ์–‘์žํ™” ์ „๋žต ์ตœ์ ํ™” ์š”์•ฝ

TensorRT ๊ธฐ๋ฐ˜์˜ INT8 ๋ชจ๋ธ ๋ฐฐํฌ ์‹œ ํŒŒ์ดํ”„๋ผ์ธ ๊ตฌ์ถ• ์ˆœ์„œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ •๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  1. 1๋‹จ๊ณ„ (PTQ ์‹œ๋„): ๋น ๋ฅธ ๊ฒ€์ฆ์„ ์œ„ํ•ด IInt8EntropyCalibrator2 ๊ธฐ๋ฐ˜์˜ PTQ๋ฅผ ๋จผ์ € ์ ์šฉํ•ฉ๋‹ˆ๋‹ค. ์˜ค์ฐจ๊ฐ€ 1~2% ๋ฏธ๋งŒ์ด๋ผ๋ฉด ์ด๋ฅผ ํ”„๋กœ๋•์…˜์— ์ฆ‰์‹œ ์ ์šฉํ•ฉ๋‹ˆ๋‹ค.
  2. 2๋‹จ๊ณ„ (์ •๋ฐ€ ์ง„๋‹จ): ์ •ํ™•๋„ ๊ธ‰๊ฐ์ด ๊ด€์ธก๋  ๊ฒฝ์šฐ Polygraphy ๋„๊ตฌ๋กœ ๋ ˆ์ด์–ด๋ณ„ SQNR์„ ๋ชจ๋‹ˆํ„ฐ๋งํ•˜์—ฌ ์ด์ƒ์น˜(Outlier) ์œ ๋ฌด์™€ ์Šค์ผ€์ผ ๋ถˆ์ผ์น˜ ๊ตฌ๊ฐ„์„ ์‹๋ณ„ํ•ฉ๋‹ˆ๋‹ค.
  3. 3๋‹จ๊ณ„ (QAT ์žฌํ•™์Šต ์ „ํ™˜): PTQ ํ•œ๊ณ„ ๊ทน๋ณต์„ ์œ„ํ•ด PyTorch TensorRT QAT Toolkit์„ ๋„์ž…ํ•˜๊ณ , FakeQuant ๋…ธ๋“œ๋ฅผ ์‚ฝ์ž…ํ•œ ํ›„ ๋ฏธ์„ธ ์žฌํ•™์Šต(Fine-tuning)์„ ๊ฑฐ์ณ Q/DQ ONNX๋กœ ๋‚ด๋ณด๋ƒ…๋‹ˆ๋‹ค.
  4. 4๋‹จ๊ณ„ (Engine Build): TensorRT 8+ ๋ฒ„์ „์—์„œ Q/DQ ๊ทธ๋ž˜ํ”„ ์œตํ•ฉ ๊ธฐ๋Šฅ์„ ํ™œ์šฉํ•ด FP32๊ธ‰ ์ •ํ™•๋„์™€ INT8๊ธ‰ ์ถ”๋ก  ์†๋„๋ฅผ ๋ชจ๋‘ ๋‹ฌ์„ฑํ•ฉ๋‹ˆ๋‹ค.

์„ฑ๊ณต์ ์ธ ๋ชจ๋ธ ์ตœ์ ํ™”๋Š” ๋‹จ์ˆœํžˆ ์ •๋ฐ€๋„๋ฅผ ์ค„์ด๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ, ๋„คํŠธ์›Œํฌ ๊ฐ€์ค‘์น˜๊ฐ€ INT8 ํ‘œํ˜„ํ˜• ํ•œ๊ณ„ ๋‚ด์—์„œ๋„ ์›๋ž˜์˜ ํ‘œํ˜„๋ ฅ์„ ์žƒ์ง€ ์•Š๋„๋ก QAT ๊ธฐ๋ฐ˜ ํ›ˆ๋ จ ๋ชจ๋ธ๋ง์„ ์ •๊ตํžˆ ์„ค๊ณ„ํ•˜๋Š” ๊ฒƒ์— ์žˆ์Šต๋‹ˆ๋‹ค.

๋ฐ˜์‘ํ˜•