모델 운영

MLOPS / 62번째 글

카드 한 장을 여럿이 나눠 쓰는 세 가지 방법

작은 모델 하나에 A100 한 장을 통째로 주기는 아깝습니다. 시분할·MPS·MIG가 각각 무엇을 나누고 무엇을 못 지키는지, 어떤 상황에 무엇을 고를지 정리합니다.

PALDYN Team9 MIN READ

지난 글의 계산에는 조용한 전제가 하나 있었다. 복제본 하나가 카드 한 장을 통째로 쓴다는 전제다. 3B 모델을 A100 80GB에 올려 두고 초당 두어 건을 처리하는 상황이라면 그 전제부터 아깝다. 메모리도 계산 자원도 대부분 놀고 있는데 카드 값은 다 낸다.

그럼 두 프로세스를 같은 카드에 그냥 띄우면 어떻게 되는가. 된다. 다만 무엇이 어떻게 되는지 모르고 하면 원인 모를 지연 요동과 메모리 부족을 만난다.

아무 설정도 안 하면 시분할이다

기본 동작부터 알아 두는 편이 낫다. 한 GPU에 여러 프로세스가 커널을 올리면 드라이버가 번갈아 실행한다.

카드 한 장을 둘이 쓰는 세 가지 방식

①이 그 모습이다. 어느 순간에도 한 프로세스만 돌고, 전환할 때마다 문맥을 갈아 끼운다. 여기서 두 가지가 나온다.

  • 처리량은 거의 안 는다. 어차피 한 번에 하나만 도니 나눠 쓴다고 계산이 더 되지 않는다
  • 지연은 나빠지고, 무엇보다 예측이 안 된다. 내 요청이 언제 차례를 받을지가 옆 프로세스가 얼마나 오래 커널을 붙잡는지에 달렸다

메모리는 그나마 나눠 갖는다. 다만 칸막이가 없다. 옆 프로세스가 배치를 키워 메모리를 다 먹으면 내 쪽이 메모리 부족으로 죽는다. 서빙 엔진은 대개 시작할 때 남은 메모리의 90%를 KV 캐시로 미리 잡아 두므로(vLLM의 gpu_memory_utilization), 두 번째 프로세스는 자리가 없어 아예 못 뜨는 경우가 더 흔하다.

MPS — 커널을 같이 올린다

MPS(Multi-Process Service)는 여러 프로세스의 커널을 하나의 스케줄러 아래로 모아 동시에 올린다. 그림 ②처럼 A와 B가 같은 시간대에 함께 돈다.

이득은 빈자리를 메우는 데서 온다. 작은 모델의 커널은 GPU의 연산 유닛을 다 채우지 못하는데, 그 빈 유닛에 다른 프로세스의 커널이 들어간다. 배치가 작고 커널이 자잘한 워크로드에서 특히 효과가 크다.

대가는 격리다.

  • 메모리 칸막이가 없다. 상한을 걸 수는 있지만(CUDA_MPS_PINNED_DEVICE_MEM_LIMIT) 하드웨어가 강제하는 것이 아니다
  • 오류 격벽이 없다. 한 프로세스가 메모리 오류로 죽으면 같은 MPS 서버에 붙은 다른 프로세스까지 함께 넘어질 수 있다
  • 성능이 이웃에 좌우된다. 옆이 조용하면 빠르고 붐비면 느리다. 지연 시간 약속을 걸기 어렵다

연산 자원의 비율은 정할 수 있다(CUDA_MPS_ACTIVE_THREAD_PERCENTAGE). 다만 이것도 상한일 뿐 최소 보장이 아니라서, 「최소한 이만큼은 준다」는 약속에는 못 쓴다.

MIG — 카드를 하드웨어로 자른다

MIG(Multi-Instance GPU)는 접근이 다르다. 카드를 여러 개의 작은 GPU로 물리적으로 쪼갠다. 연산 유닛, 메모리, L2 캐시, 메모리 대역폭까지 갈라서 각 조각에 붙인다.

그림 ③에서 두 칸이 서로 남남처럼 보이는 이유가 그것이다. 조각 하나는 운영체제에 별개의 GPU로 보이고, 옆칸이 무엇을 하든 내 성능은 그대로다. 지연 시간 약속을 걸 수 있는 유일한 방식이다.

A100 80GB의 프로파일을 예로 들면 이렇게 나뉜다.

프로파일 메모리 한 장에서 몇 개 어울리는 것
1g.10gb 10GB 7 임베딩·재순위·분류 모델
2g.20gb 20GB 3 3B 안팎 모델 서빙
3g.40gb 40GB 2 8B 모델 서빙
7g.80gb 80GB 1 나누지 않음

