[GPU 자원 관리 방법] MIG vs CUDA_VISIBLE_DEVICES: 완벽한 격리? 유연한 공유?

  • 카카오톡 공유하기
  • 네이버 블로그 공유하기
  • 네이버 밴드에 공유하기
  • 페이스북 공유하기
  • 트위터 공유하기
  • 링크 복사하기

이번에 GPU 정부지원 사업을 신청하여 H100 4장을 할당 받았습니다. 각 본부에서 LLM 개발 및 fine tuning을 목적으로 할당 하여 사용할 계획입니다. 아무래도 지원 사업 자체가 하나의 인스턴스에 GPU 자원을 나눠서 사용해야 하는 방식이다보니 자원을 어떻게 할당하는 것이 좋을지 알아보다가 정리된 내용을 포스트로 기록합니다.

GPU 자원을 관리하는 가장 대표적인 두 가지 방식, NVIDIA MIG(Multi-Instance GPU)CUDA_VISIBLE_DEVICES 환경 변수의 차이점과 각각의 제어 방식에 대해 정리하겠습니다.


1. CUDA_VISIBLE_DEVICES: “소프트웨어적 시야 가리기”

가장 흔하게 사용되는 방법이자, 가장 기초적인 방법입니다.

1. 제어 방식: “Masking (마스킹)”

이 방식은 ‘눈가리개’와 같습니다. 실제로는 GPU가 4개 있더라도, 애플리케이션에게 “너는 1번 GPU만 봐”라고 소프트웨어적으로 속이는 것입니다.

  • 작동 원리: CUDA 런타임(Runtime) 레벨에서 특정 GPU ID만 애플리케이션에 노출합니다.
  • 사용법:

2. GPU 통합 제어

만약 GPU 4장(각 80GB)라고 할 때, LLM 서빙 프레임워크에서 3장 정도를 할당하려고 합니다. 3장을 하나로 합쳐서 사용을 설정하기 위해서는 CUDA_VISIBLE_DEVICES=1,2,3 으로 지정합니다. 그러면 해당 프로세스를 위해서 3장의 GPU를 자원으로 사용하게 됩니다.

vLLM에서는 이렇게 물리적으로 분리된 GPU 자원을 묶어내기 위해 병렬로 묶는 옵션을 실행해야합니다.

3. 장점 (Pros)

  • 간편함: 관리자(root) 권한이 필요 없고, 누구나 바로 사용할 수 있습니다.
  • 유연함: 언제든지 설정을 바꿀 수 있으며 재부팅이 필요 없습니다.
  • 호환성: 모든 NVIDIA GPU(GeForce 포함)에서 작동합니다.

4. 단점 (Cons)

  • 자원 격리 불가: 지정된 GPU 안에서는 자원(Memory, Compute)을 독점할 수 없습니다. 같은 GPU를 CUDA_VISIBLE_DEVICES=1로 설정한 두 개의 프로세스가 있다면, 서로 자원을 뺏기 위해 경쟁합니다.
  • 강제성 부족: 사용자가 unset CUDA_VISIBLE_DEVICES를 입력하면 모든 GPU에 접근할 수 있습니다. 보안용으로는 부적합합니다.
  • Fault Isolation 불가: 한 프로세스가 GPU 메모리 오류를 일으키면, 같은 GPU를 공유하는 다른 프로세스도 함께 죽을 수 있습니다.

2. NVIDIA MIG (Multi-Instance GPU): “하드웨어적 공간 나누기”

MIG를 사용하면, 마치 하나의 큰 아파트 건물을 물리적인 벽으로 나눠 7개의 원룸으로 분리하는 것과 같습니다. 각 원룸(MIG 인스턴스)은 자체 메모리, 캐시, 컴퓨팅 코어를 가지며, 한 방(사용자)에서 아무리 시끄럽게 해도(작업을 100% 돌려도) 옆방(다른 사용자)에 전혀 영향을 주지 않는 완벽한 자원 격리(Isolation)를 제공합니다.

A100, H100 등 최신 데이터센터 GPU에서 지원하는 강력한 격리 기술입니다.

