Models & AlgorithmsEN

TurboQuant llama.cpp CUDA 포크, A100에서 실측 — turbo4는 q4_0급, turbo3는 긴 컨텍스트에서 무너진다

Qwen3-8B Q4_K_M, A100 한 장, KV 타입 6종: perplexity·프리필·깊이별 디코드·VRAM 실측. turbo4는 q4_0과 품질 동급에 깊은 컨텍스트에선 q8_0보다 2.5배 빠르고, turbo3는 32K에서 PPL이 세 배로 뜁니다.

TurboQuant llama.cpp CUDA 포크, A100에서 실측 — turbo4는 q4_0급, turbo3는 긴 컨텍스트에서 무너진다

TurboQuant llama.cpp CUDA 포크, A100에서 실측 -- turbo4는 q4_0급, turbo3는 긴 컨텍스트에서 무너진다

llama.cpp용 TurboQuant 수치로 돌아다니는 것들은 Apple Silicon(Metal)과 소비자용 RTX에서 나왔습니다. 저희 질문은 달랐습니다. 데이터센터 GPU에서, 사람들이 실제로 서빙하는 모델로, 사람들이 건너뛰는 측정 -- *긴 컨텍스트에서의* perplexity, *캐시가 가득 찬 상태의* 디코드 속도, VRAM -- 을 하면 CUDA 포크는 어떻게 되는가.

설정: Qwen3-8B Q4_K_M, A100 80GB 한 장, spiritbuun CUDA 포크-DGGML_CUDA=ON sm80으로 빌드, flash attention 켬, KV 캐시 타입 6종(f16, q8_0, q4_0, turbo4, turbo3, turbo2) + 커뮤니티가 권하는 비대칭 K/V 조합 둘. 아래 숫자는 전부 이 머신에서 나왔고 JSON 로그를 첨부합니다.

결과 넷:

  1. turbo4는 진짜 q4_0 대체재입니다 -- perplexity 동일(f16 대비 +0.65%), 27% 더 작고, 이 커널에서 64K 컨텍스트 디코드가 q8_0/q4_0보다 2.5배 빠릅니다.
  2. turbo3는 4K에서는 괜찮고 16K면 망가집니다. perplexity가 4K +5.5% → 8K +24% → 16K +210%로 뜁니다. 컨텍스트 길이를 확인하지 않고 배포하지 마세요.
  3. 이 포크의 양자화 KV 어텐션 경로는 A100에서 q8_0/q4_0에 느립니다 -- 64K 깊이에서 f16 속도의 29%로 디코드합니다. TurboQuant 커널이 더 낫고, f16이 가장 빠릅니다.
  4. 비대칭 조합 K q8_0 / V turbo3는 거의 무손실(+0.18%)이지만 q8_0의 느린 디코드를 물려받습니다.

이 글은 TurboQuant 시리즈 Part 5입니다. 왜 이게 본류가 아니라 포크인지는 Part 3, 알고리즘을 직접 구현해 *왜* 이런 숫자가 나오는지 설명한 글은 Part 6입니다.

1. 무엇을 쟀나, 왜 이 넷인가

TurboQuant 벤치마크 대부분은 llama-bench 프리필 처리량과 -c 512-c 4096의 perplexity를 보고합니다. KV 압축이 공짜로 보이게 만드는 숫자들입니다. KV 압축이 바꾸는 바로 그것 -- 디코드 스텝마다 큰 양자화 캐시를 읽는 일 -- 을 건드리지 않기 때문입니다.

그래서 이렇게 쟀습니다.

  • perplexity: wikitext-2, 컨텍스트 4,096(40청크), 그리고 8K / 16K / 32K에서 다시 -- 각 토큰이 어텐션하는 양자화 컨텍스트 양에 따라 품질이 어떻게 변하는지.
  • 프리필 처리량: 8K·32K 프롬프트(llama-bench -p).
  • 깊이별 디코드 처리량: 캐시에 8K·32K·64K 토큰이 이미 든 상태에서의 생성 tok/s(llama-bench -d). KV 대역폭을 반영하는 유일한 속도 지표입니다.
  • 최대 VRAM: 32K 컨텍스트, 단일 청크 perplexity 실행 중 nvidia-smi로 샘플링.

모델: Qwen3-8B(36 레이어, KV 헤드 8, 헤드 차원 128 → 토큰당 f16 KV 144 KiB). 가중치 Q4_K_M(4.68 GiB).

2. 4K perplexity: turbo4 = q4_0, turbo3는 5% 비용

!f16 KV 대비 perplexity 변화

