콘텐츠로 이동

nvidia-smi는 80GB라 하고, torch는 44GB라 한다

SFTP 삽질이 끝나고 워크스페이스 리소스 설정을 다시 들여다보다가 이상한 점을 발견했다. 리소스셋 이름에 gpu-block-855mb라는 단위가 들어 있는데, 정작 컨테이너에서 nvidia-smi를 치면 H100 80GB가 통째로 잡혀 있었다. 855MB짜리 블록이라는 이름과 80GB라는 표시가 같이 있을 수는 없다. 둘 중 하나는 거짓말이라고 생각했는데, 결론부터 말하면 둘 다 참이었다.

리소스셋 이름 해독

먼저 이름부터 풀었다. 우리 워크스페이스는 224m-2474mb-gpu-block-855mb 단위를 50개 묶어 할당받는 구조다. 곱해 보면 실체가 나온다.

  • CPU: 224m × 50 = 11200m, 즉 11.2코어
  • 메모리: 2474MB × 50 = 123700MB, 약 121GB
  • GPU: 855MB 블록 × 50 = 약 42.8GB

CPU와 RAM은 계산과 화면 표시가 일치했다. 문제는 GPU였다. 계산대로면 42.8GB인데 nvidia-smi는 81559MiB, 즉 80GB 전체를 보여주고 있었다.

측정해 보니 제3의 숫자가 나왔다

표시가 아니라 실제 할당 가능량을 재보기로 했다.

python3 -c "import torch; f,t=torch.cuda.mem_get_info(); \
  print(f'{f/1e9:.1f} / {t/1e9:.1f} GB free/total')"
44.3 / 85.0 GB free/total

total 85GB는 카드 전체가 보인다는 뜻이니 MIG처럼 하드웨어 수준에서 쪼갠 건 아니다. 그런데 free가 44.3GB다. 첫 해석은 "나머지 40GB를 다른 사람 작업이 점유 중이거나, 죽은 프로세스가 메모리를 안 놓고 있다"였다. 공유 GPU니까 그럴듯한 가설이었다.

확인하러 nvidia-smi를 다시 봤다.

Memory-Usage: 973MiB / 81559MiB    GPU-Util: 6%
Processes: No running processes found

카드는 사실상 텅 비어 있었다. 아무도 안 쓰는데 40GB가 없다? 가설이 무너졌다.

두 도구는 다른 것을 재고 있었다

모순처럼 보였지만, 두 숫자는 애초에 측정 대상이 달랐다.

  • nvidia-smi물리 카드를 호스트 관점에서 본다. 실제 점유 973MiB, 빈 카드.
  • torch.cuda.mem_get_info()의 44.3GB는 내 컨테이너에 걸린 VRAM 상한이다. 물리적 여유가 아니라 내 몫의 천장.

즉 리소스셋의 855MB 블록 × 50이 바로 이 44GB 쿼터의 정체였다. 카드는 통째로 보이지만(타임셰어 방식), 내가 할당받을 수 있는 양은 쿼터로 제한되는 구조다. 이름과 화면 표시가 모순됐던 게 아니라, 하나는 쿼터를 말하고 하나는 물리 카드를 말하고 있었던 것이다.

부수 발견도 하나 있었다. 컨테이너 안 nvidia-smi의 Processes 목록은 믿으면 안 된다. PID 네임스페이스가 격리돼 있어 다른 컨테이너의 프로세스는 안 보이고 자기 것도 제대로 안 잡힌다. "No running processes"는 정상 출력이고, 신뢰할 수 있는 건 위쪽 Memory-Usage 숫자뿐이다. 사용량 확인은 torch 쪽 API로 하는 게 맞다.

44GB로 부족한가

처음엔 80이 44가 된 게 아까웠는데, 계산해 보면 연구실 워크로드에는 충분하고도 남는다. fp16 기준 7B 모델 추론이 약 14GB, 13B가 26GB. LoRA 계열이면 훨씬 큰 모델도 이 안에서 학습이 돌아간다. 우리 도메인의 트래픽 분석 모델은 애초에 몇 GB 수준이라 오히려 배치를 키워 학습 속도를 버는 쪽에 여유가 쓰인다.

무엇보다 이 쿼터 구조는 합리적이다. 80GB를 한 명이 독점하고 나머지가 줄을 서는 것보다, 44GB를 보장받고 여럿이 동시에 도는 쪽이 공유 랩에는 맞다.

남은 것

모순되는 두 측정값이 있으면, 둘 중 하나가 틀린 게 아니라 서로 다른 것을 재고 있을 가능성부터 본다. 이번 건이 정확히 그랬다. 표시 계층(물리 카드)과 할당 계층(쿼터)을 구분하고 나니 모든 숫자가 맞아떨어졌다.

그리고 855MB 블록, 생성마다 바뀌는 포트, 재시작하면 초기화되는 환경 같은 조각들이 하나의 그림을 가리키고 있었는데, 그 얘기는 다음 글에서 잇는다.