npuloop

고객 모델 인테이크 · 가상 NPU 비용 모델 · 비트 정확 정수 엔진 · CIFAR-10

가상 NPU에 올려보고 양자화·프루닝을 고릅니다

고객이 체크포인트를 보내오면 돌기는 하는지 · 얼마나 걸리는지 · 무엇을 바꿔야 하는지를 숫자로 답합니다. 바로 아래 고객 모델 인테이크가 그 리포트이고, 나머지 섹션은 그 답을 뒷받침하는 실험 12개입니다. 사이클은 해석적 systolic-array 비용 모델(SCALE-Sim과 레이어당 0.5% 이내), 정확도는 비트 정확(bit-exact) 정수 엔진으로 잰 값이고, 모든 숫자는 저장소의 실험 스크립트가 만든 JSON에서 그대로 읽어옵니다.

00고객 모델 인테이크

고객이 체크포인트를 보내왔습니다. 우리 NPU에서 돌기는 하는가, 얼마나 걸리는가, 무엇을 바꿔야 하는가. 아래 세 칸은 이 저장소의 npuloop intake가 실제로 만든 리포트입니다 — 모델과 NPU를 바꿔가며 보세요.

1접수

2진단

3처방

00폐루프 한 장 요약

모델 → fx 그래프(BN folding) → 비용 모델 & lint → 압축 결정(프루닝 · 활성함수 교체 · PTQ/QAT/CLE) → 정수 그래프 export → NumPy/C++ 비트 정확 실행 → fake-quant와 비교. 화살표가 다시 위로 올라가는 것이 이 프로젝트의 요점입니다.

E1베이스라인

같은 레시피(30 epoch OneCycle SGD, seed 0)로 학습한 모델들과 4개 가상 NPU 프리셋에서의 사이클·배열 활용률, lint 점수입니다.

01가상 NPU 비용 모델 탐색기

weight-stationary systolic array 타일 모델입니다. 배열 크기·코어 수·DRAM 대역폭을 바꾸면 레이어별 사이클과 배열 활용률이 어떻게 변하는지 바로 계산됩니다(이 페이지 안의 JavaScript로 포팅한 같은 모델). 채널 수가 배열 폭의 배수가 아니면 활용률이 계단식으로 떨어지는 것을 확인해 보세요.

compute-boundmemory-boundvector (add/pool/LUT)host fallbackdepthwise engine

E8비용 모델 검증 — SCALE-Sim 대조

해석적 모델의 연산 사이클을 SCALE-Sim v3(사이클 정확 systolic-array 시뮬레이터, weight-stationary, 대역폭 제한 없음)와 레이어별로 비교했습니다. 타일당 M + 2R + C − 2 모델은 세 배열 크기 모두에서 합계 0.03% 이내입니다. 오른쪽 열은 fill/drain 항을 빼면 얼마나 낙관적이 되는지 보여줍니다.

검증 범위는 dense conv·linear의 systolic GEMM 사이클(단일 코어, 메모리 스톨 없음)뿐입니다. depthwise 엔진, activation×activation matmul, softmax·LayerNorm·add·pool 벡터 패스, 멀티코어 분할, DRAM roofline은 해석적 값이며 여기서 검증되지 않았습니다.

E10실측 vs 모델 — 검증 엔진의 wall-clock

이 저장소에서 실측한 시간은 비트 정확 검증 엔진 두 개(NumPy int64 워크, C++ 커널)가 호스트 CPU에서 도는 시간뿐이고, NPU 사이클은 전부 모델 값입니다. 둘을 섞어 읽지 않도록 같은 모델·같은 노드에 대해 나란히 둡니다. 처음 잰 C++ 엔진은 순진한 7중 루프라 NumPy(내부는 torch conv2d)보다 3배 느렸고, im2col + int32 GEMM으로 고친 뒤의 값입니다.

E11실제 런타임과 비트가 맞는가 — TensorFlow Lite 교차 검증

TFLite full-integer PTQ 모델의 스케일·zero-point·int8 가중치·int32 바이어스를 그대로 읽어 npuloop 정수 그래프를 만들고, 같은 int8 입력을 TFLite reference 커널과 npuloop 엔진 두 개에 넣어 모든 중간 텐서와 출력 코드를 비교했습니다. conv·pool은 gemmlowp 이중 반올림, fully-connected는 단일 반올림일 때 1,000장 × 모든 텐서가 완전히 일치합니다.

E12두 번째 데이터셋 · 큰 입력 — Imagenette 128×128

