MLOPS
GPU 기반 ML 서비스를 운영하며 정리한 학습 기록. CUDA 버전 생태계, GPU 컨테이너 최적화, 모델 서빙 워커 풀, 추론 성능 분석을 묶었다.
Triton, BentoML, Ray Serve를 층위별로 비교한 스터디 시리즈. OCR 추론 서빙에 어느 프레임워크가 적절한지 판단하기 위한 기록이다.
GPU 컨테이너의 CUDA 버전 호환성 — nvidia-smi부터 이미지 다이어트까지
GPU로 모델을 추론하는 문서 파싱 서비스의 컨테이너 이미지가 압축 기준 10GB, 디스크에 풀면 30GB까지 부푼 걸 마주했다. 줄여보려고 들여다보다가, 정작 내가 GPU 컨테이너의 버전 체계를 제대로 모른다는 걸 알았다. nvidia-smi가 찍어주는 두 개의 버전 숫자가 무슨 뜻인지, 왜 컨테이너 안 CUDA를 마음대로 못 올리는지부터 막혔다. 이 글...
GPU·CUDA·MPS 기초 — 자바 백엔드 개발자가 처음 만나는 그림
자바로 백엔드만 짤 때는 컴퓨팅 자원이 단순했다. CPU 코어 수, JVM heap (-Xmx), 시스템 RAM. 워크로드가 커지면 인스턴스를 늘리거나 스레드를 늘리는 게 답이었다. ML 서비스를 다루기 시작하면 그림이 한 층 더 생긴다. GPU 라는 별도 컴퓨팅 장치, 그 안의 VRAM 이라는 별도 메모리, 그리고 그것들을 다루는 CUDA·cuDNN·MP...
Kubernetes GPU 노드에서 /run tmpfs가 꽉 차서 Pod가 안 뜰 때
NHN Cloud OCR 리얼 배포 중 ArgoCD sync가 Degraded로 떨어졌다. pod sandbox 생성 단계에서 no space left on device 에러가 반복 발생했고, 원인은 GPU 노드의 /run tmpfs 포화였다. 루트 디스크는 16%밖에 안 쓰고 있는데 pod가 안 뜨는 상황이라 처음엔 혼란스러웠다. 이 글에서는 /run t...
ML 서비스 성능 분석 워크플로 — 자바 백엔드 트러블슈팅과 다른 점
이 시리즈의 마무리 글이다. 앞선 글들에서 다음 주제를 자바 백엔드 비교 관점으로 정리했다. - Python 문법 - 의존성 관리 - FastAPI - async/await - GPU·CUDA·MPS - PyTorch - multi-process worker pool - OCR 파이프라인 마지막은 이 모든 개념을 적용해 실제 ML 서비스의 성능을 분석하는...
Multi-process GPU 워크로드 — 자바 ThreadPool 사용자가 만나는 모델 차이
자바 백엔드에서 ThreadPoolExecutor 는 거의 만능이었다. CPU bound 든 I/O bound 든 스레드 풀 크기만 잘 잡으면 동시성을 챙길 수 있었다. JVM 안에서 메모리를 공유하니 작업 간 데이터 전달도 가볍다. Python ML 서비스는 그림이 다르다. ThreadPoolExecutor 가 있지만 CPU/GPU 작업에서는 거의 안 쓰...
Python CUDA 버전 생태계 — nvidia-smi, nvcc, pip, conda가 다 다른 버전을 말하는 이유
PyTorch를 pip install로 깔았는데 시스템에 CUDA Toolkit을 따로 안 깔아도 GPU가 돌았다. 그러다 nvidia-smi는 CUDA 12.2라고 하고, nvcc --version은 아예 명령이 없다고 하고, python -c "import torch; print(torch.version.cuda)"는 12.6이라고 한다. 같은 머신에서...
한 GPU 를 여러 프로세스가 나눠 쓰기 — Time-Slicing 과 MPS
GPU·CUDA·MPS 기초 에서 MPS 라는 약어가 NVIDIA 와 Apple 두 가지를 가리킨다는 것까지 정리했다. 그 글 끝에 "multi-process GPU 패턴은 다음 글에서" 라고 미뤄둔 부분을 이어 쓴다. 질문은 단순하다. GPU 는 한 장인데, 그 위에서 추론하는 프로세스가 여러 개면 GPU 를 어떻게 나눠 쓰는가. 여러 워커 프로세스가 각...