Navigation
🏭 Platform & Infrastructure· 10 min read

GPU Virtualization

MIG (hardware partitioning), MPS (time-sharing), time-slicing β€” sharing a single GPU across multiple workloads safely.

migmpstime-slicingvirtualizationmulti-tenant

A single H100 has 80 GB of memory and 989 TFLOPS β€” far more than many workloads need. GPU virtualization shares one physical GPU across multiple workloads, improving utilization from 20-30% to 70-90%.


1. The Utilization Problem

Typical GPU utilization without virtualization:

WorkloadGPU memory usedCompute usedWaste
8B model inference (INT4)4 GB / 80 GB5%95% idle
Dev notebook (experiment)10 GB / 80 GB2% (bursty)95% idle most of the time
Embedding model2 GB / 80 GB15%85% idle

These workloads could share a single GPU β€” if the isolation is sufficient.


2. MIG (Multi-Instance GPU)

MIG partitions the GPU in hardware β€” dedicated SMs, memory controllers, and L2 cache per partition. The strongest isolation available.

How MIG Works

H100 (80 GB, 132 SMs):
  └── Partition into instances:
      β”œβ”€β”€ Instance 0: 1g.10gb (1/7 GPU, 10 GB, ~19 SMs)
      β”œβ”€β”€ Instance 1: 1g.10gb
      β”œβ”€β”€ Instance 2: 1g.10gb
      β”œβ”€β”€ Instance 3: 1g.10gb
      β”œβ”€β”€ Instance 4: 1g.10gb
      β”œβ”€β”€ Instance 5: 1g.10gb
      └── Instance 6: 1g.10gb

  Or: mixed profiles
      β”œβ”€β”€ Instance 0: 3g.40gb (3/7 GPU, 40 GB) β†’ 70B INT4 inference
      β”œβ”€β”€ Instance 1: 2g.20gb (2/7 GPU, 20 GB) β†’ 13B model
      └── Instance 2: 2g.20gb (2/7 GPU, 20 GB) β†’ embedding service

Configuration

# Enable MIG mode (requires GPU reset)
sudo nvidia-smi -i 0 -mig 1

# Create instances
sudo nvidia-smi mig -i 0 -cgi 9,14,14    # 3g.40gb + 2g.20gb + 2g.20gb
sudo nvidia-smi mig -i 0 -cci             # create compute instances

# List instances
nvidia-smi mig -i 0 -lgi
# +---+------+--------+------+
# | 0 | 9    | 3g.40gb| 40GB |
# | 1 | 14   | 2g.20gb| 20GB |
# | 2 | 14   | 2g.20gb| 20GB |
# +---+------+--------+------+

# Use in Kubernetes
# Each MIG instance appears as a separate GPU resource:
# nvidia.com/mig-3g.40gb: 1
# nvidia.com/mig-2g.20gb: 2

MIG Profile Options (H100)

ProfileSMsMemoryUse case
1g.10gb~1910 GBSmall inference (1-3B INT4), embedding
2g.20gb~3820 GBMedium inference (8B), fine-tuning experiments
3g.40gb~5740 GBLarger inference (13-30B INT4)
4g.40gb~7640 GBSame memory, more compute
7g.80gb13280 GBFull GPU (no partitioning)

MIG Limitations

  • Requires GPU reset to enable/disable MIG mode
  • Fixed profiles β€” can’t create arbitrary sizes
  • Not all GPUs support MIG β€” A100, H100, H200, B200 only
  • No NVLink between MIG instances β€” each instance is isolated

3. MPS (Multi-Process Service)

MPS allows multiple CUDA processes to share a GPU simultaneously via time-slicing at the CUDA context level:

Without MPS:
  Process A runs β†’ context switch β†’ Process B runs β†’ context switch
  (expensive context switches, ~ms each)

With MPS:
  Process A and B share the GPU simultaneously
  MPS server multiplexes their CUDA work onto the GPU
  (no context switches, overlapped execution)
# Start MPS server
nvidia-cuda-mps-control -d

# All CUDA processes on this GPU now go through MPS
# Set memory limit per process
echo "set_active_thread_percentage 50" | nvidia-cuda-mps-control

When MPS helps: Multiple small training jobs (hyperparameter search), each using <50% of the GPU. MPS lets them overlap instead of context-switching.

When MPS doesn’t help: If one process already uses 100% of compute, MPS adds overhead with no benefit.

Isolation: Weak β€” processes share the same memory space. A crash in one process can affect others. Not suitable for multi-tenant production.


4. Time-Slicing (Kubernetes)

The simplest approach β€” Kubernetes schedules multiple pods onto the same GPU, and NVIDIA’s time-slicing alternates between them:

# NVIDIA device plugin config for time-slicing
apiVersion: v1
kind: ConfigMap
metadata:
  name: nvidia-device-plugin
data:
  config.yaml: |
    version: v1
    sharing:
      timeSlicing:
        resources:
        - name: nvidia.com/gpu
          replicas: 4    # each GPU appears as 4 "virtual GPUs"

Now each H100 appears as 4 nvidia.com/gpu resources β€” 4 pods can each request 1 GPU and share the physical device.

Isolation: None β€” pods share all GPU memory. If one pod allocates too much, others OOM. Only suitable for development/non-critical workloads.


5. Comparison and Selection

MIGMPSTime-Slicing
IsolationHardware (strong)Weak (shared memory)None
Memory partitioningHardware-enforcedVoluntary limitsNone (shared)
OverheadNear-zeroLowMedium (context switch)
ConfigurationGPU reset requiredStart MPS daemonK8s config only
Failure isolationOne instance crashes, others fineCrash can propagateCrash can propagate
Best forMulti-tenant productionMultiple small training jobsDev/test only

Decision: If you’re running production multi-tenant inference β†’ MIG. If you’re maximizing a dev cluster β†’ time-slicing. MPS is niche (multiple small training experiments).

For dynamic scaling of GPU resources, see Dynamic Allocation.


Self-Check

  • Explain the GPU utilization problem that virtualization solves
  • Configure MIG on an H100 with mixed profiles (3g.40gb + 2Γ—2g.20gb)
  • Compare MIG vs MPS vs time-slicing on isolation, overhead, and use case
  • Explain why MIG requires a GPU reset and time-slicing doesn’t
  • Choose a virtualization approach for: (a) multi-tenant inference, (b) dev cluster

References