트랜스포머·PEFT 2일 과정6장 · Qwen 모델 준비와 텍스트 생성5 / 17← 이전목차다음 →MetaContents

6장. Qwen 모델 준비와 텍스트 생성

모델 크기와 GPU 메모리

이삿짐을 트럭에 싣기 전에는 상자 수 × 상자 하나의 부피로 짐의 크기를 어림합니다. 모델도 같습니다. 가중치만 올릴 때 필요한 메모리는 파라미터 수 × 파라미터 1개당 바이트 수 로 어림합니다. 상자 수(파라미터 수)는 모델이 정하고, 상자 크기(바이트 수)는 우리가 고르는 정밀도가 정합니다.

FP32, BF16, INT8, 4bit 네 가지 정밀도에서 0.49B 모델의 가중치 크기를 나란히 놓은 비교 그림

그림의 네 상자는 같은 Qwen 0.5B 를 네 가지 정밀도로 올렸을 때의 크기입니다. 왼쪽에서 오른쪽으로 갈수록 숫자 하나가 절반씩 작아지므로 전체도 절반씩 줄어듭니다. 실습 1에서 get_memory_footprint() 가 알려 준 942 MB 가 둘째 상자(BF16)의 손계산과 맞는지 아래에서 확인합니다.

정밀도별 가중치 크기

정밀도1개당 크기Qwen 0.49B 가중치(손계산)8B 모델 가중치(약)쓰임
FP324바이트약 1,885 MB32GB32비트 부동소수점, 기본 형식
BF16 / FP162바이트약 942 MB16GBLLM 학습과 추론에 주로 쓰는 16비트
INT81바이트약 471 MB8GB8비트 양자화
4bit(NF4)0.5바이트약 236 MB4GBQLoRA 에서 쓰는 4비트 양자화

손으로 한 번 계산해 봅니다. 파라미터 494,032,768 개 × 2바이트 = 988,065,536 바이트입니다. 1 MB 는 1024 × 1024 = 1,048,576 바이트이므로 988,065,536 ÷ 1,048,576 ≈ 942.3 MB 입니다. 실습 1의 출력 "메모리 사용량: 942 MB" 와 맞습니다.

8B 모델을 BF16 으로 올리면 가중치만 약 16GB 입니다. 모델을 돌리는 데 드는 메모리가 따로 있으므로 16GB GPU 한 장으로는 여유가 거의 없습니다. 학습할 때는 그래디언트(gradient, 고칠 방향), 옵티마이저 상태(optimizer state, 보폭 기록), 중간 계산 결과(activation)도 저장해야 하므로 훨씬 더 듭니다. 이 부담을 줄이는 LoRA 는 8장에서, 4비트로 더 줄이는 QLoRA 는 9장에서 봅니다.

짧은 예시

Python
# 실습 1의 출력에 나온 파라미터 수
n_params = 494_032_768

# 정밀도 이름과 파라미터 1개당 바이트 수
bytes_per_param = {"FP32": 4, "BF16": 2, "INT8": 1, "4bit": 0.5}

for name, nbytes in bytes_per_param.items():
    total_bytes = n_params * nbytes  # 파라미터 수 × 바이트 수
    mb = total_bytes / 1024**2  # 1024 × 1024 바이트 = 1 MB
    # :>5 = 다섯 칸에 오른쪽 맞춤, :,.0f = 천 단위 쉼표와 소수점 없이
    print(f"{name:>5}: {mb:,.0f} MB")
# 결과: FP32: 1,885 MB / BF16: 942 MB / INT8: 471 MB / 4bit: 236 MB

# 8B(80억) 모델을 BF16 으로 올리면 몇 GB 일까(1GB = 10억 바이트로 어림)
print(8e9 * 2 / 1e9, "GB")  # 결과: 16.0 GB

이 코드가 뜻하는 것

이삿짐 상자 수를 그대로 두고 상자 크기만 바꿔 가며 트럭 짐칸이 얼마나 필요한지 표로 뽑은 것입니다. 상자 수는 실습 1의 출력에서 가져왔고, 상자 크기는 정밀도표에서 가져왔습니다.

줄하는 일쉽게 말하면
n_params * nbytes전체 바이트 수상자 수 × 상자 부피
/ 1024**2바이트를 MB 로단위 바꾸기
8e9 * 2 / 1e98B 모델의 BF16 크기큰 트럭이 필요한 이사

BF16 줄의 942 MB 는 실습 1의 실제 측정값과 같습니다. 이 손계산 하나로 "내 GPU 에 어떤 모델까지 올릴 수 있나"를 미리 가늠할 수 있습니다.

주의할 점

  • 이 계산은 가중치만의 크기입니다. 실제로 생성할 때는 입력 길이에 따라 중간값이 더 올라가고, 학습할 때는 몇 배가 더 듭니다.
  • nvidia-smi 로 보는 사용량은 PyTorch 가 미리 잡아 둔 메모리까지 포함하므로 get_memory_footprint() 보다 큽니다.
  • 다 쓴 모델은 del model 과 torch.cuda.empty_cache() 로 비웁니다. 원본 노트북이 import gc 를 해 둔 것도 이 정리를 위해서입니다.
← 이전 절6장 · Qwen 모델 불러오기다음 절 →6장 · 문장 이어 쓰기