공부/인공지능

GPU 사용률 0%인데 메모리 6.7GB — 좀비라고 의심했던 그 프로세스는 살아있었습니다

TechToast 2026. 10. 12. 10:27
반응형

🚨 증상: 연산은 0%인데 메모리는 6.7GB

로컬 GPU 서버에서 작업을 마치고 nvidia-smi로 그래픽 카드 상태를 한번 열어봤습니다. GPU Utilization은 0%, 전력도 23W라 완전한 대기 상태였습니다. 아이들로 조용히 쉬고 있는 셈이죠. 그런데 메모리 점유율은 6.7GB — GPU가 11GB라니까 전체의 절반을 넘게 물고 있었습니다. 연산은 하나도 안 하는데 메모리를 6.7GB나 쥐고 있는 겁니다.

 

"화면은 안 보면서 키보드만 두드리고 있는 격"이라는 비유가 떠올랐습니다. 연산을 안 하는데 자원을 버티고 있는 건 뭔가 잘못된 것 같아 보이니까요.

 

점유 프로세스를 내려보니 프로세스는 하나뿐이었고, 오래된 로컬 임베딩 서버였습니다. 게다가 게시된 지 5일이 넘게 상주해 있었습니다.

 

 

🧟 좀비라고 의심했지만, 실측으로 배제했습니다

첫 반응은 좀비였습니다. "연산도 안 하면서 VRAM을 물고 있다"는 그림이 ps에서 본 좀비(Z) 프로세스의 전형과 겹쳐 보였습니다. 이미 죽은 프로세스가 자원을 놓지 못해 화면 구석에서 버티고 있는 상황 말이죠.

 

 

하지만 실측으로 확인해보니 전혀 달랐습니다. 그 프로세스는 S (sleeping) 상태, 즉 정상적으로 대기 중이었고, 포트 리스닝도 정상이며 /health 응답까지 정상이었습니다. 그리고 10월 6일에 기동된 뒤 계속 살아 있었네요.

 

여기서 이 글의 핵심 반전이 나옵니다. 좀비(Z) 프로세스는 자원을 전혀 보유하지 않습니다. 좀비는 부모 프로세스가 exit 상태를 정리해주기만 기다리는 이미 죽은 프로세스라서, 메모리든 VRAM이든 아무것도 들고 있지 않아요. 반대로 VRAM을 점유하면서 Utilization이 0%라는 건 그 프로세스가 살아있다는 증거입니다. 죽은 게 아니라 잠들어 있었던 것이죠.

 

그러니까 이건 좀비가 아니라, 평범하게 살아서 대기 중인 임베딩 서버였습니다. 그럼 왜 계속 메모리를 잡고 있을까, 이제 진짜 원인으로 넘어갑니다.

🔍 진짜 원인: 모델 교체 + CUDA 캐싱 알로케이터

메모리 점유가 커진 데는 두 가지 이유가 겹쳐 있었습니다.

 

첫째, 지난 8월 17일에 임베더를 교체했습니다. 기존 e5-large(약 1.1GB)에서 KURE-v1(XLM-RoBERTa-Large, 250K 단어장)로 바꿨는데, 다국어를 지원하려고 단어장을 크게 가져간 모델이라 가중치 자체가 커졌습니다. 다국어 임베딩을 되살리고 싶어서였죠.

 

둘째, 메모리를 계속 쥐고 있는 주범은 PyTorch의 CUDA 캐싱 알로케이터입니다. 크론 기반으로 대량 임베딩(batch 16, seq 8192)을 돌리면 처리 순간에 피크 메모리가 확 치솟는데, forward pass가 끝나면 텐서 자체는 해제되지만, CUDA 캐싱 알로케이터가 CUDA 드라이버에 메모리를 돌려주지 않고 캐시로 미리 쥐어둡니다. 다음 임베딩을 위해 비축해두는 셈이죠.

 

냉장고에 비유하면 이렇습니다. 매번 마트를 왔다갔다 하면 손해니까 재료를 미리 쌓아두고, 그 쌓인 자리가 6.7GB인 겁니다. 임베딩 작업이 크론으로 자주 돌아오니까 서버는 항상 "준비된 상태"로 유지되는 거고요.

 

 

🤔 이게 문제일까요 — 판단

그렇다고 성능에 문제가 생긴 건 아닙니다. GPU가 11GB니까 6.7GB를 잡아도 여유가 있습니다. 다른 GPU 작업(모델 학습이나 추론)이 동시에 돌아갈 때만 메모리 경쟁이 생길 뿐이고, 현재 운용에는 전혀 지장이 없습니다.

📌 정직한 한계 + 후속 계획

이 6.7GB는 아이들 상태에서 계속 잡고 있는 "안정 점유"라서 코드 수정만으로는 쉽게 줄이기 어렵습니다. 요청 처리 후에 torch.cuda.empty_cache()를 호출하면 메모리를 반환할 수 있지만, 자주 호출하면 재할당 비용이 붙어 오히려 성능이 나빠질 수 있습니다. 어차피 캐시로 유지하는 게 유리한 상황이라서 적극적으로 비우진 않겠습니다.

 

후속으로는, 로컬 GPU를 진짜로 비워야 할 때 이 임베딩 서버를 GB10 듀얼 노드나 워크스테이션으로 옮기는 방법을 생각하고 있습니다. 그리고 혹시 몰라 주 1회 /health 응답을 확인하는 크론을 등록하는 것도 고려 중입니다. "여전히 메모리를 쥐고 있지만 살아있는 프로세스다"라는 확인을 주기적으로 받는 셈이죠.

💡 마무리

이번 경험으로 배운 건 하나입니다. VRAM을 점유하면서 Utilization이 0%인 걸 보고 곧바로 좀비라고 단정하면 안 된다는 것, 그리고 좀비라고 부르기 전에 프로세스 상태와 포트·헬스 응답을 직접 확인해보라는 것입니다. 좀비는 자원을 잡지 않는다는 사실이 이번 사건의 가장 큰 교훈이었습니다.

반응형