NVIDIA MIG(Multi-Instance GPU)는 하나의 물리 GPU를 하드웨어 수준에서 여러 개의 독립적인 ‘미니 GPU’로 분할하여, 각 사용자나 작업에 격리된 자원을 할당하는 가장 강력한 기술입니다.

MIG를 사용하면, 마치 하나의 큰 아파트 건물을 물리적인 벽으로 나눠 7개의 원룸으로 분리하는 것과 같습니다. 각 원룸(MIG 인스턴스)은 자체 메모리, 캐시, 컴퓨팅 코어를 가지며, 한 방(사용자)에서 아무리 시끄럽게 해도(작업을 100% 돌려도) 옆방(다른 사용자)에 전혀 영향을 주지 않는 완벽한 자원 격리(Isolation)를 제공합니다.

이는 CUDA_VISIBLE_DEVICES 같은 ‘협조’ 방식이 아닌, 하드웨어 레벨의 ‘강제’ 방식입니다.


1. MIG 설정 전 필수 확인 사항

  • 1. 지원 하드웨어: A100, H100, A30 등 NVIDIA의 데이터센터용 GPU에서만 작동합니다. (GeForce RTX 3090, 4090 등은 지원하지 않습니다.)
  • 2. 관리자 권한: 모든 설정 명령어는 sudo (root) 권한이 필요합니다.
  • 3. 독점 사용: MIG 모드를 켜고 끄는 순간에는 해당 GPU를 사용하는 다른 프로세스가 없어야 합니다.
  • 4. 드라이버 버전: 최신 NVIDIA 드라이버가 설치되어 있어야 합니다.

2. MIG 설정 단계별 가이드 (A100/H100 기준)

모든 과정은 nvidia-smi 명령어를 통해 이루어집니다. (예시: 0번 GPU를 설정)

1단계: MIG 모드 활성화

MIG를 사용하려면 먼저 GPU의 MIG 모드를 켜야 합니다. 이 작업은 GPU를 리셋하므로, 실행 중인 작업이 없어야 합니다.

# 0번 GPU의 MIG 모드를 활성화합니다. (반드시 sudo 필요)
sudo nvidia-smi -i 0 -mig 1

nvidia-smi를 다시 실행해 보면, GPU의 MIG M. (MIG Mode) 항목이 Disabled에서 Enabled로 바뀐 것을 볼 수 있습니다.

2단계: 생성 가능한 프로파일 확인 (매우 중요)

MIG는 사용자가 원하는 대로 13GB, 7GB처럼 마음대로 나누는 것이 아니라, NVIDIA가 미리 정해둔 ‘프로파일(조각 레시피)’ 중에서 선택해야 합니다.

lgip (List GPU Instance Profiles) 명령어로 가능한 레시피를 확인합니다.

# 0번 GPU에서 생성 가능한 GI(GPU Instance) 프로파일 목록 보기
sudo nvidia-smi mig -i 0 -lgip

[출력 예시 (A100 80GB)]

GPU instance profiles:
ID  PROFILE NAME         #Slices  Memory  Volatile  Non-Volatile
===============================================================
19  1g.10gb                1      10 GiB      0 MiB       0 MiB
14  2g.20gb                2      20 GiB      0 MiB       0 MiB
 9  3g.40gb                3      40 GiB      0 MiB       0 MiB
 0  7g.80gb                7      80 GiB      0 MiB       0 MiB
  • 1g.10gb: 컴퓨팅 유닛 1개, 메모리 10GB (최대 7개 생성 가능)
  • 2g.20gb: 컴퓨팅 유닛 2개, 메모리 20GB (최대 3개 생성 가능)
  • 3g.40gb: 컴퓨팅 유닛 3개, 메모리 40GB (최대 2개 생성 가능)
  • 7g.80gb: GPU 통째로 1개 (MIG지만 1개로만 씀)
3단계: GPU 인스턴스 (GI) 생성

이제 원하는 프로파일을 선택하여 GPU 인스턴스(GI)를 생성합니다. GI는 ‘메모리’를 분할하는 단위입니다.