제약도 분명하다.

  • A100·H100 같은 데이터센터 카드에서만 된다. L40S나 소비자용 카드에는 없다
  • 나눈 뒤에는 못 빌려준다. 내 칸이 놀아도 옆칸이 못 쓴다. 이용률로 보면 오히려 손해가 날 수 있다
  • 바꾸려면 비운다. 프로파일을 다시 짜려면 그 카드의 작업을 전부 내려야 한다
  • 조각끼리 묶어 못 쓴다. 텐서 병렬처럼 여러 조각을 합쳐 큰 모델을 올리는 것은 안 된다

셋을 나란히 놓으면

시분할 MPS MIG
동시에 도는가 아니오 예 예
메모리 칸막이 없음 소프트웨어 상한 하드웨어
오류 격벽 있음 없음 있음
성능 예측 나쁨 중간 좋음
자원 되빌려주기 됨 됨 안 됨
필요한 하드웨어 아무거나 아무거나 A100·H100 계열
켜는 법 기본값 데몬 실행 카드를 내리고 재구성

「무엇이 제일 좋은가」로는 답이 안 나온다. 격리와 이용률을 맞바꾸는 축 위에 셋이 놓여 있어서, 어느 쪽이 더 급한지가 정한다.

나눠 쓸지, 어떻게 나눌지를 정하는 순서

쿠버네티스에서 주의할 것

쿠버네티스에 GPU를 붙일 때 흔히 쓰는 설정이 하나 있다. NVIDIA 디바이스 플러그인의 time-slicing 옵션인데, 카드 한 장을 replicas: 4로 선언하면 파드 넷이 각각 GPU 하나를 받았다고 여기게 만든다.

이름 그대로 시분할이라는 점을 오해하지 않는 것이 중요하다. 자원을 나눈 것이 아니라 스케줄러를 속인 것이다. 넷이 각자 「GPU 한 장」을 받았다고 믿고 저마다 메모리의 90%를 잡으려 들면 세 개가 못 뜬다. 서빙 엔진을 이 방식으로 여럿 올릴 때는 각 파드의 메모리 비율을 손으로 나눠 줘야 한다(넷이면 gpu_memory_utilization을 0.22쯤으로).

MIG는 반대로 정직하다. 조각마다 별개의 장치로 보이므로 플러그인이 nvidia.com/mig-3g.40gb 같은 자원 이름으로 내보내고, 파드는 진짜로 그 칸만 받는다.

나누기 전에 물어볼 것

카드를 나누는 방법을 고르기 전에, 나눌 필요가 있는지를 먼저 보는 편이 낫다. 이용률이 낮은 이유가 대개 둘 중 하나이기 때문이다.

  • 동시 요청이 적어서라면 나누는 것이 맞다
  • 배치가 안 차서라면 연속 배칭이 제대로 도는지부터 본다. 요청은 충분한데 하나씩 처리하고 있었다면, 카드를 나누는 것보다 엔진 설정 한 줄이 훨씬 크게 바꾼다

모델이 여러 개인 것이 이유라면 선택지가 하나 더 있다. 같은 베이스의 파생 모델이라면 카드를 나눌 것 없이 어댑터를 함께 태우는 방식으로 프로세스 하나에 담을 수 있다. 나누지 않고 합치는 쪽이 이용률에는 언제나 유리하다.


읽어주셔서 감사합니다. 😊

LATEST

모델 운영의 최신 글

모델 운영2026.09.04

KV 캐시 양자화 — 가중치보다 이쪽이 먼저 넘친다

긴 문맥에서 GPU 메모리를 실제로 잡아먹는 것은 가중치가 아니라 KV 캐시입니다. 캐시 크기를 계산하는 법, K와 V를 다르게 다뤄야 하는 이유, 어디까지 줄여도 되는지를 정리합니다.

16 MIN
모델 운영2026.09.04

양자화 보정 — 데이터 128개가 모델 품질을 정한다

양자화에서 스케일을 정하는 절차가 보정입니다. 무엇을 재는지, 데이터를 어디서 몇 개 뽑아야 하는지, 자르는 지점을 어떻게 고르는지, 그리고 잘못된 보정이 어떤 모양으로 드러나는지를 정리합니다.

21 MIN
모델 운영2026.09.03

과제 특화 증류 — 큰 모델의 답을 작은 모델에 옮긴다

범용 성능이 아니라 우리 과제 하나만 잘하는 작은 모델을 만드는 방법입니다. 교사에게 무엇을 받아야 하는지, 데이터를 어떻게 모으고 거르는지, 손익 분기가 어디인지를 정리합니다.

15 MIN