- 대형 LLM은 GPU 메모리 한계 때문에 배포가 어려운데, DFloat11은 BFloat16 가중치를 약 70% 크기로 줄이면서 원본과 비트 단위 동일 출력을 유지함
- 핵심은 BFloat16의 8비트 exponent가 실제로는 약 2.6비트 정보만 담는다는 점으로, sign과 mantissa는 보존하고 exponent만 Huffman coding으로 압축함
- 동적 길이 인코딩은 GPU에서 병목이 되기 쉬워, DFloat11은 계층형 LUT, 2단계 커널, transformer block 단위 압축 해제로 병렬 추론에 맞춤
- Llama 3.3, Qwen 3, Mistral 3, DeepSeek R1 Distilled, FLUX.1, Stable Diffusion 3.5 등에서 약 30% 모델 크기 감소와 원본 출력 보존을 확인함
- CPU offload 대안보다 token generation 처리량이 2.3–46.2배 높고, 8×80GB GPU 단일 노드에서 810GB 규모 Llama 3.1 405B의 무손실 추론을 가능하게 함
DFloat11이 겨냥한 메모리 병목
- LLM과 Diffusion Model 같은 기반 모델은 크기가 빠르게 커져, 메모리 제약이 있는 하드웨어에서 효율적으로 배포하기 어려움
- Llama 3.1 405B는 4050억 개 파라미터를 BFloat16 형식으로 저장하며 전체 추론에 약 810GB 메모리가 필요함
- 이는 8×80GB GPU를 갖춘 일반적인 고급 GPU 서버 용량을 넘음
- 여러 노드가 필요해지면 배포 비용과 접근성 부담이 커짐
- DFloat11은 BFloat16 모델을 원래 크기의 약 70%로 압축하면서도, 어떤 태스크에서도 정확도를 100% 보존하는 것을 목표로 함
손실 양자화와 다른 접근
- 양자화는 가중치 정밀도를 낮춰 메모리를 줄이는 손실 압축 방식임
- 메모리 사용량을 크게 줄이고 추론 속도를 높일 수 있지만 근사 오차가 생김
- 정확도 손실은 기본 모델, 양자화 방식, 평가 벤치마크, 목표 bit-width에 따라 달라 예측하기 어려움
- 예를 들어 8-bit SmoothQuant를 DeepSeek-R1-Distill-Qwen-1.5B에 적용하면 reasoning task 평균 정확도가 9.09% 하락함
- 전체 정확도 지표가 비슷해도 양자화 모델은 원본과 다른 답변 행동을 보일 수 있음
- Dutta et al.은 정답이 오답으로, 또는 오답이 정답으로 바뀌는 flips 현상을 관찰함
- W8A16 GPTQ로 양자화한 Qwen2-1.5B는 GSM8K 8-shot 정확도 하락이 0.3%에 그치지만, 답변의 6.37%에서 정오답 상태가 바뀜
- 금융·의료 같은 영역에서는 양자화 모델의 출력 변화가 규제와 신뢰성 요구를 충족하기 어렵게 만들 수 있음
- 기존 무손실 모델 압축은 주로 checkpoint 저장 효율, 모델 허브 다운로드 시간 단축, FPGA 같은 특수 하드웨어에 초점을 맞춰 일반 GPU 추론에서는 이점이 작음
BFloat16 exponent에 남아 있는 압축 여지
- BFloat16은 16비트를 sign 1비트, exponent 8비트, mantissa 7비트로 나눔
- DFloat11의 출발점은 LLM 가중치의 BFloat16 구성요소별 Shannon entropy 분석임
- sign과 mantissa entropy는 각각의 bit-width에 가까워 압축 여지가 제한적임
- exponent는 8비트가 할당되어 있지만 entropy가 약 2.6비트에 불과함
- exponent 값의 분포는 매우 불균형함
- 가능한 256개 8비트 값 중 약 40개만 사용됨
- 나머지 값은 등장하지 않음
- 빈도 순위도 빠르게 감소함
- 낮은 entropy 덕분에 exponent는 무손실 압축 대상이 되며, 약 5.4비트의 exponent 정보가 압축 가능함
DFloat11 형식
- DFloat11 또는 DF11은 BFloat16 가중치의 exponent만 entropy coding으로 압축하는 동적 길이 부동소수 형식임
- Huffman tree는 모델 가중치의 exponent 분포를 바탕으로 구성됨
- 자주 등장하는 exponent 값에는 짧은 코드가 배정됨
- 드문 값에는 긴 코드가 붙음
- sign과 mantissa는 원본 그대로 유지함
- exponent는
EncodedExponentbyte array에 bit-packed 형태로 저장됨 - sign과 mantissa는
PackedSignMantissabyte array에 별도로 저장됨
- exponent는
- 결과적으로 BFloat16 가중치는 평균 약 11비트 수준으로 줄어들며, 정밀도 손실 없이 원래 BFloat16 값으로 복원 가능함
GPU 추론에 맞춘 압축 해제
- entropy-coded 가중치는 동적 길이 인코딩을 사용하므로 matrix multiplication에 바로 투입할 수 없음
- 필요한 weight matrix를 즉시 원래 BFloat16으로 압축 해제해야 함
- matrix multiplication이 끝나면 BFloat16 matrix는 GPU 메모리 절약을 위해 바로 폐기됨
- 일반 Huffman decoding은 bit 단위로 tree를 순차 탐색하므로 GPU 병렬 구조와 맞지 않음
- 단일 thread가 압축 해제를 맡으면 GPU 활용률이 낮고 latency가 커짐
계층형 LUT 기반 디코딩
- DFloat11은 Huffman tree 탐색 대신 lookup table 기반 디코딩을 사용함
- 최대 Huffman code 길이를 L이라고 할 때 단일 LUT는
2^L크기가 필요함- LLM에서 L은 보통 24–32 범위임
2^32항목 규모 LUT는 GPU SRAM에 올리기 어려움
- 이를 피하기 위해 Huffman tree를 높이 8의 겹치지 않는 subtree로 나누고, 각 subtree를 256-entry compact LUT로 만듦
- 계층형 LUT에서는 일부 항목이 하위 LUT를 가리키는 참조 역할을 해야 함
- LLM exponent에서 사용되지 않는 값이 많다는 점을 활용함
- 240–255 범위의 unused exponent 값을 내부 포인터로 재사용함
- 이 값들은 ±2^113에서 ±2^128 수준의 매우 큰 크기를 나타내며 LLM 가중치에는 등장하지 않음
- 실험에서 BFloat16 exponent Huffman tree의 compact LUT 개수 k는 4–8개 범위임
CodeLengths와 함께 최대(8 + 1) × 256 bytes메모리를 사용함- 이 정도 크기는 SRAM에 들어가 반복 lookup을 빠르게 수행할 수 있음
2단계 GPU 커널과 보조 메타데이터
- 각 GPU thread는 encoded exponent의 연속된 n byte 구간을 맡음
- 실험에서는 n = 8을 사용함
- thread는 자기 구간 안에서 시작하는 Huffman code를 디코딩함
- 동적 길이 코드 때문에 두 가지 문제가 생김
- 각 thread의 정확한 시작 bit 위치가 명확하지 않음
- 첫 thread를 제외하면 decoded element의 출력 index를 알기 어려움
- 첫 문제는 Gaps 배열로 해결함
- Gaps는 thread당 하나의 항목을 가짐
- 각 항목은 thread 시작 byte 기준 첫 valid Huffman code의 bit offset을 나타냄
- 최대 code length가 32비트라 offset은
[0, 31]범위이고 5비트로 저장됨
- 출력 위치 문제는 thread block 단위 위치만 저장해 메모리 오버헤드를 줄임
- thread마다 32비트 출력 위치를 저장하면 weight matrix당 수만 개 thread에서 오버헤드가 커짐
- DFloat11은 각 thread block의 첫 element 출력 위치만 저장함
- 커널은 두 단계로 동작함
- 1단계에서 각 thread는 자기 구간을 디코딩해 element 개수만 세고 HBM에는 쓰지 않음
- block 내부 thread들은 Blelloch algorithm으로 prefix sum을 수행해 thread별 출력 위치를 계산함
- 2단계에서 같은 구간을 다시 디코딩하고, 계산된 위치에 따라 SRAM write buffer에 decoded 값을 씀
- encoded exponent는 첫 pass 전에 SRAM으로 로드해 중복 global memory access를 피함
- 모든 decoded exponent가 SRAM에 쓰인 뒤 HBM으로 coalesced write를 한 번 수행함
Transformer block 단위 압축 해제
- 단일 weight matrix 압축 해제는 크기가 작아 GPU 자원을 충분히 활용하지 못할 수 있음
- matrix 크기가 커질수록 DFloat11 압축 해제 throughput이 개선됨
- 여러 matrix를 함께 압축 해제해 throughput을 높이고 latency를 숨김
- transformer block 안의 모든 DFloat11 weight matrix를 하나의 batch로 압축 해제함
- 이 batched decompression은 해당 transformer block의 forward pass 직전에 수행됨
- LLM의 token embedding과 language modeling head도 압축 대상임
- 이 matrix들은 GPU 자원을 포화시킬 만큼 커서 별도 batching이 필요 없음
평가 결과와 실제 효과
- DFloat11은 Llama 3, Qwen 3, Mistral 3, DeepSeek R1 Distilled, FLUX.1, Stable Diffusion 3.5 등을 포함한 LLM과 diffusion transformer에서 평가됨
- 결과는 약 30% 모델 크기 감소와 원본 출력의 완전한 보존을 보임
- 출력은 원본 모델과 bit-for-bit 동일함
- 손실 압축이 아니므로 원본 BFloat16 가중치 정밀도를 유지함
- CPU로 비압축 모델 일부를 offload해 메모리 제약을 맞추는 대안과 비교하면, DFloat11은 token generation에서 2.3–46.2배 높은 throughput을 달성함
- 고정된 GPU 메모리 예산에서는 비압축 모델보다 5.7–14.9배 긴 generation length를 가능하게 함
- Llama 3.1 405B는 810GB 규모 모델이지만, DFloat11은 8×80GB A100 GPU 단일 노드에서 무손실 추론을 가능하게 함
- 이 결과는 Llama-3.1-405B 실행에 필요한 하드웨어 요구를 절반으로 줄이면서 accuracy loss 없이 추론할 수 있음을 보여줌