예를 들어, 10GB짜리 조각(1g.10gb) 2개를 만들어 보겠습니다.

# 0번 GPU에 '1g.10gb' 프로파일(ID 19)로 GI 2개 생성
sudo nvidia-smi mig -i 0 -cgi 1g.10gb,1g.10gb
# 또는 ID를 사용: sudo nvidia-smi mig -i 0 -cgi 19,19

만약 20GB짜리 1개, 10GB짜리 1개를 만들고 싶다면:

sudo nvidia-smi mig -i 0 -cgi 2g.20gb,1g.10gb

4단계: 컴퓨팅 인스턴스 (CI) 생성

GI(메모리)를 만들었으면, 그 안에서 실제 ‘컴퓨팅 코어’를 분할하는 컴퓨팅 인스턴스(CI)를 만들어야 합니다.

(참고: 1g.10gb, 2g.20gb 등 대부분의 프로파일은 GI와 CI가 1:1로 자동 생성되기도 하지만, 명시적으로 생성하는 것이 좋습니다.)

먼저 nvidia-smi -L로 방금 만든 GI의 ID를 확인합니다.

nvidia-smi -L
# 출력 예시:
# GPU 0: ... (UUID: ...)
# MIG 1g.10gb Instance (GPU Instance ID: 9)
# MIG 1g.10gb Instance (GPU Instance ID: 12)

GI ID 9번과 12번이 생성된 것을 확인했습니다. 이제 이 GI 내부에 CI를 생성합니다.

# GI ID 9번 내부에 CI 생성 (프로파일 이름은 보통 GI와 동일)
sudo nvidia-smi mig -gi 9 -cci 1g.10gb

# GI ID 12번 내부에 CI 생성
sudo nvidia-smi mig -gi 12 -cci 1g.10gb

5단계: 최종 확인

모든 설정이 완료되었습니다. nvidia-smi -L 명령어로 최종 생성된 MIG 인스턴스 목록과 고유 UUID를 확인합니다.

nvidia-smi -L

[최종 출력 예시]

GPU 0: NVIDIA A100-SXM4-80GB (UUID: GPU-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx)
MIG 1g.10gb Instance (GPU Instance ID: 9)
Compute Instance 0 (CI ID: 0, UUID: MIG-GPU-aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa)
MIG 1g.10gb Instance (GPU Instance ID: 12)
Compute Instance 0 (CI ID: 0, UUID: MIG-GPU-bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb)

이제 MIG-GPU-aaaaaaaa...MIG-GPU-bbbbbbbb...라는 2개의 완벽히 분리된 10GB짜리 ‘미니 GPU’가 생성되었습니다.


3. 생성된 MIG 인스턴스 할당 및 사용

생성된 MIG 인스턴스는 고유 UUID를 통해 사용자나 작업에 할당합니다.

방법 1: 터미널 사용자별 할당 (CUDA_VISIBLE_DEVICES)

사용자가 터미널로 접속할 때, 환경 변수로 이 UUID를 지정해 주면 됩니다.

  • A 사용자.bashrc 또는 /etc/profile.d/userA.sh에 추가:
  • export CUDA_VISIBLE_DEVICES=MIG-GPU-aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa
  • B 사용자.bashrc 또는 /etc/profile.d/userB.sh에 추가:
  • export CUDA_VISIBLE_DEVICES=MIG-GPU-bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb

이제 A 사용자는 1번 MIG 인스턴스만, B 사용자는 2번 MIG 인스턴스만 볼 수 있으며 서로 침범이 불가능합니다.

방법 2: Docker 컨테이너에 할당

NVIDIA Container Toolkit을 사용하여 Docker에 특정 MIG 인스턴스만 할당할 수 있습니다.

# A 사용자를 위한 Docker 컨테이너 (첫 번째 MIG 할당)
docker run -it --rm --gpus '"device=MIG-GPU-aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa"' ...

# B 사용자를 위한 Docker 컨테이너 (두 번째 MIG 할당)
docker run -it --rm --gpus '"device=MIG-GPU-bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb"' ...

4. MIG 인스턴스 삭제 및 비활성화 (초기화)