KV 타입값당 비트(근사)PPL @4Kf16 대비
f16168.319 ± 0.084--
q8_08.58.318+0.00%
q4_04.58.374+0.66%
turbo44.258.373+0.65%
turbo33.258.776+5.5%
turbo22.2515.23+83%
K q8_0 / V turbo35.98.333+0.18%
K turbo4 / V turbo33.758.407+1.06%

4K 컨텍스트에서는 이야기가 깔끔합니다. turbo4는 더 적은 비트로 q4_0에 정확히 얹힙니다(8.373 vs 8.374). turbo3는 5.5% -- Qwen3.5-35B Metal에서 보고된 "+1%"보다 눈에 띄게 크고, 작은 모델이 더 민감하다는 패턴과 일치합니다. turbo2는 쓸 수 없습니다. 그리고 키를 q8_0에 두고 값만 turbo3로 내리면 f16과 노이즈 범위 안입니다 -- 커뮤니티가 발견한 K/V 비대칭은 실재하고 큽니다.

3. 컨텍스트 길이별 perplexity: turbo3가 무너진다

저희 권고를 바꾼 측정입니다. 같은 모델, 같은 파일, 각 토큰이 더 많은 양자화 캐시에 어텐션하도록 컨텍스트 창을 넓힌 perplexity:

KV 타입ctx 8Kctx 16Kctx 32K
f167.907.609.09
turbo48.04 (+1.8%)7.71 (+1.5%)9.18 (+1.0%)
turbo39.76 (+23.6%)23.56 (+210%)26.67 (+193%)
K q8_0 / V turbo37.91 (+0.1%)7.62 (+0.4%)9.10 (+0.1%)
K turbo4 / V turbo38.12 (+2.8%)7.73 (+1.8%)9.20 (+1.2%)

각 셀은 wikitext-2 3청크 평균 perplexity(f16 대비 변화율)입니다. 컨텍스트가 길수록 청크 수가 적어 절대값의 신뢰구간이 넓지만, 타입 간 비교는 같은 텍스트 위에서 이뤄집니다.

turbo4는 완만하게 나빠집니다. turbo3는 아닙니다. 32K에서 perplexity가 f16의 대략 세 배입니다. turbo3가 키마다 넣는 오차가 무엇이든, 쿼리가 순위를 매겨야 하는 키 수에 비례해 누적되고, 3.25비트에서는 softmax가 올바른 키를 더는 찾지 못합니다. 커뮤니티의 "context-scaling regression" 보고는 Metal에서의 장문 *속도* 문제였습니다. 이것은 CUDA에서의 *품질* 퇴행이고, 훨씬 심합니다.

비대칭 K q8_0 / V turbo3 조합은 컨텍스트 길이에 걸쳐 평평합니다 -- 피해가 키 쪽에 있다는 또 하나의 신호입니다. 3비트 값을 원하면 키는 8비트로 두세요.

실무 규칙: 이 포크에서 turbo3는 4K 이하 컨텍스트용 설정입니다 -- 8K에서 이미 +24%입니다. 그보다 길면 turbo4나 비대칭 조합.

4. 속도: 프리필은 싸고, 깊이별 디코드에서 타입이 갈린다

!프리필·디코드 처리량, f16 대비

프리필(tok/s, 높을수록 좋음):

KV 타입pp 8Kpp 32Ktg 128 (빈 컨텍스트)
f164,5113,342152.5
q8_04,3853,205135.9
q4_04,3793,194135.3
turbo44,071 (−10%)2,788 (−17%)130.2
turbo33,969 (−12%)2,953 (−12%)92.4 (−39%)
turbo24,0613,011116.1

A100에서 turbo 타입의 프리필 비용은 10~17%입니다. 저장 경로의 Walsh-Hadamard 회전과 코드북 조회가 이 커널에서는 공짜가 아닙니다 -- "q8_0보다 2% 빠르다"는 Metal 결과와 다릅니다. turbo3는 빈 컨텍스트 디코드부터 f16보다 39% 느린데, 토큰당 역양자화 비용을 암시합니다.

이제 중요한 숫자 -- 캐시가 가득 찬 디코드:

!8K·32K·64K 깊이의 디코드 tok/s

KV 타입디코드 @8K@32K@64K@64K f16 대비
f16134.7103.979.6100%
turbo4111.179.557.873%
turbo380.458.442.654%
q8_083.939.522.829%
q4_082.338.021.727%
K q8_0 / V turbo372.937.522.929%