ImageNet 10클래스(Imagenette)를 128×128로 준비해 ResNet-20(stem stride 2)을 처음부터 학습하고, 같은 인테이크·PTQ·정수 엔진·실측 파이프라인을 돌렸습니다. 사전학습 가중치 호스트는 이 환경에서 막혀 있어 쓰지 않았습니다.

02NPU 준비도 lint

양자화를 하기 전에 가중치와 shape만 보고 예측한 문제들입니다. 효율성(배열 정렬·depthwise·활성함수 실행 방식)과 양자화 강건성(BN folding 후 채널별 가중치 범위 편차·outlier·비대칭 활성값·residual 스케일 불일치) 두 점수로 요약합니다.

03PTQ 스킴 그리드와 fake-quant ↔ 정수 엔진 일치도

같은 캘리브레이션 세트로 7가지 스킴을 적용하고, PyTorch fake-quant 정확도와 비트 정확 정수 엔진 정확도를 따로 잰 결과입니다. 레이어별 그래프는 정수 엔진 코드가 fake-quant 코드와 다른 비율을 두 가지 관점(전파 vs 국소 teacher-forced)으로 보여줍니다.

propagated mismatch % (end-to-end integer run)local mismatch % (each op fed fake-quant inputs)

레이어별 민감도 (해당 텐서만 양자화했을 때 loss 증가)

04정수 구현 선택의 정확도 비용 (requant ablation)

같은 양자화 파라미터로 정수 엔진의 구현 세부만 바꿨습니다: 반올림(gemmlowp 이중 반올림 vs TFLite single rounding vs truncate), 곱셈기 비트 수, 바이어스/누산기 폭. 기준 구현과의 top-1 일치율은 이미지 단위 짝지은 비교라 잡음이 없습니다.

05수술: CLE · 바이어스 보정 · 활성함수 교체 · QAT

(a) per-tensor 가중치만 지원하는 NPU를 가정한 MobileNetV2 복구, (b) SiLU 모델을 ReLU/HardSwish로 바꾸고 짧게 재학습(healing)했을 때의 정확도와 NPU 사이클, (c) 모든 베이스라인에 3 epoch QAT.

(a) MobileNetV2 · per-tensor 가중치

(b) ResNet-20-SiLU · 활성함수 교체

(c) PTQ → QAT

06캘리브레이션 세트: 몇 장이면 되는가

이미지 수(8 → 2048), 무작위 vs 클래스 균형, 시드 3개. 선은 시드 평균, 띠는 최소–최대입니다.

per-channel W · randomper-channel W · class-balancedper-tensor W · randomper-tensor W · class-balanced

07PE-array 정렬 프루닝: MACs와 사이클은 다르게 움직인다

uniform(FLOPs 기준) · aligned(16/32 배수) · cost-greedy(비용 모델을 루프 안에서 호출) 전략으로 프루닝 → 짧은 fine-tune → PTQ. 왼쪽은 MACs 기준, 오른쪽은 선택한 NPU의 사이클 기준 Pareto입니다. 같은 점들이 두 축에서 얼마나 다르게 보이는지가 요점입니다.

uniformalignedcost-greedyunpruned

08정적 lint는 실제 손실을 예측하는가

레이어 단위: BN folding 후 채널별 가중치 범위 비율(데이터 없이 계산) vs 그 레이어의 가중치만 per-tensor로 양자화했을 때의 loss 증가. Spearman 상관으로 요약합니다.

모델 단위: lint 점수 vs E2에서 측정한 FP32 대비 손실(양수 = 손실). 순서는 맞지만 점수 차이(22점)가 0.3~0.5%p에 해당해 점수는 순위용이지 보정된 예측기가 아닙니다.

09방법과 출처 라벨

measuredCIFAR-10 test 10,000장에서 직접 잰 정확도·일치율. 정수 엔진 정확도는 스킴에 따라 10,000장(주 스킴) 또는 2,000장(보조 스킴)에서 측정했으며 표에 이미지 수를 함께 적습니다.
simulated사이클·활용률·DRAM 트래픽은 해석적 비용 모델의 값입니다. 프리셋은 공개된 헤드라인 수치(TOPS, 대역폭)에 맞춘 가정이지 특정 벤더의 실제 마이크로아키텍처가 아닙니다.
bit-exactNumPy 엔진과 C++ 커널은 모든 중간 텐서가 비트 단위로 같음을 테스트로 강제합니다. requant는 gemmlowp/TFLite 참조 구현과 동일한 고정소수점 연산입니다.
seed학습은 seed 0 한 번입니다. 캘리브레이션 실험만 시드 3개를 씁니다. 0.2%p 이하의 차이는 잡음으로 읽어야 합니다(10k 이미지 표준오차 ≈ 0.3%p).