> EulerNPU > 튜토리얼 > 05. INT8 양자화

05. INT8 양자화

소형 NPU에서 FP32 가중치는 두 가지 이유로 비쌉니다: 메모리 (4× weight bytes) 와 연산 (FP32 곱셈 = INT8 곱셈 × ~4 area). 양자화는 두 비용을 함께 4× 가깝게 줄입니다.

eulernpu의 양자화는:

QAT (Quantization-Aware Training)는 필요 시 add-on 입니다.

스펙 수준 양자화 표시

quantization:
  mode: int8                  # fp32 | int8 | int4
  policy: symmetric           # symmetric (default) | asymmetric
  activation_bits: 8
  weight_bits: 8
  accumulator_bits: 32        # S07: ≥ activation_bits

S07 규칙: accumulator_bits < activation_bits 면 overflow 위험 → validator 가 막습니다.

S23 규칙: quantize / dequantize op이 인접 그래프에서 불일치하면 차단.

양자화 + 컴파일 흐름

# 1) FP32 weights로 컴파일 + golden 생성
eulernpu compile --spec spec.yaml --weights fp32_weights.npz \
                 --backend cpu_ref --out /tmp/golden
eulernpu run     --artifact /tmp/golden --input input.npz --out /tmp/golden.out.npz

# 2) INT8 quantize (per-tensor scale 계산 + 적용)
eulernpu quantize \
    --weights fp32_weights.npz \
    --calib   calib_data.npz \
    --out     int8_weights.npz \
    --report  /tmp/quant_report.json

# 3) INT8 compile + run
eulernpu compile --spec spec_int8.yaml --weights int8_weights.npz \
                 --backend cpu_ref --out /tmp/int8
eulernpu run     --artifact /tmp/int8 --input input.npz --out /tmp/int8.out.npz

# 4) FP32 vs INT8 정확도 비교
eulernpu compare --got /tmp/int8.out.npz --expected /tmp/golden.out.npz --tol 0.02

QuantReport 읽기

cat /tmp/quant_report.json
{
  "tensors": {
    "fc1.weight": {"scale": 0.0127, "max_abs": 1.612, "quant_err_max": 0.0098},
    "fc2.weight": {"scale": 0.0089, "max_abs": 1.131, "quant_err_max": 0.0042}
  },
  "summary": {
    "n_tensors": 12,
    "max_err": 0.0098,
    "median_err": 0.0021
  }
}

quant_err_max ≥ 0.05 이면 layer 별 outlier 분석을 권장합니다 (clipping or per-channel 양자화 검토). CWRU bearing 같은 분포가 좁은 데이터셋은 대개 PTQ 만으로 정확도 손실 없음 (P07 케이스).

fake-fixed-point host sim

silicon 가기 전에 INT8 수학을 host gcc에서 실제 재현:

from eulernpu.quant import FixedPointConfig, quantize_tensor

cfg = FixedPointConfig(bits=8, symmetric=True)
qw, scale = quantize_tensor(fp32_weights, cfg)
# qw: int8, scale: float — 그래프 평가 시 (qw * scale) 로 dequantize

이게 INT8 → FP32 dequantize 결과와 silicon 측에서 ARM이 하는 계산이 byte-equal. host_smoke 가 PASS 하면 silicon 측 수학은 보장됩니다 (silicon-only 함정은 register-map 같은 별도 카테고리).

보드별 INT8 영향

같은 INT8 가중치도 보드별로 cycle/memory 영향이 다름:

eulernpu profile --all-boards /tmp/int8.profile.json

INT4도 지원

quantization:
  mode: int4
  weight_bits: 4
  activation_bits: 8
  accumulator_bits: 32

S21 규칙: INT4 weight + INT8 activation 조합만 허용 (대칭이 아닌 조합은 차단). ZU-class board (XCZU9EG 등)에서 의미 있음.

다음 단계

다양한 모델 패밀리 (MLP/CNN/Transformer/LSTM/Decoder KV) 예제를 보려면 → 06. models.