놀라운 점 둘. 첫째, 이 포크의 CUDA 빌드에서 q8_0q4_0는 깊은 컨텍스트에서 디코드가 형편없습니다 -- 64K에서 f16의 30% 미만입니다. 양자화 KV의 flash-attention 경로가 텐서코어를 쓰지 않는 "vec" 커널이라 장문에서 그 비용이 지배합니다. 둘째, TurboQuant 커널이 양자화 옵션 중 가장 빠릅니다: 64K에서 turbo4q8_0보다 2.5배, q4_0보다 2.7배 빠릅니다. 포크의 어텐션 내 fused 역양자화 경로는 분명히 깊이를 염두에 두고 짜였습니다.

그래도 f16이 가장 빠릅니다. 80GB 카드에 8B 모델이면 128K를 한참 넘기 전까지는 메모리 때문에 캐시를 압축할 *필요*가 없고, 그 전까지는 f16이 품질도 속도도 최고입니다. 큰 GPU에서 KV 압축은 속도가 아니라 용량의 결정입니다.

5. 32K 컨텍스트의 VRAM

!32K 컨텍스트 최대 VRAM

KV 타입최대 VRAM @32Kf16 대비추정 KV 캐시
f169.86 GB--~4.8 GB
q8_07.70 GB−2.2 GB~2.6 GB
q4_06.55 GB−3.3 GB~1.4 GB
turbo46.57 GB−3.3 GB~1.3 GB
turbo36.40 GB−3.5 GB~1.0 GB
turbo26.11 GB−3.7 GB~0.7 GB
K q8_0 / V turbo37.12 GB−2.7 GB~1.8 GB

최대 VRAM에는 Q4_K_M 가중치 4.7GB와 컴퓨트 버퍼 ~0.4GB가 포함되고, 차이는 KV 캐시입니다. 32K 토큰의 f16 KV는 해석적으로 4.83GB(36 레이어 × 8 헤드 × 128 × 2 × 2바이트 × 32,768)이고, 측정된 차이는 명목 bpv를 잘 따라갑니다. turbo4q4_0는 크기가 같습니다. 둘 사이의 선택은 속도와 품질인데, 둘 다 turbo4 편입니다.

이게 중요해지는 곳: 70B Q4_K_M 모델은 80GB A100에 ~34GB를 남기고, 70B(80 레이어, KV 헤드 8)의 128K f16 KV는 ~40GB입니다. turbo4가 "안 들어감"을 "배치 여유 있게 들어감"으로 바꾸는 경우입니다.

6. 권고 (A100, 이 포크)

상황선택이유
캐시가 VRAM에 들어감f16가장 빠르고 무손실. 얻을 게 없음
~3.5배 작은 캐시, 컨텍스트 무관`turbo4`q4_0 품질, 깊은 컨텍스트에서 q8_0/q4_0보다 2.5배 빠른 디코드
거의 무손실 + 약간의 절약-ctk q8_0 -ctv turbo3+0.18% PPL, 컨텍스트에 걸쳐 평평 -- 단 q8_0의 느린 깊이 디코드
짧은 컨텍스트(≤4K), 최대 압축turbo34K에서 +5.5% PPL, 4.9배 압축
8K 이상 컨텍스트`turbo3` 금지8K에서 +24%, 16K에서 세 배
어떤 경우든turbo2 금지4K에서 +83%, 32K에서 약 60배

그리고 메타 권고 하나: 실제로 서빙하는 컨텍스트 길이에서 llama-perplexity를 반드시 돌리세요. 4K perplexity는 turbo3가 괜찮다고 했습니다. 아닙니다.

7. 재지 않은 것

  • 태스크 정확도(needle-in-a-haystack, GSM8K) -- Part 4가 vLLM에서 합니다.
  • 배치 > 1. llama-bench 디코드는 단일 스트림이라 배치 서빙에서는 대역폭 그림이 바뀝니다.
  • 다른 GPU. q8_0/q4_0의 깊이 페널티는 sm80에서 이 포크의 CUDA flash-attention 경로에 특유한 것이고, 본류 llama.cpp나 Hopper는 다를 수 있습니다.
  • 다른 모델. 전부 Qwen3-8B입니다. Llama-3.1-8B나 70B에서는 turbo3의 임계가 움직일 수 있습니다.

재현: 포크 빌드(cmake -B build -DGGML_CUDA=ON -DCMAKE_CUDA_ARCHITECTURES=80) 후 첨부 번들의 bench-llamacpp-tq.sh, bench-llamacpp-depth.sh, ctxscale.sh, kvmem-probe.sh. A100 한 장 기준 총 약 2.5시간.

참고 자료

더 많은 콘텐츠를 받아보세요

SNS에서 새로운 글과 튜토리얼 소식을 가장 먼저 받아보세요

이메일로 받아보기

관련 포스트