본문 바로가기

02. bit, byte, parameter, tensor

이 장의 핵심 연결: 01장의 data path에 "무엇이 흐르는가"를 채웁니다. 그 흐름의 정체는 결국 숫자 덩어리입니다.
다음 질문: 파라미터를 담는 데 최소 얼마의 storage가 필요한가? 그리고 그 "최소"는 실제 메모리 사용량과 같은가?
목표:
  • bit·byte·parameter·tensor를 정확히 정의하고 단위 표기를 못 박는다.
  • 파라미터 수 × 비트 폭으로 weight-only storage 하한을 직접 계산한다.
  • 그 하한을 런타임 메모리 전체와 반드시 구분한다.

일상 비유: 서랍장과 서랍

숫자를 담는 저장 공간을 서랍장이라고 합시다.

  • bit(비트)는 가장 작은 칸. 0 또는 1, 딱 두 상태만 담습니다.
  • byte(바이트)는 8칸(8 bit)을 한 묶음으로 본 것. 관례적으로 저장·전송의 기본 단위입니다.
  • parameter(파라미터)는 모델이 학습으로 정한 숫자 하나. 서랍장에 든 물건 하나에 해당합니다.
  • tensor(텐서)는 그 숫자들을 정해진 모양(행·열·…)으로 담은 다차원 배열. 서랍이 격자로 정렬된 서랍장 한 짝입니다.

핵심 질문은 이겁니다. "물건 하나(파라미터 하나)를 담는 데 칸(bit)을 몇 개 쓰느냐"에 따라 서랍장 전체 크기가 정해집니다. 이 "칸 수"가 바로 03장의 정밀도(precision)입니다.

정확한 정의와 단위 표기 (여기서 못 박기)

  • bit(비트, 기호 b): 정보의 최소 단위. 0/1.
  • byte(바이트, 기호 B): 8 bit. 표기 주의 — 소문자 b는 bit, 대문자 B는 byte. 예: 8 b = 1 B.
  • parameter(파라미터): 학습으로 정해진 모델의 숫자값 하나. 흔히 가중치(weight)라 부릅니다.
  • tensor(텐서): 같은 자료형(dtype)의 숫자들을 다차원 격자에 담은 배열. 스칼라(0차원)·벡터(1차원)·행렬(2차원)·그 이상.
  • dtype(data type, 자료형): 숫자 하나를 몇 bit로, 어떤 형식으로 담는지의 규칙. 03장의 주제.
⚠️ 단위·접두어 함정 — 처음 나올 때 못 박기
"1억 파라미터가 몇 GB냐?"에서 GB의 뜻이 두 가지입니다.
  • 10진 접두어: 1 KB = 1,000 B, 1 MB = 1,000,000 B, 1 GB = 10⁹ B.
  • 2진 접두어: 1 KiB = 1,024 B, 1 MiB = 1,024² B, 1 GiB = 1,024³ B.

이름도 다릅니다: KiB/MiB/GiB(2진, "키비·메비·기비")와 KB/MB/GB(10진). 그런데 현실에선 GB라 써 놓고 2진(GiB)을 뜻하는 자료가 흔합니다. 어느 쪽 접두어인지 확인하지 않으면 약 7%(GiB vs GB) 오차가 조용히 섞입니다. 이 안내서는 계산에서 어느 쪽을 쓰는지 매번 밝힙니다.
또 하나: 대역폭은 흔히 GB/s(초당 바이트), 네트워크는 Gb/s(초당 비트)로 표기하기도 합니다(07장). b와 B를 놓치면 8배 차이납니다.

시각적 직관: 비트에서 텐서까지

flowchart LR
    BIT["bit (b)<br/>0 또는 1"]:::mem --> BYTE["byte (B)<br/>= 8 bit"]:::mem
    BYTE --> PARAM["parameter<br/>숫자 하나<br/>(= N bit, dtype이 결정)"]:::mem
    PARAM --> TENSOR["tensor<br/>파라미터들을<br/>격자 모양으로"]:::mem
    TENSOR --> MODEL["모델<br/>= 수많은 tensor의 모음"]:::compute

    classDef mem fill:#ede9fe,stroke:#7c3aed,color:#4c1d95
    classDef compute fill:#dbeafe,stroke:#2563eb,color:#1e3a8a

계산: weight-only storage 하한

이제 핵심 계산입니다. 가중치만 담는 데 필요한 최소 바이트를 구합니다.

입력 → 식 → 산술

CODE
입력:
  P = 파라미터 수 (개)
  w = 파라미터 하나당 비트 폭 (bit/parameter)   ← dtype이 결정 (03장)

식:
  storage_하한(byte) = P × w / 8
  (÷8 은 bit → byte 변환. 8 bit = 1 byte)

기호의 뜻:
  P  … 몇 개의 숫자를 담는가
  w  … 숫자 하나를 몇 bit로 담는가
  /8 … bit를 byte로 바꾸는 나눗셈

산술 예시 (가상의 조건 명시 모델)

파라미터 수 P = 7 × 10⁹(70억), 비트 폭 w = 16 bit(예: BF16 — 03장)라고 합시다.

CODE
storage_하한 = 7×10⁹ × 16 / 8
            = 7×10⁹ × 2 byte
            = 14 × 10⁹ byte
            = 14 GB   (10진, GB 기준)
            ≈ 13.04 GiB (2진, ÷1024³ 하면 14×10⁹ / 1.0737×10⁹)
  • 비트 폭을 절반(8 bit)으로 낮추면 하한도 절반(약 7 GB)이 됩니다. 이것이 03장에서 볼 정밀도-메모리 절충의 산술적 뿌리입니다.
  • 10진(GB)과 2진(GiB)을 같이 적은 이유를 보세요. 같은 14×10⁹ byte가 "14 GB"이자 "약 13 GiB"입니다. 어느 접두어인지 안 밝히면 이 차이가 숨습니다.

