2P by GN⁺ | ★ favorite | 댓글 1개
  • 대형 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는 EncodedExponent byte array에 bit-packed 형태로 저장됨
    • sign과 mantissa는 PackedSignMantissa byte array에 별도로 저장됨
  • 결과적으로 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 없이 추론할 수 있음을 보여줌

댓글과 토론

Hacker News 의견들
  • 이는 bfloat16의 동적 범위가 매우 넓지만 실제로는 그 범위를 다 쓰지 않는다는 사실의 결과일 뿐임
    사람들은 하이퍼파라미터가 10^10이 아니라 0.01처럼 보이길 좋아하지만, 각 지수마다 같은 상대 정밀도를 쓸 수 있음. 네트워크의 하이퍼파라미터, 초기화된 가중치, 학습 데이터 등을 전부 10^6배 해도 상한 영역을 거의 쓰지 않기 때문에 대체로 비슷하게 동작함. 다만 일부 특수 함수는 예외일 수 있음
    가중치와 활성값에서 보이는 bfloat16 값의 전형적인 엔트로피는 10~12비트 정도이고, 실제로는 값 범위의 약 65~75%만 쓰임. 부호와 가수 비트는 압축하기 어려운 잡음에 가까움
    이런 성질은 고전적인 고성능 컴퓨팅과 AI 양쪽에서 이미 여러 번 활용됐음. Martin Burtscher 연구실의 무손실 압축 작업(https://userweb.cs.txstate.edu/~burtscher/), LLNL의 fpzip(https://computing.llnl.gov/projects/fpzip), 2021년에 만든 내 라이브러리 dietgpu(https://github.com/facebookresearch/dietgpu)가 그런 예임. 우리는 대형 GPU 클러스터에서 전송 전 모든 데이터, 예컨대 그래디언트나 백업에서 온 가중치를 무손실 압축하고 수신 시 압축 해제해서 전체 학습 벽시계 시간을 약 10% 줄였고, 무손실이므로 계산 결과는 이전과 같음
    또한 rANS는 Huffman 부호화보다 SIMD류 명령어 집합에서 더 효율적이고 구현도 쉬움. DFloat11에서도 산술 연산 전에 압축을 풀어야 하므로 지연 시간과 처리량 손실을 줄일 수 있음

    • 프로필을 굳이 눌러보지 않는 사람들을 위해 덧붙이면, Jeff는 이 분야를 정말 잘 아는 사람임. Meta/FAIR와 커뮤니티 상당수가 그의 코드 덕을 보고 있음
    • rANS에 대해 정리된 글을 알려줄 수 있는지 궁금함. 온라인에서 찾으면 난류 모델링 해법만 나오는데, 아마 그걸 말하는 건 아닐 것 같음
      양자화는 로컬 LLM 실행자에게 핵심 도구이고, 보통 RAM이 병목임. BF16 가중치에 대해 더 나은 무손실 압축이 있는지도 궁금함
      DFloat11은 기존 양자화 워크플로에 비교적 쉽게 끼워 넣을 수 있어 보이는데, 논문에 꽤 회의적인 듯해서 내가 놓친 부분을 이해하고 싶음
    • 네트워크의 모든 것을 10^6배 해도 거의 같게 동작한다는 말은 많이 의심스러움
      신경망 층에서는 입력에 가중치를 곱하고 더한 뒤 그 출력이 다음 층 입력이 되며, 이 과정이 백 번 이상 반복될 수 있음. 최종 출력층에 도달하면 그 10^6 계수가 여러 번 적용되어 10^600 수준으로 눈덩이처럼 커질 것임
    • 마지막 부록 페이지를 보면 원 논문은 DFloat11이 Llama-3.1-8b, Qwen-2.5-14b/32b, Mistral-small-24b 모델에서 초당 토큰 수를 약 2~3배 낮춘다고 보고함. 다른 모델의 처리량 손실은 보고되지 않음
      DFloat11로 초당 토큰 수가 더 높았던 경우는 일부 층을 CPU로 오프로딩해 추론한 것과 비교했을 때뿐임
      전형적인 컴퓨터 과학의 공간-속도 절충이고, 공짜 점심은 없음
    • 그렇다면 bfloat는 실수였던 건가? 애초에 목적이 동적 범위 증가 아니었나?
      그래도 잘라내고 0으로 채우는 비용은 작음
  • 가장 눈에 띄는 건 실용적 함의임. 405B 파라미터 모델을 8×80GB GPU 단일 노드에서 무손실 추론할 수 있게 한다는 건 꽤 놀라움
    거대한 인프라 비용 없이 프런티어 모델을 돌리고 싶은 연구실과 스타트업 모두에게 큰 해금 요소가 될 수 있음

    • 또는 네오클라우드 업체에 인프라 비용을 맡기고 거기서 빌려 쓰면 됨. 공개하자면, 나는 그런 업체 중 하나를 운영함
    • 이 분야 전문가는 아니라서 묻고 싶은데, 405B라는 숫자에 특별한 의미가 있나?
    • DeepSeek나 Llama 3 405B의 4비트 양자화 모델은 이미 저 GPU들에 들어가고, 전체 모델 대비 손실도 거의 0이라고 알려져 있음. 그런 점을 고려하면 그렇게 큰일 같지는 않음
    • 지금 당장은 유용하지만, 모델 크기와 GPU 메모리 크기, 다양한 정밀도 지원이 빠르게 바뀌는 세상에서 거대한 해금 요소까지는 아님
  • 이렇게 흥미로운 시대를 살아서 고마움. HN을 열 때마다 머신러닝과 트랜스포머 모델 관련 신소식이 계속 보임
    더 깊이 읽어봐야겠지만, llama.cpp가 cuBLAS와 함께 일종의 커스텀 커널을 쓰는 건지, 아니면 cuBLAS 커널을 잘 활용하는 것뿐인지 궁금함

    • 문장에서 시간 단위가 빠진 게 재미있음
      2주? 두 달? 이틀? 2분?
      어떤 때는 전부 맞음. 정말 흥미로운 시대임
  • 가중치 형식 전쟁이 정리되면 하드웨어가 그걸 지원하도록 만들어질 수 있음. 합리적으로 최적인 가중치 형식이 무엇으로 결정되든, 그에 맞춰 최적화된 행렬 곱셈 하드웨어가 필요할 것임

    • 여기서 최적화는 사후적임. Huffman 부호화를 하려면 먼저 학습을 해야 하므로, 순수한 형식 문제는 아님
  • 실제 에이전트 활용 사례에서는 품질, 비용, 성능의 균형을 맞추기 어려운 경우가 많음. 이 기법은 에이전트 비용을 최적화하려 할 때 예측하기 어려운 결과를 포함해, 양자화 기법이 만드는 절충을 피하는 데 도움이 될 수 있음
    DFloat11로 더 저렴한 GPU에 맞춰 넣을 수 있으면 경우에 따라 비용 절감이 상당할 수 있음. 나는 xmad.ai에서 일함

  • 메모리 제약 때문에 압축하지 않은 모델 일부를 CPU로 오프로딩하는 대안과 비교하면, DFloat11은 토큰 생성 처리량이 1.9~38.8배 높다고 함. 고정된 GPU 메모리 예산에서는 압축하지 않은 모델보다 5.3~13.17배 긴 문맥 길이를 가능하게 함
    문맥 길이만으로도 모델이 메모리에 들어가더라도 쓸 만해 보이지만, LLM은 메모리 대역폭에 묶이는 경우가 많다는 초보적인 이해를 기준으로 보면, 전부 GPU에 있을 때도 초당 토큰 수가 개선되는지 궁금함

    • 그렇지 않음. 압축 해제는 텐서 하나씩 메모리에서 메모리로 옮기며 수행되므로 더 나쁨
      논문에서는 A100에서 200GB/s 미만이라고 주장하고, 벤치마크상 GPU와 모델에 따라 배치 크기 1에서 1.5~4배 느린 것으로 보임. 물론 배치 크기가 충분히 커지면 이 오버헤드는 대부분 사라짐
      다른 무손실 코덱은 같은 하드웨어에서 600GB/s에 도달할 수 있으니 개선 여지는 있어 보임. 하지만 A100의 원시 메모리 대역폭은 1.6TB/s임
    • 내 머릿속 모델로는 가능할 수도 있어 보임. 느린 하드디스크에서 DOS의 DoubleSpace가 디스크 로딩을 약간 빠르게 했던 것과 비슷함
    • 모델 크기가 70%가 되면 속도는 1/0.7, 즉 1.43배가 될 것임
  • 이게 양자화하지 않은 LLM의 메모리 요구량을 보편적으로 30% 줄일 수 있다는 뜻인가? 사실이라면 꽤 큼

    • Q8 양자화가 이미 과하다고 여겨지면서도 크기를 50%로 줄이고, 추가 계산 오버헤드 없이 깔끔하게 2배 속도 향상을 주는 상황이라면 그렇게 크지는 않음. 더 흔한 Q4KM은 대략 30% 수준임
      기존 양자화에 더할 수 있다면 분명 흥미롭지만, K 양자화도 이미 전반적인 퍼플렉서티 영향에 따라 층별로 다른 정밀도를 사용함. 예를 들어 Q6은 4비트와 8비트를 섞어 쓰는데, 이는 여기서 쓰는 엔트로피 지표와 비슷함. 보정된 imatrix까지 고려하면, 개념적으로 FFT와 비슷한 방식으로 더 강하게 압축함
  • 이게 ZipNN과 다른 건가? https://arxiv.org/pdf/2411.05239
    언급은 보이는데, 그 기반인지 아니면 다르거나 더 나은 건지 이해가 안 됨

    • 찾았음. 이 소식이 이 논문을 떠올리게 했음 https://proceedings.neurips.cc/paper/2020/file/747e32ab0fea7...
    • 별로 그렇지는 않음. 데이터 전치, 즉 데이터 워드에서 개별 바이트를 모아 붙이는 작업을 조금 추가하고, 중복된 것을 압축하기 위해 LZ/사전형 압축기를 쓰는 선택지를 넣은 정도임
      하지만 LZ류 압축기는 신경망 가중치에는 큰 의미가 없어 보임. 반복이 많은 대부분의 텍스트 데이터만큼 중복성이 높지 않고, 데이터가 매우 희소하지 않다면 사전 오버헤드를 피할 만큼 활용할 반복도 많지 않을 수 있음
      LZ류 압축기를 추가하고 이를 추론의 핵심 경로에 넣으면 압축 해제가 훨씬 느려질 것임. 압축 해제를 계산 커널과 융합하는 편이 가장 좋음. 예를 들어 각 타일을 산술 연산 전에 압축 해제하는 GEMM처럼 만들 수 있고, 압축 해제 루틴이 단순할수록 이것이 쉬워짐
  • 이 모든 것이 얼마나 빠르게 움직이는지 보는 게 꽤 멋짐. 매주 새로운 효율화 기법이나 하드웨어 업그레이드가 나오는 느낌임
    이런 개선에 쉽게 관심을 빼앗기게 됨

  • 이걸 새 모델에도 실행할 수 있나? 내가 오해한 게 아니라면 코드는 추론용으로만 보임