QLoRA
LoRA로 학습할 건데, baseline 모델의 규모가 여전히 크긴해서 그걸 줄이고 싶다.
basemodel에 Quantization하면, 파라미터 정밀도 하락에 수반된 성능 하락이 있지만, 어짜피 sft를 할거니까 비슷한 수준 혹은 그 이상으로 회복할 수 있도록 LoRA만 기존 정밀도를 사용해서 연산 자체는 LoRA의 high-precision 연산을 수행하지만, memory에 올라가 있는 baseline model의 precision은 낮춰서 memory pressure를 줄일 수 있다.e.g. baseline ; NF4, (Q)LoRA : bf16
Abstract
Results
65B 모델을 48GB 단일 gpu만으로도 학습이 가능하도록 LoRA를 light-weight 하게 만들었다.
4 bit-quantization을 했음에도 불구하고, 16bit model을 학습했을 때와 동일한 수준의 performance를 보임.Methods
pre-train된 LLM을 4bit-quantize한 뒤, freeze함.
LoRA를 얹음.
backprop은 4bit 모델을 통과하여 adpater만 learning 됨.
QLoRA Hyperparameter
LoRA rank는 생각보다 상관없더라.
대신 추천(for 8B, 13B 정도 체급에서는.)
Expected Vram Usage
Appendix D. 에 따르면,
Guanaco model
- 65B은 41GB
- 33B은 21GB
- 13B은 10GB
- 7B은 5GB 정도 된다고 함.
학습 → 추론 파이프라인 (실무)
QLoRA는 학습 전용 메모리 최적화다. 학습이 끝나면 inference용으로 그대로 쓰지 않고 별도 경로로 변환하는 것이 표준.
왜 QLoRA 모델을 그대로 서빙하면 느린가
QLoRA 추론은 "FLOPs 동일 + VRAM 감소 + 속도는 더 느림"
bitsandbytes NF4 추론은 매 matmul 직전에 NF4 → BF16 dequantize 커널을 호출한다.
- FLOPs: BF16 matmul과 정확히 동일 (Tensor Core는 NF4 matmul을 네이티브 지원하지 않음)
- HBM read: 4-bit라 1/4로 감소 (이론상 유리)
- 실측 tok/s: 보통 BF16 대비 60–80% 수준 (bnb의 dequant 커널이 미최적화)
- 이유: dequant 결과를 SRAM에 썼다 다시 읽어 MMA에 태우는 왕복 비용이 HBM 절약을 상쇄.
권장 파이프라인
QLoRA 학습 (NF4 base + BF16 LoRA)
↓ merge_and_unload() ─── base를 BF16으로 dequant 후 LoRA 덧셈
BF16 merged model (full precision)
↓ AWQ 또는 GPTQ 재양자화 ─── fine-tuning 도메인 calibration 사용
4-bit 서빙용 모델 (전용 커널 활용)
↓ vLLM / TGI / TensorRT-LLM
고속 추론
대안 비교
| 전략 | 추론 속도 | 품질 | 비고 |
|---|---|---|---|
| QLoRA 그대로 서빙 (bnb) | 느림 (BF16의 60–80%) | 학습 그대로 | demo 용도 |
| merge → BF16 서빙 | BF16 기준 | 최고 | VRAM 여유 있을 때 |
| merge → AWQ/GPTQ 재양자화 | 가장 빠름 | 1–3% 하락 | 현업 기본 |
| LoftQ (ICLR ‘24) | AWQ와 동일 | 재양자화 손실 최소화 | 학습 초기화가 quant-aware |
| QA-LoRA | 타깃 스킴과 동일 | 스킴 일치 시 무손실 | 서빙 포맷 고정 시 |
재양자화 시 주의사항
- 이중 양자화 오차: QLoRA adapter는 NF4 오차에 맞춰 학습되었는데 서빙은 AWQ 오차가 있는 모델에서 수행 → 보상이 전이되지 않음 → 품질 1–3% 하락.
- Calibration 데이터: AWQ/GPTQ calibration은 파인튜닝 도메인으로 구성. pretraining 코퍼스로 calibration하면 “내 도메인의 salient weight”를 놓친다.
- LoRA
alpha/rscale 확인:peft.merge_and_unload()는 자동 처리. 수동 머지 시 누락 주의. - 도메인 held-out A/B 평가: MMLU 같은 범용 벤치만 보면 재양자화 회귀를 놓침.
툴체인
- Unsloth:
save_pretrained_merged()+save_pretrained_gguf()한 줄 export - Axolotl:
merge_lora+ AWQ export recipe 내장 - AutoAWQ / AutoGPTQ: 재양자화 표준 라이브러리
- vLLM / TGI: AWQ·GPTQ 네이티브 로드
핵심 오해 정리
"QLoRA 학습 후 LoRA 포함 재양자화한 모델로 추론하면 속도 이득이 있나? 어차피 dequant되는 거 아닌가?"
예, 이득이 있다. 포인트는 “어떻게 dequant하느냐”의 구현 차이.
- bnb NF4 추론: dequant가 별도 커널. NF4 → BF16 결과를 SRAM에 일단 저장 → 다시 Tensor Core로 읽음. 왕복 비용이 메모리 절감 이득을 까먹음.
- AWQ / GPTQ 전용 커널 (Marlin, ExLlamaV2, vLLM의 W4A16 kernels): dequant 결과를 SRAM을 거치지 않고 레지스터에서 바로 MMA에 fuse. HBM read를 4배 줄이면서 dequant 추가 비용이 거의 없음.
- 결과: decode 단계(memory-bound)에서 BF16 대비 1.5–3배 빠름. prefill(compute-bound)은 BF16과 비슷.
즉 “dequant된다” 자체는 맞지만, “언제·어디서 dequant되느냐” 가 속도를 가른다. AWQ/GPTQ는 HBM→register 경로에 dequant를 녹여 “4-bit weight의 메모리 이득”을 실제 tok/s로 환전한다. QLoRA(bnb) 커널은 그 환전에 실패한다.