ONNX로 변환하고 양자화까지!
NPU를 위한 모델 최적화 실습 가이드
안녕하세요!
비전공자의 시선으로 NPU를 공부하며 정리해온 블로그 시리즈, 이번에는 직접 손을 움직여보는 실습 편입니다.
저는 Furiosa NPU에 영감을 받아, NPU가 필요한 이유와 구조를 하나하나 공부하고 있습니다.
이번 실습은 실제 FuriosaAI SDK를 사용하는 것은 아니지만,
NPU에서 잘 돌아갈 수 있는 모델을 어떻게 준비할까?라는 관점에서 진행해봤습니다.
1. ONNX가 뭐고 왜 필요한가?
ONNX(Open Neural Network Exchange)는 PyTorch, TensorFlow, Keras 등 다양한 딥러닝 프레임워크에서 학습된 모델을 하나의 통일된 포맷으로 표현하기 위한 오픈 포맷입니다.
딥러닝 모델을 다양한 환경에서 활용하려면 ‘통역기’가 필요합니다.
ONNX는 바로 이 역할을 합니다.
예를 들어, PyTorch에서 학습한 모델을 TensorRT, EdgeTPU, NPU 등의 하드웨어에서 사용하고 싶을 때, ONNX로 변환하면 중간 다리 역할을 해줍니다.
NPU 실습에 ONNX가 중요한 이유는? 대부분의 NPU SDK가 ONNX 모델을 받아서 최적화 & 추론하기 때문입니다. |
특히 대부분의 NPU는 자체 프레임워크 대신 ONNX 기반 최적화 툴을 활용해 모델을 추론 엔진에 적재하므로, ONNX는 NPU 실습을 위한 첫 준비 단계라고 할 수 있습니다.
2. PyTorch 모델을 ONNX로 변환하기
ONNX 변환은 PyTorch의 torch.onnx.export() 함수를 사용하면 간단하게 수행됩니다.
✅ 예제 모델: torchvision의 resnet18
import torch
import torchvision.models as models
model = models.resnet18(pretrained=True)
model.eval()
dummy_input = torch.randn(1, 3, 224, 224)
torch.onnx.export(model, dummy_input, "resnet18.onnx", opset_version=11)
- dummy_input: 입력값의 크기를 기준으로 모델 그래프를 tracing합니다.
- opset_version: ONNX 연산자 버전. 대부분의 NPU 툴은 opset 11 이상을 권장합니다.
변환이 완료되면 resnet18.onnx 파일이 생성됩니다.
이 파일이 바로 다양한 하드웨어 추론 환경에서 사용 가능한 표준 모델입니다.
3. 양자화(Quantization)란?
양자화란 모델 내부에서 사용되는 부동소수점 연산(FP32)을 8비트 정수(INT8) 등으로 변환하여 모델 용량을 줄이고, 연산 효율을 높이는 최적화 기법입니다.
양자화의 주요 목적
- 연산량 감소: 계산 속도 향상 (특히 모바일, 엣지 환경)
- 메모리 사용량 절감: 모델 크기 축소
- 전력 효율 향상: 배터리 기반 디바이스에 유리
- 추론 지연 시간 감소: 실시간 응답이 중요한 서비스에 적합
대부분의 NPU는 INT8 연산을 기본적으로 지원하고, 그에 맞게 모델을 양자화하면 성능은 유지하면서도 훨씬 가볍게 동작시킬 수 있습니다.
🔧 왜 필요한가?
|
4. ONNX 모델 양자화 실습
이번 실습에서는 Post-Training Quantization(사후 양자화)를 사용합니다.
즉, 이미 학습된 모델을 그대로 INT8로 최적화하는 방식입니다.
준비 라이브러리 설치
pip install onnx onnxruntime onnxruntime-tools
🔧 준비물: onnxruntime + onnxruntime-tools
✨ 양자화 코드 (Dynamic Quantization)
from onnxruntime.quantization import quantize_dynamic, QuantType
quantize_dynamic(
model_input="resnet18.onnx",
model_output="resnet18_int8.onnx",
weight_type=QuantType.QInt8
)
• 단 2줄이면 끝! 😎
• resnet18_int8.onnx 파일이 생성되며, NPU 환경에서도 훨씬 가볍고 빠르게 실행 가능한 모델이 됩니다.
5. 전후 비교 (크기 & 정확도)
항목 | 변환 전 | 양자화 후 |
모델 크기 | 약 45MB | 약 11MB |
추론 속도 (CPU 기준) | 100ms | 65ms |
정확도 (Top-1) | 거의 동일 (~69.6%) | ~69.1% |
- 성능은 거의 동일하지만,
- 크기와 추론 속도에서 확실한 차이가 있습니다.
※ 결과는 예시이며, 실제는 하드웨어 및 테스트 환경에 따라 달라질 수 있습니다.
6. 정리하며 – 왜 이게 중요한가?
딥러닝 모델을 실제 하드웨어 위에서 구동하려면 단순히 학습된 모델만으로는 부족합니다.
하드웨어는 연산 방식, 정밀도, 메모리 접근 구조가 다르기 때문에, 그에 맞게 모델을 변환·최적화해야 제대로 된 성능을 낼 수 있습니다.
이번 실습은 NPU가 없어도 체험 가능한 부분부터 시작한 것으로, NPU를 이해하는 첫 단계로 매우 실용적입니다.
다음 글 예고
"NPU 워크로드 설계 전략 – MAC 어레이를 100% 활용하려면?"
이제부터는 단순히 모델을 변환하는 걸 넘어서, NPU 내부 구조에 맞게 Layer 구성, 연산 병렬성, 메모리 최적화 등을 설계하는 전략을 함께 알아보겠습니다.
궁금하신 사항은 댓글에 남겨주세요
댓글에 남겨주신 내용은
추후 정리해서 올려드리겠습니다
구독하시면 업로드 시 알려드릴게요!
-
조금이라도 도움이 되셨다면
공감&댓글 부탁드리겠습니다
감사합니다!
'NPU' 카테고리의 다른 글
NPU 실전 매핑 전략 – 이미지 분류부터 LLM까지 워크로드별 적용법 (2) | 2025.06.16 |
---|---|
NPU 아키텍처 깊이 들여다보기 – 주요 컴포넌트와 데이터 흐름 (1) | 2025.05.13 |
딥러닝 연산, 왜 GPU를 넘어서 NPU까지 필요할까? (5) | 2025.04.15 |
딥러닝은 어떻게 학습할까? 순전파부터 NPU까지 한눈에 정리 (0) | 2025.04.09 |
딥러닝 손실 함수 (MSE와 Cross-Entropy) 차이 (0) | 2025.04.09 |