⚠️ 가장 중요한 구분: 하한 ≠ 런타임 메모리 전체

방금 구한 14 GB는 "가중치만"의 "하한"입니다. 실제로 요청을 처리할 때 가속기 메모리에 올라가는 것은 그보다 많습니다.

flowchart TB
    subgraph RUNTIME["런타임 메모리 전체 (실제 사용량)"]
        W["가중치 storage 하한<br/>P×w/8 ← 방금 계산한 것"]:::mem
        A["활성값(activation)<br/>계산 중간 산물"]:::compute
        K["KV 캐시<br/>생성이 길수록·동시요청 많을수록 증가"]:::mem
        O["기타: 작업 버퍼,<br/>단편화, 런타임 오버헤드"]:::warn
    end

    classDef mem fill:#ede9fe,stroke:#7c3aed,color:#4c1d95
    classDef compute fill:#dbeafe,stroke:#2563eb,color:#1e3a8a
    classDef warn fill:#fee2e2,stroke:#dc2626,color:#7f1d1d
📌 핵심: P × w / 8"가중치를 담는 데 필요한 최소 바이트"일 뿐입니다. 런타임 메모리 전체 = 가중치 + 활성값 + KV 캐시 + 각종 버퍼·오버헤드. 하한을 실제 사용량으로 착각하면, "14 GB 가속기면 70억 파라미터 모델이 딱 들어간다"는 식의 잘못된 결론에 빠집니다. 실제로는 캐시·활성값 자리가 없어 안 들어갈 수 있습니다.

KV 캐시가 왜 메모리를 쓰는지, 왜 요청 길이·동시성에 따라 커지는지는 06장에서 다룹니다. 지금은 "하한은 바닥이지, 천장이 아니다"만 챙기면 됩니다.

조건 명시: 이 계산이 성립하는·성립하지 않는 범위

내용
성립하는 조건P × w / 8모든 파라미터가 동일한 dtype으로 촘촘히(밀집) 저장된다고 가정할 때의 가중치 storage 하한입니다. 산술 자체는 dtype·하드웨어와 무관하게 정확합니다(calculated).
성립하지 않는 결론이 값은 런타임 메모리 사용량이 아닙니다. 또한 dtype이 섞이거나(혼합 정밀도), 양자화가 블록 단위 스케일·메타데이터를 동반하거나, 저장 포맷이 압축·정렬 오버헤드를 가지면 실제 파일/메모리 크기는 하한과 달라집니다. "하한 = 실제"로 읽으면 안 됩니다.

🔬 증거 읽기: 이 수치는 어떤 유형인가

  • storage_하한 = P × w / 8으로 나온 14 GB는 calculated(계산값)입니다 — 공개 입력(P, w)과 식을 남긴 산술이므로 누구나 재현 가능합니다.
  • 반면 "이 모델은 실제로 메모리를 XX GB 쓴다"는 주장은 measured(측정값)여야 하며, 측정 조건(생성 길이·동시 요청 수·런타임)을 밝혀야 합니다.
  • calculated와 measured를 같은 표에 나란히 놓고 순위 매기면 안 됩니다. 하한(계산)과 실사용(측정)은 다른 축입니다.

이 장에서 배운 것

  • bit(b) ≠ byte(B), 10진(GB) ≠ 2진(GiB) — 표기·접두어를 매번 확인한다.
  • 가중치 storage 하한 = P × w / 8. 비트 폭을 절반으로 낮추면 하한도 절반.
  • 이 하한은 가중치만·최소치다. 런타임 메모리 전체 = 가중치 + 활성값 + KV 캐시 + 버퍼·오버헤드.
  • 하한은 calculated, 실사용은 measured — 다른 축이므로 섞어 순위 매기지 않는다.

🔎 이 장의 '지지하지 않는 결론'

  • P × w / 8으로 "이 가속기에 이 모델이 들어간다/안 들어간다"를 단정할 수 없다. 그건 런타임 메모리 전체를 알아야 하고, 이 장은 하한만 다룬다.
  • 이 계산으로 "어느 정밀도가 더 낫다"를 말할 수 없다. 메모리 하한이 준다고 품질·수치 범위까지 좋아지는 건 아니다(03장).

✍️ 확인 문제

  1. P = 3×10⁹, w = 8 bit일 때 가중치 storage 하한을 GB(10진)로 계산하세요. 식과 산술을 남기세요.
  2. "storage 하한이 14 GB이니, 16 GB 메모리 가속기면 이 모델로 추론이 된다"는 주장의 빠진 전제는 무엇인가요? 무엇을 더 알아야 하나요?
  3. [peak/measured/calculated/inferred 묻기] P × w / 8로 얻은 14 GB는 measured/calculated/inferred 중 무엇인가요? 그 이유는? 반대로 "실측 메모리 20 GB"는 무엇이며, 왜 둘을 같은 표에서 순위 매기면 안 되나요?
다음 장: 03 · FP32, FP16, BF16, INT8, INT4 — 이 장의 "비트 폭 w"를 선택지로 엽니다. 정밀도를 낮추면 무엇을 얻고(storage·대역폭) 무엇을 바꾸는지(수치 범위·품질·커널 지원)를 절충으로 읽습니다.