KubeCon2024 - Which GPU Sharing Strategy Is Right for You? A Comprehensive Benchmark Study Using DRA
https://youtu.be/nOgxv_R13Dg?si=PxCxfv_F0NCCAkRB
- Which GPU Sharing Strategy Is Right for You? A Comprehensive Benchmark Study Using DRA
GPU 자원이 워낙 희소하기에, Sharing은 오랜 시간 상당히 인기있던 주제.
GPU Sharing usecase는 보통 세 가지.
- Single user -> Multiple Apps (for many inference Jobs)
- Single tenant -> Multi Users (GPU subset을 활용해서 jupyter notebook 돌리거나, training)
- Multi tenant -> Multi Users (하나의 GPU에서 multi-tenant AI 서비스를 제공한다던가)
Space vs Time Partitioning
Space Partitioning: GPU의 특정 공간을 잘라서, 특정 Workload에 독점 할당하는 구조.
- Context Switching 없음 + 성능의 Predictability 확보
- GPU resource Subset만큼만 지원 가능 = limited number of Client
Time Partitioning: GPU workload를 context switching 형태로 사용하는 구조
- client 개수에 제한 없음 + 하나의 workload가 GPU resource 전체를 사용 가능.
- client 많아질수록 context switching overhead 발생, 성능을 예측하기 어려움.
구조상 서로 Trade off임.
Hardware vs Software Based Space Partitioning
MIG(Multi-instance GPU): Hardware (Physical) Partitioning.
- 장점: 특정 하드웨어는 특정 프로세스가 독점적으로 점유
- Full Fault isolation.
- Guaranteed Memory Bandwidth QoS
- Multi Tenant Environment에 적합
- 단점: 무한정 Partitioning 할 수는 없음.
MPS(Multi-Process Service): Logical Paritioning
- 장점: Flexible Partition Size. 원하는 memory limit / compute limit 설정 가능.
- 단점: GPU 하드웨어를 공유할 수밖에 없는 구조
- Fault isolation 제약
- Memory Bandwidth QoS 보장하지 못함
- Multi Tenant Environment에는 부적합
Layering Strategies
앞서 이야기했던 Partitioning 기법을 layer 형태로 적용할 수 있다.
- 하나의 GPU를 MIG로 paritioning한 다음, 개별 MIG를 time-slicing / MPS 형태로 제공한다거나
- vGPU: Full GPU처럼 보이지만 (time slice access to GPU), Wrapping the GPU inside of a hypervisor at the VM layer.
- isolation 효과
- MIG-backed vGPU: MIG로 분리, Wrapped by VM.
- CUDA streams: partitioning과 무관한, 순수 Application layer에서의 접근법.
- properly sharing individual resources that are available on a GPU, so you can run multiple kernels in parallel.
여기서는 Time Slicing, MPS, MIG만 구체적으로 소개할 예정.
- vGPU나 CUDA streams는 다른 종류의 의사결정이 선행되어야 하기 때문.
GPU Sharing in Kubernetes today
Dedicated
노드 한 대에 workload 하나 띄우는 것.
- limit으로 GPU 갯수를 설정하며
- node label을 걸어놓고 selector로 명시함.
time slicing
per-node 단위로 time slicing으로, 일종의 context switching 처럼 동작함.
MPS
per-node 단위로 space slicing한 걸로 보면 된다.
MIG
하나의 Nvidia GPU를 여러 개의 instance (compute engine) 형태로 분리한 것.
time slicing
MPS
Limitation
GPU가 실제로 어떻게 점유 / 공유되는지는 kubelet과 nvidia plug-in이 오롯이 관장하게 됨.
- 내 프로세스가 실행되는 GPU에서 어떤 다른 job이 실행되는지... 와 같은 정보를 파악하기 힘들다
- Incoming Request에 따라 동적으로 MIG Device provisioning할 방법이 없음
- No ability to Precisely Control the Fraction of GPU handled out per Jobs.
Control the Fraction of GPU
GPU를 Fraction 단위로 통제하기 위한 솔루션들이 있으나
- Extended Resource Model에 의존하고
- incoming resource request에 의존하는 Custom Scheduler가 필요하다.
GPU Sharing With DRA (Dynamic Resource Allocation)
count-based interface 말고, 보다 확장된 형태의 request / configuring resource를 지원함.
- k8s 1.26부터 알파로 추가된 기능으로, 1.32에 beta로 올라갈 예정.
- Persistent Volume API에서 착안한 방식.
Dedicated
ResourceClaimTemplate 이라는 kind를 정의한다.
- deviceClassName으로 gpu.nvidia.com 을 명시할 수 있음.
- deviceClassName은 DRA driver 설치했을 때 지원 가능한 클래스 이름이다.
Pod을 생성할 때, resourceClaim 항목에 resourceClaimTemplate 이름을 명시하는 방식.
- unique resource claim behind the scenes, with own unique GPU mapped to that.
- 위 예시의 경우 gpu 2개에 접근하는 pod 예시.
Shared GPU
하나의 pod 내 여러 개의 container에 Shared GPU 공유하기
여러 개의 pod에서 shared gpu 정의해서 사용하기
Time slicing
resourceClaim에서 config 항목에 sharing strategy를 정의하면 된다.
MPS
fraction정보와 limit정보 명시한 뒤, 해당 리소스에 적용할 수 있는 pod를 매핑하는 식.
Combination
Benchmark Study
DRA 활용한 GPU Sharing Strategy의 Benchmark 정보
- 작업: inference workload, small GPU batch jobs, GPU intensive jobs
- Sharing Strategy: Time-slicing, MPS (with resource limit, without resource limits), MIG
Light Inference Workload
Triton inference server 2대. performance analyzer 포함 (https://docs.nvidia.com/deeplearning/triton-inference-server/archives/triton-inference-server-2280/user-guide/docs/user_guide/perf_analyzer.html#)
- request rate를 simulate.
resource claim에서 Sharing Strategy에 맞게 각각 설정.
- triton 서버의 경우 환경변수로 request / limit를 정의함.
result
노란색: Dedicated GPU, 주황색: Sharing GPU
Time Slicing
- latency: 큰 차이 없음
- throughput: 큰 차이 없음
- GPU usage: 3배 증가. 2배 증가가 아니라 3배 증가한 이유는 context overhead of time slicing 때문.
MPS
- latency: 큰 차이 없음
- throughput: 큰 차이 없음
- GPU usage: 2배 증가.
단 MPS는 software isolation 방식, 하드웨어는 근본적으로 구분되지 않는다.
- Limited Fault Tolerance.
- Slower startup time
- Additional MPS Daemonset이 필요함.
Heavy Inference Workload
time slicing
- GPU sharing하면 전반적인 성능이 하락. Latency 증가 / Throughput 감소. GPU usage도 100%
MPS without resource limits
- 성능은 감소하지만 time slicing보다는 나은 성능을 보여준다. context switch overhead는 없기 때문
MPS with Resource Limits (no priority)
- 적절한 수준의 resource limit을 정해주면, 성능 감소폭이 크지 않다.
- Time slicing의 경우, Latency가 덜 중요한 workload라면 적용할 만 함.
- MPS는 약간의 성능 하락이 있지만, 감안하고 쓸 정도는 된다.
- resource Limit 잘 걸어주면 성능 하락폭이 줄어들어서 더욱 괜찮아진다.
Small GPU Bacth Job
Dedicated, Time Slicing, MPS로 테스트 수행
각각의 declaration 방법은 위와 같음.
result
parallel 4로 Time sharing task 실행 시
- GPU 사용량 100%
- performance 저하 - execution time이 증가함. (context switching에 드는 비용 때문)
parallel 4로 MPS task 실행 시
- GPU 사용량 증가
- performance 저하는 거의 없음. low ovrerhead
GPU intensive Batch Job
gpu-burn 작업을 수행 (micro stress testing)
declaration yaml 파일
result
time sharing의 경우
- fair Memory sharing을 보장하지 않으므로, job 하나가 10배 넘게 쓴다.
MPS에 resource limit이 없을 경우, fair memory sharing을 보장하지 않으므로 time sharing과 마찬가지 결과.
resource Limit을 설정한 경우, 정의된 만큼만 메모리 사용.
GPU intensive job일 경우, resource limit을 정의한 MPS 방식을 사용하는 것이 좋다.
MIG
A100 한 대를 4 MIG instance로 나눠서 사용.
- 2 * 1g.5gb
- 1 * 2g.10gb
- 1 * 3g.20gb
inference workload
small instance와 large instance에 request rate를 low / high로 테스트.
resource claim으로 위와 같이 정의하면 된다.
result
Same Performance. (isolation이 잘 되어 있다)
- small server가 worse인 이유는, right size of request / workload가 맞으면 효율이 극대화된다는 것을 보여줌.
GPU intensive Batch job
gpu burn job을 small instance / large instance에 배포한다.
- 정상 동작하는 경우, OOMKilled 발생하는 경우를 테스트
small instance, large instance 적용하기
result
resource isolation은 (당연하게도) 잘 된다.
- too many memory allocate 시도할 경우 Out of Memory 발생
하드웨어 Partitioning이므로 QoS, Fault tolerance를 보장함.
- Multi-tenant 구조에 보다 적합하다
단, Nvidia GPU 구조상 Partition Size를 마음대로 지정할 수 없다 (Max 7)
Summary of BenchMark Study
takeaway
- GPU Sharing은 호율적인 리소스 사용 / 비용 절감의 핵심.
- 각각의 sharing 방법에는 tradeoff가 있다.
- DRA: GPU 할당을 보다 configurable하고 unified way로 제공하기 위해 k8s에서 지원하는 방법
- GPU resource allocation / sharing 방법을 단순화
- k8s 1.32+ 에서 Beta feature로 제공
time slicing
- 가장 단순하고 쉬운 방법
- Lack of Resource Guarantees, Context Switch overhead
MPS (Multi process Service)
- 애플리케이션에 필요한 resource limit을 지정할 수 있음, Lower Overhead
- Multi-Tenant 환경에서 Memory-related Fault 발생 시 영향을 받을 수 있다.
MIG (Multi-Instance GPU)
- 하드웨어 Partitioning이므로, QoS와 Fault Tolerance를 확실히 보장
- Partition Size가 고정되어 있음
Q&A
Q1. GPU Self-Service Portal 같은 경우 사용자가 뭘 얼마나 필요로 할지 알기가 어렵다. k8s의 경우 greate resource fraction을 지원하고, scheduler도 잘 되어 있다. 리소스 요청 / 할당 인터페이스를 k8s처럼 만들 생각은 없는지?
- 요구사항은 인지하고 있음. k8s DRA팀과도 이야기해봤는데, 아직 갈 길이 멀더라.
Q2. inference 항목에서, MPS with resource limit의 성능이 without limit보다 더 좋더라. 이유를 설명해줄 수 있는지?
- without limit이라는 건, 특정 프로세스가 리소스를 얼마나 점유할 것인지 보장하지 않는다는 뜻. 그래서 랜덤성이 발생했다고 봐야 함.
Q3. MPS에서 적용하기 위한 최적의 limit값은 얼마라고 계산할 수 있는가?
- 벤치마크로 미리 확인해봐야 함. 표준이라고 말할 만한 방법은 없다.