TL;DR
저희가 공개한 Darwin-180B-RSI-R3 가중치를 다른 분들이 GGUF로 양자화해 올려 두었습니다. HF에서 이 모델을 기반으로 표시한 양자화 저장소는 7곳이고, 그중 GGUF 저장소 4곳의 파일 6개를 골라 GGUF 헤더를 열어 파일 안에서 바이트가 어디로 가는지 계산했습니다. 파일 전체를 받지 않고 앞부분만 HTTP Range로 읽었습니다.
가장 눈에 띈 것은 이름과 크기의 어긋남입니다. 이름에 TQ2_0이 붙은 파일은 91.97GB인데, Q3_K_S라는 이름의 파일은 90.00GB, IQ3_XXS라는 이름의 파일은 75.84GB입니다. 2비트 이름이 3비트 이름보다 큽니다. 이유는 이 모델의 구조에 있습니다. GGUF에 담긴 파라미터 1,769억 개 가운데 512억 개(28.9%)가 per_layer_token_embd라는 조회용 표이고, 이 표는 양자화 이름과 상관없이 4.5비트 또는 8.5비트로 고정되어 있었습니다. 이름에 적힌 비트 수는 나머지 전문가(experts) 쪽을 가리키는 경우가 많았습니다.
이 글의 수치는 전부 공개 파일에서 저희가 계산한 값입니다. 파일의 품질이나 속도는 재지 않았고, 추론도 돌리지 않았습니다. 열어 본 저장소 4곳 가운데 POCKET-Darwin-180B-GGUF는 저희 것이고 나머지 3곳은 다른 분들이 만든 파일입니다.
양자화 이름의 비트 수로 파일 크기를 어림하면 왜 틀리나요?
보통은 이렇게 어림합니다. 1,800억 개 파라미터에 3비트면 67.5GB, 2비트면 45GB입니다. 이 계산이 맞으려면 이름의 비트 수가 모든 텐서에 똑같이 적용되어야 합니다. 실제 GGUF는 텐서마다 다른 형식을 씁니다. 헤더에는 텐서마다 이름, 차원, 형식 번호가 적혀 있어서, 파라미터 수와 형식별 블록 크기만 알면 텐서가 차지하는 바이트를 정확히 셀 수 있습니다.
아래 표가 그렇게 센 결과입니다. 「조회용 표」는 per_layer_token_embd.weight 하나이고, 「전문가」는 라우팅되는 전문가 텐서 전체입니다.
| 파일 | 크기(GB) | 조회용 표(GB) | 전문가(GB) | 전문가 평균 bit | 파일 전체 평균 bit |
|---|---|---|---|---|---|
| zacaj 「IQ3_XXS」 | 75.84 | 28.80 (IQ4_NL) | 42.92 | 2.84 | 3.43 |
| zacaj 「TQ2_0」 | 91.97 | 54.40 (Q8_0) | 32.09 | 2.13 | 4.16 |
| mradermacher Q2_K | 81.51 | 28.80 (Q4_0) | 50.10 | 3.25 | 3.63 |
| mradermacher Q3_K_S | 90.00 | 28.80 (Q4_0) | 58.45 | 3.79 | 4.01 |
| mradermacher Q3_K_M | 95.49 | 28.80 (Q4_0) | 63.74 | 4.14 | 4.25 |
| POCKET Q4_K_XL (자사) | 111.33 | 28.80 (IQ4_NL) | 77.02 | 5.10 | 5.03 |
표를 읽는 방법은 간단합니다. 전문가 평균 bit만 보면 TQ2_0 파일이 2.13으로 가장 낮고 POCKET 파일이 5.10으로 가장 높습니다. 그런데 「파일 전체 평균 bit」 열은 TQ2_0 파일에서 4.16으로 올라가 Q3_K_S의 4.01을 넘어섭니다. 조회용 표가 Q8_0으로 저장되어 54.40GB를 차지하기 때문입니다. 같은 표가 다른 파일에서는 28.80GB입니다.
전체 평균 bit를 계산할 때 분모는 GGUF 안의 파라미터 수입니다. zacaj 파일 두 개와 POCKET 파일은 1,769억 4,390만 개이고, mradermacher 파일은 1,795억 5,105만 개입니다. 차이 26억 715만 개는 mradermacher 파일에만 49번째 블록(blk.48, nextn_predict_layers가 1로 적힌 다음 토큰 예측 층)이 들어 있어서 생깁니다. 두 숫자를 직접 더하면 맞아떨어집니다.
어떤 파일을 열어 봤고, 어떻게 열었나요?
2026년 11월 9일 HF API에서 base_model:quantized:FINAL-Bench/Darwin-180B-RSI-R3 필터로 조회하면 저장소 7곳이 나옵니다. zacaj 2곳, mradermacher 1곳, Cianidos 2곳, scorpoon 1곳, 그리고 저희의 POCKET-Darwin-180B-GGUF입니다.
이 가운데 GGUF 헤더를 읽을 수 있는 곳은 zacaj 2곳, mradermacher, POCKET의 4곳입니다. mradermacher는 양자화 변형이 여러 개라서 그중 Q2_K, Q3_K_S, Q3_K_M 3개를 골랐고, 그렇게 파일 6개(샤드로 나뉜 것을 풀면 13조각)를 열었습니다. Cianidos의 두 저장소는 GGUF가 아니라 Apple Silicon용 Sushi 형식이라 헤더 대신 저자 README를 읽었습니다. scorpoon 저장소는 조회 시점에 README, LICENSE, 평가 결과 JSON 등 4개 파일(39,917바이트)뿐이고 가중치 파일이 목록에 없었습니다. 태그로 센 파생 모델 수와 지금 내려받을 수 있는 파일 수는 다를 수 있다는 뜻입니다.
계산이 맞는지는 이렇게 점검했습니다. 파일 크기에서 헤더 크기(data_start)를 빼면 텐서 바이트의 합과 같아야 합니다. 13조각 가운데 9조각은 1바이트도 틀리지 않았습니다. 1조각(POCKET 첫 샤드)은 텐서가 없는 메타데이터 샤드입니다. 나머지 3조각은 mainline ggml 표에 없는 형식 번호(42와 144)가 들어 있어서 그 부분만 「파일 크기에서 나머지를 뺀 값」으로 역산했습니다. 형식 번호 42는 2.25비트(250억 개), 144는 2.125비트(1,208억 개)로 나왔습니다. 이 두 값은 다른 텐서가 전부 맞는다는 가정에서 나온 역산이라 계산값이 아니라 추정값으로 읽어 주십시오.
파라미터의 28.9%가 왜 조회용 표인가요?
헤더에서 가장 큰 단일 텐서는 per_layer_token_embd.weight이고 모양은 [160, 320001536], 즉 파라미터 51,200,245,760개입니다. 이 값은 Darwin-180B-RSI-R3의 전체 파라미터 179,999,981,459개 가운데 28.4%, GGUF 안의 1,769억 개 가운데 28.9%입니다. 행렬곱에 들어가는 가중치라기보다 행 번호로 꺼내 쓰는 표이고, 행 하나가 160개 원소입니다.
행 하나의 크기는 IQ4_NL(4.5비트)로 저장되면 90바이트, Q8_0(8.5비트)이면 170바이트입니다. 토큰 하나를 처리할 때 이 표에서 몇 행을 읽는지는 이 글에서 확인하지 않았습니다. 다만 몇백 행이라도 수십 KB 수준이라 28.8GB 표 전체와는 비교가 되지 않습니다. 표를 통째로 메모리에 올릴 이유가 약하다는 뜻이고, 실제로 Cianidos의 README는 이 표(n-gram table)를 디스크에 두고 읽는 방식(disk-backed)으로 설명합니다.
Cianidos 팩에서 하나 더 확인할 수 있었습니다. ngram_table.bin은 32,000,153,944바이트인데, 512억 개를 5비트로 계산하면 32,000,153,600바이트입니다. 차이 344바이트는 파일 머리말 정도의 크기입니다. README에 적힌 「4비트, 그룹 크기 32」에 그룹마다 붙는 스케일과 바이어스가 합쳐져 5비트가 된 것으로 보이고, 같은 512억 개짜리 표가 서로 다른 형식으로 저장된 사례입니다.
이름과 안쪽 구성은 얼마나 다른가요?
파일마다 사정이 달랐습니다.
zacaj의 「TQ2_0」 파일은 전문가 텐서 1,208억 개가 전부 형식 번호 144이고, 역산한 크기는 32.09GB(2.125비트)입니다. mainline의 TQ2_0은 형식 번호 35에 2.0625비트라서 번호가 다릅니다. 나머지는 거의 Q8_0입니다. 조회용 표 54.40GB, 어텐션 약 3.19GB 등이 그렇습니다. 이 저장소의 README에 따르면 만든 분은 agentionai의 Gyro-M 전문가를 가져와 Darwin 쪽 나머지 가중치와 합쳤다고 합니다. 파일 이름은 그 결과물에 붙인 이름표이고, 이름이 실제 구성을 대변하지 않을 수 있다는 점을 저희는 이 파일에서 처음 확인했습니다. 참고로 이 파일의 general.file_type 값은 7이었습니다. 저희가 아는 llama.cpp 열거형에서는 Q8_0에 해당하는 번호입니다.
zacaj의 「IQ3_XXS」 파일은 전문가 안에서만 7가지 형식이 섞여 있습니다. IQ2_XXS, IQ2_XS, IQ2_S, IQ3_XXS, IQ3_S, IQ4_NL, 그리고 번호 42입니다. 전문가 평균은 2.84비트이고, 이름의 3.06비트(IQ3_XXS 단독)와도 다릅니다. 이 파일은 ISTA-DASLab의 GSQ-RCO 전문가를 가져온 것이라고 README에 적혀 있습니다.
mradermacher의 Q2_K에서는 ffn_down_exps 49개 텐서가 전부 Q4_0이고, ffn_gate_exps와 ffn_up_exps만 Q2_K입니다. 전문가 파라미터의 정확히 3분의 1인 411억 개가 4.5비트라는 뜻입니다. Q3_K_S도 같은 411억 개가 Q4_0이라서 Q2_K에서 Q3_K_S로 올라갈 때 늘어나는 용량은 8.49GB(81.51에서 90.00)뿐입니다. 이름은 2비트에서 3비트로 올라가는데 파일은 10.4%밖에 늘지 않습니다.
Cianidos 저자는 README에서 이 문제를 직접 짚어 두었습니다. 2.5bpw는 라우팅된 전문가의 코드율이지 모든 텐서의 평균이나 다운로드 크기가 아니라고 적었고, 실제 내려받는 크기는 45.33GB(가중치 샤드)에 32.00GB(n-gram 표)를 더한 약 77.36GB라고 밝혔습니다. 이 글의 표가 말하려는 것과 같은 이야기를 저자가 먼저 정리해 둔 셈입니다.
그러면 메모리는 얼마나 필요한가요?
파일 크기만 보고 RAM을 정하면 틀릴 수 있다는 것이 이번 계산의 실용적인 결론입니다. 조회용 표를 메모리에 올리지 않는다는 가정에서 최소한 필요한 양은 「파일 크기 빼기 표 크기」입니다. 계산값은 이렇습니다.
| 파일 | 파일 크기(GB) | 표 제외 하한(GB) | 저자 README의 RAM 자기보고 |
|---|---|---|---|
| zacaj 「IQ3_XXS」 | 75.84 | 47.04 | 약 50GB |
| zacaj 「TQ2_0」 | 91.97 | 37.57 | 약 45GB |
| mradermacher Q2_K | 81.51 | 52.71 | 없음 |
| mradermacher Q3_K_S | 90.00 | 61.20 | 없음 |
| mradermacher Q3_K_M | 95.49 | 66.69 | 없음 |
| POCKET Q4_K_XL (자사) | 111.33 | 82.53 | 없음 |
zacaj 두 파일의 README에는 자신의 환경에서 RAM을 각각 약 50GB, 약 45GB 쓴다고 적혀 있습니다. 저희 계산의 하한(47.0GB, 37.6GB)보다 3GB와 7GB 높습니다. 하한을 넘고 있으니 앞뒤가 어긋나지는 않지만, 이것이 「표가 메모리에 올라오지 않는다」는 가설을 증명하지는 않습니다. 저자 본인이 적은 숫자이고, 저희는 재현하지 않았습니다. KV 캐시와 활성화 메모리는 위 하한에 들어 있지 않습니다. 그래도 하한만 비교하면 92GB짜리 TQ2_0 파일(37.6GB)과 90GB짜리 Q3_K_S 파일(61.2GB)은 파일 크기가 거의 같은데 필요한 메모리는 크게 다를 수 있다는 점은 분명합니다.
직접 확인하려면 어떻게 하나요?
GGUF 헤더는 파일 맨 앞에 있습니다. 샤드마다 Range 요청으로 앞부분만 읽으면 됩니다. 토크나이저가 들어 있는 첫 샤드는 헤더가 약 11MB라서 16MB를 요청하면 충분했고(mradermacher 단일 파일도 16MB로 파싱됐습니다), 텐서가 하나뿐인 샤드는 4KB로 끝납니다. 아래는 저희가 쓴 코드를 줄인 것입니다. 표(BLK)에는 흔한 형식 몇 개만 넣었으므로, 표에 없는 형식(F32, BF16, 위의 번호 42 같은 것)은 바이트를 None으로 돌려줍니다. 전체 계산에서는 ggml 형식 표를 더 채워 쓰고, 그래도 모르는 번호는 파일 크기에서 나머지를 빼서 역산했습니다.
import struct, urllib.request F = {0:'B', 1:'b', 2:'H', 3:'h', 4:'I', 5:'i', 6:'f', 7:'?', 10:'Q', 11:'q', 12:'d'} BLK = {8:(32,34), 10:(256,84), 11:(256,110), 12:(256,144), 14:(256,210), 18:(256,98), 20:(32,18)} # 형식 번호: (원소 수, 바이트) class Buf: def __init__(s, b): s.b, s.p = b, 0 def u(s, f): v = struct.unpack_from('<' + f, s.b, s.p)[0]; s.p += struct.calcsize(f); return v def text(s): n = s.u('Q'); v = s.b[s.p:s.p + n]; s.p += n; return v.decode('utf-8', 'replace') def skip(s, t): if t == 8: s.text() elif t == 9: et, n = s.u('I'), s.u('Q') for _ in range(n): s.skip(et) else: s.p += struct.calcsize(F[t]) def tensor_table(url, n=16_000_000): req = urllib.request.Request(url, headers={'Range': f'bytes=0-{n-1}', 'User-Agent': 'x'}) r = Buf(urllib.request.urlopen(req).read()) assert r.b[:4] == b'GGUF'; r.p = 8 n_tensors, n_kv = r.u('Q'), r.u('Q') for _ in range(n_kv): r.text(); r.skip(r.u('I')) rows = [] for _ in range(n_tensors): name = r.text(); dims = [r.u('Q') for _ in range(r.u('I'))]; ty = r.u('I'); r.u('Q') params = 1 for d in dims: params *= d el, by = BLK.get(ty, (None, None)) rows.append((name, dims, ty, params, params // el * by if el else None)) return rows zacaj IQ3_XXS 파일의 두 번째 샤드를 4KB만 읽어 돌리면 이렇게 나옵니다.
per_layer_token_embd.weight [160, 320001536] type 20 params 51200245760 bytes 28800138240 bpw 4.5 샤드 전체 크기는 28,800,138,432바이트이고, 텐서 바이트에 헤더 192바이트를 더하면 정확히 같습니다.
이 계산이 말해 주지 못하는 것은 무엇인가요?
첫째, 품질입니다. 어느 파일이 더 정확한지는 재지 않았습니다. 일부 저장소 README에는 만든 분이 직접 돌린 벤치마크 수치가 있지만, 저희는 재현하지 않았고 이 글에서도 쓰지 않았습니다. 둘째, 속도와 실제 RAM 사용량도 측정하지 않았습니다. 셋째, 형식 번호 42와 144의 바이트는 역산한 추정값입니다. 넷째, 텐서 역할(조회용 표, 전문가)은 텐서 이름 규칙으로 분류했습니다. 다섯째, 표의 저장소 상태는 2026년 11월 9일 조회 기준이라 만든 분이 파일을 바꾸면 달라질 수 있습니다. 여섯째, POCKET 파일은 저희 것이므로 같은 방식으로 계산해 같은 표에 넣었을 뿐, 다른 파일과 우열을 가린 것이 아닙니다.
자주 묻는 질문
GGUF 양자화 이름의 비트 수는 파일 전체의 평균 비트인가요?
이 모델의 파일 6개에서는 아니었습니다. 이름은 전문가 텐서의 코드율이거나 만든 도구의 이름표인 경우가 많았고, 파일 전체 평균은 3.43에서 5.03비트까지 따로 움직였습니다. 헤더에서 텐서별 형식을 읽으면 정확한 값을 알 수 있습니다.
파일 크기가 크면 RAM도 그만큼 필요한가요?
조회용 표처럼 통째로 올릴 필요가 없는 텐서가 파일의 상당 부분을 차지하면 그렇지 않을 수 있습니다. 이 글의 계산으로는 표를 뺀 하한이 파일 크기의 41%(TQ2_0 파일)에서 74%(POCKET 파일) 사이였습니다. 실제 사용량은 실행 엔진과 문맥 길이에 따라 달라지므로 직접 재어야 합니다.
per_layer_token_embd는 무엇인가요?
공개 파일에서 확인한 사실은 모양이 [160, 320001536]이고 파라미터가 512억 개이며 파일마다 4.5비트에서 8.5비트로 저장되어 있다는 것까지입니다. 모델 구조의 정확한 설명은 모델 카드와 코드를 확인해 주십시오.
왜 어떤 파일은 형식 번호를 알 수 없나요?
번호 42와 144는 mainline ggml의 형식 표에 없는 번호였습니다. 포크나 실험 빌드에서 쓰는 형식으로 보이는데, 이 글에서는 출처를 확인하지 못했습니다. 그래서 그 부분만 파일 크기에서 역산했습니다.
어느 파일을 받는 것이 좋나요?
품질을 재지 않았으므로 추천하지 않습니다. 고를 때는 파일 이름의 비트 수보다 헤더의 형식 분포, 전문가 평균 비트, 조회용 표의 저장 형식, 그리고 자기 환경에서 잰 RAM 사용량을 보시기 바랍니다.