MIG를 제거하는 것은 생성의 역순입니다.

# 1. CI(컴퓨팅 인스턴스) 삭제
# (nvidia-smi -L로 CI ID 확인 후)
sudo nvidia-smi mig -dci -gi 9 -ci 0
sudo nvidia-smi mig -dci -gi 12 -ci 0

# 2. GI(GPU 인스턴스) 삭제
# (nvidia-smi -L로 GI ID 확인 후)
sudo nvidia-smi mig -dgi -gi 9
sudo nvidia-smi mig -dgi -gi 12

# 3. MIG 모드 비활성화
sudo nvidia-smi -i 0 -mig 0

5. 장점 (Pros)

  • 완벽한 격리 (QoS 보장): 옆방(다른 MIG 인스턴스)에서 아무리 헤비한 작업을 돌려도, 내 방(내 인스턴스)의 성능에는 0.1%도 영향을 주지 않습니다. (메모리 대역폭까지 격리됨)
  • 안정성: 한 MIG 인스턴스에서 에러가 발생해도 다른 인스턴스는 안전합니다.
  • 보안: 하드웨어 레벨에서 메모리 접근이 차단되므로 데이터 유출 걱정이 없습니다.

6. 단점 (Cons)

  • 설정의 복잡함: Root 권한이 필요하고, 설정 과정(GI/CI 생성)이 까다롭습니다.
  • 재구성의 어려움: 파티션을 다시 나누려면 GPU를 사용하는 모든 프로세스를 중단해야 할 수도 있습니다.
  • 유연성 부족: 정해진 규격(Profile)대로만 잘라야 합니다. (예: 10GB, 20GB 단위로만 가능, 15GB는 불가능)

3. 한눈에 보는 비교 (VS)

특징CUDA_VISIBLE_DEVICESNVIDIA MIG
비유선글라스 (시야 제한)벽 설치 (물리적 분할)
제어 레벨소프트웨어 (CUDA Runtime)하드웨어 (GPU Architecture)
성능 간섭심함 (자원 경쟁 발생)없음 (완벽한 독립성)
메모리 보호없음 (OOM 발생 시 동반 종료)완벽함 (별도 메모리 공간)
사용 난이도매우 쉬움어려움 (관리자 개입 필요)
지원 GPU모든 NVIDIA GPUA100, H100, A30 등 엔터프라이즈급

4. 결론: 언제 무엇을 써야 할까?

상황에 따라 적절한 도구를 선택하는 것이 핵심입니다.

이런 경우엔 CUDA_VISIBLE_DEVICES (또는 vLLM의 gpu_memory_utilization)

  • 개발/실험 단계: 빠르게 모델을 돌려보고 싶을 때.
  • 탄력적 운영이 필요할 때: H100 80GB 하나에 10GB 모델과 50GB 모델을 유동적으로 띄워야 할 때. (MIG는 40+40 혹은 20+20+20 등으로 쪼개기가 경직되어 있어 낭비가 생길 수 있음)
  • GeForce GPU 사용 시: 선택권이 없습니다.

이런 경우엔 MIG

  • SaaS 서비스 제공: 여러 고객사(Tenant)에게 GPU 자원을 빌려줄 때. (보안 및 성능 보장 필수)
  • 안정적인 프로덕션 서빙: 옆 프로세스의 부하로 인해 내 서비스의 응답 속도(Latency)가 튀면 안 될 때.
  • H100/A100의 효율적 분할: 80GB 통짜 GPU를 작은 모델 7개 서빙용으로 쪼개서 비용을 절감하고 싶을 때.

마무리 Tip

최근에는 MIG의 격리성소프트웨어의 유연성을 결합하려는 시도가 많습니다. 예를 들어, H100을 MIG로 크게 2등분(3g.40gb x 2)하여 물리적 안정성을 확보한 뒤, 각 파티션 내부에서 다시 gpu_memory_utilization 등을 활용해 여러 컨테이너를 띄우는 하이브리드 전략이 엔터프라이즈 환경에서 각광받고 있습니다.


게시됨

카테고리

작성자

댓글

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다