런을 취소했는데 GPU가 계속 물려 있다
의미 없는 런(멈춤·교착·degraded)을 발견하면 바로 취소합니다. DB에서 상태를 cancelled로 바꿉니다. 그런데 — GPU 사용량이 안 떨어집니다. 취소했는데 무언가 계속 GPU를 90%로 물고 있습니다. 무슨 일일까요?
상태 플래그 ≠ 프로세스
핵심은 단순합니다. DB의 상태는 기록일 뿐, 이미 실행 중인 프로세스를 죽이지 않습니다.
도식 렌더링 중…
워커가 런을 claim해 Isaac을 띄운 뒤라면, 그 Isaac 프로세스는 독립적으로 GPU를 쓰고 있습니다. DB 플래그를 바꿔도 그 프로세스는 자기가 취소된 줄 모릅니다 — 그래서 GPU를 계속 무는 좀비가 됩니다.
복구 — 그 프로세스만 정확히 죽인다
복구는 실제 Isaac 프로세스를 직접 죽이는 것입니다. GPU를 쓰는 프로세스 목록에서 PID를 찾아 종료합니다.
# GPU를 점유한 compute 프로세스의 PID 확인
nvidia-smi --query-compute-apps=pid,used_memory --format=csv
# 해당 Isaac PID를 직접 종료
kill -9 <isaac_pid>
⚠️
pkill -f '<run_id>'는 자기 세션을 죽인다 — "run_id로 싹 죽이자"며pkill -f를 쓰면, 그 run_id가 들어간 모든 명령이 매칭됩니다 — 지금 입력 중인 ssh 세션 명령(run_id가 포함된)까지요. 그래서 출력이 뚝 끊기고 자기 발등을 찍습니다. PID를 특정해 죽이는 게 안전합니다.
💡 다른 GPU 작업은 보존하라 — 같은 노드에 다른 정상 작업(학습·다른 런)이 돌고 있을 수 있습니다. "GPU 비우자"고 전부 죽이면 멀쩡한 작업까지 날립니다. nvidia-smi로 문제의 Isaac PID만 골라 죽이세요.
왜 이렇게 설계됐나 — 그리고 교훈
정상 종료(teardown)는 영상을 묶고 리소스를 정리합니다. 하지만 강제 취소는 그 경로를 안 거치니, 프로세스가 고아로 남을 수 있습니다.
💡 취소는 "기록 + 실제 종료" 두 가지다 — 분산 시스템에서 "취소"는 상태 기록과 실제 리소스 회수가 별개입니다. 둘 다 해야 진짜 취소입니다. 상태만 바꾸고 "취소했다"고 믿으면, GPU는 계속 타들어 갑니다. alive ≠ working의 반대편 — cancelled ≠ stopped입니다.
한 줄 정리
📌 DB
status='cancelled'는 기록일 뿐, 워커가 띄운 Isaac 프로세스는 안 죽어 GPU 좀비가 된다. 복구는nvidia-smi로 PID를 찾아 직접kill -9— 단,pkill -f run_id는 자기 ssh 세션까지 죽이니 금물이고, 같은 노드의 다른 작업은 보존한다. "취소"는 기록 + 실제 종료 둘 다여야 한다.
