Skip to content

Instantly share code, notes, and snippets.

@mu-hun
Last active March 9, 2025 11:53
Show Gist options
  • Save mu-hun/4ef092305d307f9c0a4bb81415512c4b to your computer and use it in GitHub Desktop.
Save mu-hun/4ef092305d307f9c0a4bb81415512c4b to your computer and use it in GitHub Desktop.
`nvshare`: 메모리 크기 제약 없는 실용적인 GPU 공유

nvshare: 메모리 크기 제약 없는 실용적인 GPU 공유

읽기 전에...

아래 인용 아티클의 영상 버전 및 nvshare 데모: https://youtu.be/9n-5sc5AICY

I've written a Medium article on the challenges of GPU sharing on Kubernetes, it's worth a read.1

연구 키워드 정리

CUDA는 다들 아실 것 같아 생략합니다.

CUDA

Compute Unified Device Architecture(CUDA)는 NVIDIA GPU에서 범용 컴퓨팅을 가능하게 하는 잘 확립된 플랫폼 및 API입니다. CUDA는 Python 및 C++와 같은 다양한 프로그래밍 언어와 함께 작동하도록 설계되었습니다. API를 통해 CUDA는 GPU의 가상 명령어 및 계산 요소에 대한 액세스를 제공합니다. CUDA 프로그램은 CPU에서 실행되는 호스트 코드와 GPU에서 실행되는 장치 코드의 혼합으로 구성됩니다.

CUDA Context

CUDA Context는 CPU 프로세스에 해당하는 GPU입니다. GPU를 활용하기 위해 애플리케이션은 Context를 생성하고 해당 명령(예: 메모리 할당 및 계산)을 발행합니다. 각 Context는 자체 페이지 테이블 세트(가상 주소 공간)를 가지고 있으며 다른 Context의 메모리에 액세스할 수 없습니다. 동일한 GPU에 여러 Context가 동시에 존재하지만, 주어진 순간에는 하나만 작업을 실행할 수 있습니다.

블랙박스 CUDA 드라이버는 공개되지 않은 방식으로 동일한 GPU에서 실행되는 Context를 Time-Slice 합니다. 이 시간 조각은 몇 밀리초 단위입니다. GPU 메모리를 할당하는 표준 방법은 cuMemAlloc이라는 방법을 사용하는 것입니다.

이러한 방식으로 할당된 모든 가상 메모리 바이트는 물리적 메모리 바이트에 의해 백업되어야 합니다. 이 개념의 함의는 모든 Context에 걸친 GPU 메모리 할당의 합계가 기껏해야 물리적 GPU 메모리 크기와 같을 수 있다는 것입니다. 예를 들어, 16GB GPU 메모리의 경우, 한 프로세스가 10GB를 할당하면 다른 프로세스는 치명적인 OOM 오류가 발생하지 않고 최대 6GB의 GPU 메모리를 할당할 수 있습니다.

CUDA는 Context 별 메모리 할당 크기를 제한하는 방법을 제공하지 않습니다. 모든 응용 프로그램의 최고 GPU 메모리 사용을 선험적으로 알 수 없다는 점에 유의하십시오. 결과적으로, 쿠버네티스 및 Slurm2과 같은 Orchestrator 는 일대일 작업 대 GPU 할당 정책을 시행하고 공유를 허용하지 줌으로써 OOM 오류의 위협을 해결합니다.

Unified Memory

통합 메모리(UM)3 하드웨어/소프트웨어 기술은 시스템의 RAM을 swap 공간으로 사용하여 GPU의 페이지 오류를 기능하게 하기 때문에 앞서 언급한 문제를 해결합니다. 페이지 가능한 메모리를 할당하기 위해, CUDA 프로그램은 cuMemAllocManaged 방법을 사용합니다. 페이지 오류가 발생하면 UM 하위 시스템(커널 모듈)은 누락된 페이지를 GPU 메모리로 가져오고 가장 오래전에 사용된(LRU) 교체 정책을 사용하여 모든 Context에서 호스트 RAM으로 퇴거할 페이지를 선택합니다. 따라서 UM은 모든 Context 에 걸친 메모리 할당의 합계가 GPU 물리적 VRAM 크기를 초과를 가능하게 만듭니다.

결과

  • Co-located processes limited by systeam RAM
  • Each process can use the entire GPU memory

자세한 사항은 지원되는 GPU 섹션을 참고 바랍니다.

Thrashing

Thrashing은 페이지 오류를 처리하는 데 소요된 시간이 유용한 계산을 수행하는 데 소요된 시간을 압도하는 상황입니다. 개발자가 GPU 메모리를 과도하게 구독할 때, 함께 위치한 앱의 작업 세트(즉, 그들이 적극적으로 사용하고 있는 데이터; 할당의 하위 집합)가 해당 GPU VRAM에 맞지 않을 때 Thrashing 을 피해야 합니다. 블랙박스 CUDA 스케줄러의 지속적인 밀리초 스케일 Context 전환은 이 위험을 악화시킵니다.

요약: 페이지 오류가 자주 발생하면 시스템은 프로세스를 실행하는 것보다 이를 처리하는 데 더 많은 지연 시간을 소비하는 것을 Thrashing 이라고 부릅니다. 또한 이로 인해 전반적인 성능도 저하됩니다.

Nvshare는 Pascal 아키텍처에 도입된 Unified Memory의 동적 페이지 오류 처리 메커니즘에 의존합니다. 모든 Pascal(2016) 또는 최신 Nvidia GPU를 지원합니다. Linux 시스템에서만 테스트되었습니다.

(운영체제 개념) 페이지 오류 처리 메커니즘 소개

Page Replacement Algorithm

다른 분 블로그에서 가져왔습니다. [OS] Virtual Memory System

새로운 페이지를 메모리에 적재해야 하는데 저장공간이 부족한 경우, 어떤 것을 쫒아낼 것인가? ➜ 다시 사용안될 가능성이 큰 메모리를 쫒아내야 한다.

알고리즘 설명
FIFO 가장 오래전에 적재된 페이지를 버린다.
Second chance FIFO를 약간 보완한 방식이다.
페이지의 reference bit를 사용하여 최근에 사용된 페이지에 "두 번째 기회"를 제공한다.
Clock Second Chance를 원형으로 적용한 알고리즘이다.
Optimal Page Replacement(OPT) 이론적인 모델
미래에 가장 오랫동안 사용되지 않을 페이지를 버린다.
LRU(Least Recently Used) 가장 오래전에 참조된 페이지를 버린다.
제일 많이 사용하는 알고리즘이다.
NRU(Not Recently Used) 가장 낮은 우선순위의 클래스에서 페이지를 선택하여 버린다.
NFU(Not Frequently Used) Aging 알고리즘과 같이 사용하여 LRU를 근사적으로 구현
각 페이지에 대한 참조 횟수를 계산하여 메모리에서 가장 적게 사용된 페이지를 버린다.
  • 성능: OPT > LRU > CLOCK > FIFO

Page Fault Handling

  • A 명령어를 실행하고자 필요한 페이지가
    • 마이너: 메모리에 있지만 현재 프로세스의 페이지 테이블에 없는 경우
    • 메이저: 페이지가 메모리에 없고 디스크에서 가져와야 하는 경우
    • 잘못된 페이징: 프로세스가 잘못된 메모리 주소에 접근하려고 할 때
  • (CPU) Page Fault Handling 절차
    1. Page fault 발생
    2. CPU는 인터럽트(Page fault interrupt)를 걸어서 운영체제로 점프 - Fault를 일으킨 주소는 스택에 저장
    3. CPU 내부의 레지스터들도 스택에 저장
    4. OS가 SWAP에 존재하는 페이지를 메모리에 적재 후, 페이지 테이블 수정(valid bit = 1)
    5. 리턴 후 CPU는 A부터 실행

⠀위와 같은 과정을 Page Fault Handling라 한다.

  • 일반 Interrupt가 걸리면 명령어 A를 다 끝낸 다음에 OS로 점프한다.
  • 하지만, Page fault Interrupt는 인터럽트가 걸린 시점의 명령어(A)부터 다시 실행한다.

페이지 오류가 시스템 성능에 어떤 영향을 미치는가

Page Fault Handling in Operating System - Geeks for Geeks Page Fault가 자주 발생하는 경우 시스템에 아래와 같은 영향을 미칩니다.

  • Thrashing: 페이지 오류가 자주 발생하면 시스템은 프로세스를 실행하는 것보다 이를 처리하는 데 더 많은 시간을 소비하며, 그로 인해 전반적인 성능도 저하됩니다.
  • 증가된 지연 시간: 디스크에서 페이지를 가져오는 것은 메모리에서 액세스하는 것보다 시간이 더 많이 걸리며, 이로 인해 더 많은 지연이 발생합니다.
  • 동일한 GPU에서 빈번하지 않게 GPU 버스트가 발생하는 2+ 프로세스/컨테이너 실행(예: 대화형 앱, ML 추론)
    • GPU 버스트란 특정 GPU 작업을 연속적으로 처리하는 것,
    • 주로 GPU 실행이 많이 필요한 작업을 수행할 때 일어난다.
  • 동일한 GPU에서 2+ 비-대화형 워크로드(예: ML 교육)를 실행하여 총 완료 시간을 최소화하고 대기열을 줄입니다.
  • 여러 프로세스/컨테이너 간의 단일 GPU 공유
    • 아래 언급하는 코로케이션 프로세스를 (공동-위치 작업) 의미함
  • 이 프로젝트에서 사용하는 코로케이션 프로세스NVIDIA MPS 와 같은 다른 접근 방식과 달리 서로 다른 CUDA contexts 를 사용하기 때문에 메모리 및 장애 격리가 보장됩니다.
  • 투명성 (zero-config?): 준비한 앱 내부에서 코드 변경 이 필요하지 않습니다.
  • 각 프로세스/컨테이너는 전체 GPU 메모리를 사용할 수 있습니다.
    • Unified Memory 를 사용하여 GPU 메모리를 시스템 RAM으로 swap 합니다.
    • 스케줄러는 Thrashing을 피하기 위해 겹치는 GPU 작업을 선택적으로 직렬화합니다(한 번에 TQ초 동안 하나의 앱에 대한 독점 액세스를 할당합니다)
    • TQ가 경과하기 전에 작업이 완료되면 앱은 GPU를 해제합니다.

정리

  • Unified Memory: GPU VRAM을 동적 페이지 오류 처리(Dynamic Page fault handling)를 통해 마치 시스템 RAM 공간처럼 다루어 각 앱마다 메모리 공간 할당을 동적으로 기능하게 함
  • 물리적 GPU 메모리 초과 활용: 동적 할당을 하게 되니 모든 앱의 실행된 동안 할당 되었던 최대 GPU 메모리 리소스를 합치면 물리적 VRAM 크기 초과를 가능하게 됩니다.

Unifined Memory 섹션 발췌: 페이지 오류가 발생하면 UM 하위 시스템(커널 모듈)은 누락된 페이지를 GPU 메모리로 가져오고 가장 최근에 사용된(LRU) 교체 정책을 사용하여 모든 Context에서 호스트 RAM으로 퇴거할 피해자 페이지를 선택합니다. 따라서 모든 Context 에 걸친 메모리 할당의 합계가 GPU 물리적 VRAM 크기를 초과를 가능하게 만듭니다.

추가 자료

Footnotes

  1. 번역 - K8s의 GPU 가상화: 도전과 최첨단

  2. Slurm workload manager. https://slurm.schedmd.com/documentation.html. [Online; accessed 22-October-2023].

  3. Unified Memory Programming. https://docs.nvidia.com/cuda/cuda-cprogramming-guide/index.html#um-unified-memory-programming-hd. [Online; accessed 21-October-2023].

K8s의 GPU 가상화: 도전과 최첨단

원문: GPU Virtualization in K8s: Challenges and State of the Art | Medium

GPU는 일반적으로 Jupyter Notebook에서 수행되는 처리량 집약적 모델 교육, 지연 감지 추론 및 대화형 개발로 구성된 기계 학습 워크로드를 가속화하는 데 필수적입니다. 일반적인 관행은 ML 작업을 Kubernetes에 의해 관리되는 컨테이너로 배포하는 것입니다.

1. GPUs and Kubernetes

쿠버네티스는 전체 장치를 단일 작업에만 할당하여 GPU 워크로드를 예약합니다. 이러한 일대일 관계는 특히 상당한 유휴 기간과 과도한 GPU 사용의 빈번하지 않은 폭발을 특징으로 하는 대화형 작업의 경우 대규모 GPU 활용 부족으로 이어집니다.

더 보기현재 마련된 기성 솔루션은 각 공동 작업에 GPU 메모리의 고정 슬라이스를 정적으로 할당하여 GPU 공유를 가능하게 합니다. 이러한 솔루션은 공동 위치 작업의 수가 물리적 GPU 메모리 크기에 의해 제한되기 때문에 대화형 시나리오에는 적합하지 않습니다. 결과적으로, 사용자는 실행을 위해 작업을 제출하기 전에 작업의 GPU 메모리 수요를 알아야 하며, 이는 비실용적입니다.

2. GPU and Kubernetes

NVIDIA는 범용 GPU 컴퓨팅과 관련하여 단연코 가장 널리 퍼진 GPU 벤더입니다. 구글 클라우드 플랫폼아마존 웹 서비스는 거의 독점적으로 NVIDIA GPU를 제공합니다.

쿠버네티스 클러스터에서 GPU를 처리하는 사실상의 방법은 엔비디아의 디바이스 플러그인1을 이용하는 것입니다. N개의 물리적 GPU가 있는 쿠버네티스 노드의 경우, 장치 플러그인은 N개의 nvidia.com/gpu 장치를 클러스터에 나타냅니다. 컨테이너는 소수의 CPU와 메모리를 요청할 수 있지만, GPU는 정수로만 요청할 수 있습니다.

따라서 쿠버네티스는 GPU와 컨테이너 간에 1-1 할당을 시행합니다. 컨테이너가 수명 기간 동안 GPU에서 최소한의 작업을 하더라도, 컨테이너가 실행되는 동안 해당 GPU는 나머지 클러스터에서 사용할 수 없습니다.

2. GPU ML 사용 패턴

선형 대수 연산은 ML 계산의 핵심입니다다. GPU는 본질적으로 엄청나게 평행하며, 이러한 간단한 선형 대수 연산을 동시에 수행할 수 있습니다. 기계 학습은 엄청난 양의 데이터를 처리해야 합니다. 따라서 GPU의 높은 메모리 대역폭은 ML 개발 프로세스 속도를 높이는 데 활용됩니다.

K8s의 기계 학습 작업은 일반적으로 다음 세 가지 버킷에 속합니다:

  1. 훈련
  2. 추론된 것
  3. 대화형 개발/실험

추론 작업 요청은 무작위로 오고, 유휴 기간(IDLE)이 상당해서 GPU 활용도가 제한됩니다. 보통 ML 실무자는 장기 실행 대화형 도구인 Jupyter Notebooks 위에서 개발합니다.

ML 개발 작업 특징 (주피터 노트북)

  • 애플리케이션의 GPU 작업 실행 시간을 사전에 계산/구속될 수 없기 때문에 미리 정해진 양의 작업을 수행하지 마십시오.
  • 급작스럽게 많은 컴퓨팅이 일어나는 경우(bursts)와 유휴 기간이 긴 GPU 사용 패턴이 있는 장기 실행 작업입니다. (코드 리팩토링/디버깅/개발자 중단 중)

3. 문제 (1-1 바인딩이 나쁜 아이디어 인 이유)

일반적으로 하나의 프로세스만이 GPU를 완전히 사용할 수 있습니다. 이는 특히 MPI 작업 (여러 컴퓨터/프로세스에서 실행되는 작업)과 같이 하나의 프로세스가 GPU의 기능을 충분히 활용하지 못할 때 비효율적입니다..

위 도식을 보시면 GPU가 충분히 활용되지 않은 문제가 발생합니다. 동일한 GPU에서 작업(Kubernetes 컨테이너)을 공동 배치할 수 있는 옵션이 없기 때문에 대화형 ML 개발 또는 추론과 같이 간헐적인 GPU 버스트가 있는 작업에 대해 엄청나게 낭비적인 활용이 발생합니다.

다음은 문제를 표명하는 사용자의 몇 가지 사례가 있습니다:

4. NVIDIA는 왜 1-1 바인딩을 선택했는가?

1-1 바인딩이 유지되지 않는 반례 시나리오를 가정해 봅시다.

동일한 GPU를 사용하는 프로세스는 할당을 위해 동일한 물리적 GPU 메모리 풀을 놓고 경쟁합니다. 프로세스가 할당하는 각 바이트는 물리적 GPU 메모리의 바이트에 의해 백업되어야 합니다. 따라서 GPU를 사용하는 모든 프로세스에 걸친 메모리 할당의 합계는 GPU의 물리적 메모리 용량으로 제한됩니다.

프로세스가 GPU 메모리 사용량을 동적으로 성장 및 축소할 수 있고 할당 요청이 FIFO(선입선출) 순서로 처리되기 때문에 Out-of-Memory(OOM) 오류로 프로세스가 실패하는 시나리오가 있을 수 있습니다.

각 프로세스마다 별도의 페이지 테이블을 소유하기 때문에 한 프로세스가 다른 프로세스의 GPU 메모리 콘텐츠를 방해할 수 없지만, NVIDIA는 각 프로세스가 할당하는 GPU 메모리의 양을 제한하는 방법을 제공하지 않습니다.

5. K8에서 GPU 가상화의 진정한 도전

GPU의 배타적 할당 문제는 소소하게 해결될 수 있습니다. 예를 들어 업스트림 장치 플러그인을 수정하여 물리적 GPU보다 더 많은 수의 nvidia.com/gpu리소스 타입을 나타냅니다.

nvidia.com/gpu

쿠버네티스 디바이스 플러그인(물리적 장치를 연결해주는 확장 소프트웨어)을 한 번 설치하고 나면, 클러스터는 amd.com/gpu 또는 nvidia.com/gpu를 스케줄 가능한 리소스 키로써 노출시킵니다. 출처 - 쿠버네티스 문서 / 테스크 / GPU 스케줄링

kind: Pod
spec:
 containers:
- name: my-container
 image: myimage
 resources:
   requests:
     limits:
       nvidia.com/gpu: 1

위의 파드는 1개 nvidia.com/gpu 타입의 확장된 리소스를 요청합니다.

모든 완전한 해결책은 다음을 포함해야 합니다:

  • 동일한 노드의 프로세스 간에 GPU 사용을 격리하고 공유를 용이하게 하는 메커니즘
  • 사용자 지정 리소스를 요청 서식을(?) 통해 해당 메커니즘을 노출하는 K8s 방법

주어진 순간에 오직 하나의 컨테이너(CUDA 용어 안의 맥락)만이 GPU의 계산 단위를 적극적으로 사용할 수 있다는 것을 명확히 밝혀야 합니다. GPU 드라이버와 하드웨어는 컨텍스트 전환을 비공개로 처리하고, 독점적으로 GPU에 쏟은 시간 범위를 몇 밀리초 단위로 계산합니다.

6. GPU 가상화 및 공유에 대한 기존 접근 방식

우리는 GPU 메모리를 프로세스 간 GPU 공유의 핵심 차단 요소로 확인했습니다. GPU 공유 솔루션 뒤에 있는 팀들도 이를 차단 요인으로 확인했습니다.

우리가 언급할 기존의 모든 GPU 공유 접근 방식은 쿠버네티스와 통합되어 있습니다. 즉, 사용자가 nvidia.com/gpu(기본 방식)와 같은 방식으로 공유 GPU 장치를 소비할 수 있는 방법을 제공합니다.

따라서 메모리 문제를 해결하기 위해 선택한 방식에 따라 기존 GPU 공유 솔루션을 다음과 같은 범주로 분류할 수 있습니다.

A. 메모리 문제를 무시하는 해결책

이러한 접근 방식은 단순히 동일한 GPU의 여러 복제본을 쿠버네티스 클러스터에 광고하지만, 각 컨테이너의 GPU 메모리 사용을 제한하는 조치는 취하지 않습니다.

GPU 메모리 사용량의 합계가 물리적 GPU 메모리를 초과하지 않도록 "적절한 조치를 취해야" 합니다. 이러한 Out of Memory 오류를 피하기 위해서는 사용자에게 스스로 맡기도록 경고한다고 하네요.

그러한 주목할 만한 접근 방식은 다음과 같습니다:

  • Google Kubernetes Engine 의 Time-sharing GPU(Https://cloud.google.com/kubernetes-engine/docs/concepts/timesharing-gpus) 문서에 따르면 사용자는 애플리케이션 별 GPU 메모리 제한을 스스로 설정해야 합니다. 문서 인용:

    "GKE는 물리적 GPU를 공유하는 컨테이너 간에 메모리(주소 공간) 격리, 성능 격리 및 오류 격리를 시행합니다. 그러나, Time-sharing GPU에는 메모리 제한이 적용되지 않습니다. 메모리 부족(OOM) 문제를 피하려면 애플리케이션에서 GPU 메모리 제한을 설정하십시오."

  • 엔비디아 장치 플러그인 - CUDA Time-Slicing 이 접근법은 CPU 프로세스와 동등한 동일한 CUDA Context 에서 여러 애플리케이션을 실행하여 GPU 장치를 과도하게 구독합니다. 단점은 CUDA 메모리를 무효화하고 오류 격리를 보장한다는 것입니다. 문서 인용:

    "그러나 동일한 기본 GPU에서 복제본을 부여받은 워크로드를 격리하기 위해 특별한 작업을 수행하지 않았으며, 각 워크로드는 GPU 메모리에 액세스할 수 있으며 다른 모든 워크로드와 동일한 오류 도메인에서 실행됩니다(즉, 하나의 워크로드가 충돌하면 모두 충돌합니다)."

    • 그 외에 CUDA MPS를 지원하나 아직 쿠버네티스에선 실험적 기능입니다.
    • CUDA Multi-Process Service - NVIDIA

      여러 프로세스가 하나의 GPU를 공유할 수 있는 런타임 서비스

      • MPS를 사용하면 여러 프로세스가 하나의 GPU를 공유할 수 있습니다. "Hyper-Q"를 통해 GPU의 여러 부분을 동시에2 여러 작업 (커널)에 사용할 수 있도록 합니다. 이는 고속도로에 여러 개의 차선이 있는 것과 같습니다.

B. 메모리 문제를 어느 정도 해결하는 해결책

우리는 이것들을 다음과 같이 더 분류할 수 있다:

B1. 시행(enforcement) 메커니즘 없이 GPU 메모리 슬라이싱을 구현하는 것들:

알리윤 GPU 공유 스케줄러 익스텐더 ( https://github.com/AliyunContainerService/gpushare-scheduler-extender)

이 접근법은 리소스 aliyun.com/gpu-mem을 클러스터에 보여주는 사용자 지정 장치 플러그인을 사용합니다. 정수 GPU 수량을 요청하는 대신, 컨테이너는 이제 GPU 메모리의 MiB를 요청하고, Kubernetes bin은 GPU 메모리 요청을 기반으로 컨테이너를 포장합니다.

그러나, 이 접근법은 GPU 메모리 슬라이싱을 시행하지 않으며, 대신 섹션 (A)의 접근 방식과 마찬가지로 사용자에게 맡기고 있습니다.

OOM 오류는 GPU를 공유하는 모든 컨테이너에서 여전히 발생할 수 있습니다.

B2. 런타임 동안 GPU 메모리 슬라이싱을 강제하는 것들

이러한 접근 방식은 쿠버네티스 스케줄링에 관한 B1의 접근 방식과 유사한 접근 방식을 따릅니다. 즉, 빈 패킹을 위해 GPU 메모리를 사용합니다.

이 접근법은 GPU 메모리를 사용하여 컨테이너 요청을 예약할 뿐만 아니라 이러한 요청을 실행에 적용합니다. 예를 들어, 500 MiB를 요청한 컨테이너는 런타임에 최대 해당 양의 GPU 메모리를 할당할 수 있습니다. 더 많이 할당하려고 하면, OOM 오류로 실패합니다. Kubeshare 는 CUDA API 메모리 할당 호출을 연결하고 컨테이너가 Kubernetes에서 요청한 것보다 더 많은 메모리를 할당할 수 없도록 함으로써 이를 달성합니다. TKEStack GPU 관리자(tkestack/gpu-manager)이 접근 방식은 Kubeshare와 매우 유사합니다. GPU 메모리 요청을 기반으로 컨테이너를 예약하여 런타임에 시행합니다.

7. 기존 접근 방식의 단점

메모리에 대한 하드 제한

기존의 모든 접근 방식은 사용자가 워크로드를 제출할 때 지정해야 하는 GPU 메모리에 하드 제한을 부과합니다. 특히 대화형 개발 작업이 관련될 때는 작업의 최대 메모리 사용량을 사전에 아는 것은 일반적으로 불가능합니다. 이 엄격한 제한은 점진적으로 더 큰 모델을 테스트하는 것과 관련하여 사용자의 워크플로우의 유연성을 제한합니다. 스스로 메모리 제한을 다루면서 대부분 사용되지 않는 많은 양의 메모리를 요청하거나 OOM 오류에 직면할 수 있습니다.

물리적 GPU 메모리에 의해 제한된 공동 위치 프로세스의 수

이미 언급 했듯이, 정상적인 CUDA 메모리 할당의 경우, 모든 프로세스에 걸친 합계는 물리적 GPU 메모리 용량보다 작아야 합니다. 결과적으로, 모든 기존 계획에서, 함께 배치될 수 있는 프로세스의 수는 이 메모리 용량에 의해 제한됩니다. GPU 메모리를 과도하게 구독할 수 있는 옵션은 없습니다.

8. 현재 기술 상태 평가

할당은 더 이상 Pods 와 GPU 간에 배타적이지 않으며, K8s가 bin packing 에 사용하는 새로운 자원은 GPU 메모리입니다.

이러한 기존 GPU 공유 접근 방식은 GPU 메모리 크기가 예측 가능하기 때문에 ML 추론에 적합합니다.

그러나 이 새로운 기준은 GPU burst 가 빈번하지 않은 워크로드의 특성(예: Jupyter 노트북의 대화형 ML 모델 탐색)과 결합되어 여전히 활용 부족 시나리오를 허용합니다.

GPU에 4GB의 메모리가 있고 사용자가 2.5GB 메모리 요청으로 작업 A를 먼저 제출하고 다른 사용자가 2GB 요청으로 작업 B를 제출하는 시나리오를 상상해 봅시다.

작업 A의 실제 메모리 사용량에 관계없이 작업 B는 작업 A가 실행되는 동안 절대 예약되지 않습니다. 이는 계산 집약적인 작업(ML 교육)의 경우 허용되지만, 대화형 작업의 경우 GPU는 작업 A의 결정되지 않는 기간 동안 활용도가 낮습니다.

부록

ML 프레임워크의 GPU 메모리 처리

ML 프레임워크는 내부 하위 할당자를 통해 GPU 메모리를 처리하는 것을 선호합니다. 따라서, 그들은 GPU 메모리를 큰 덩어리로 요청하고 일반적으로 실제보다 "수요"를 초과합니다. 또한, Tensorflow3는 기본적으로 모든 GPU 메모리를 할당합니다. 이 동작은 필요에 따라 GPU 메모리 사용량이 증가할 수 있도록 선택적으로 변경될 수 있습니다. 여전히 그 사용은 결코 줄어들지 않을 것입니다. ML 작업의 "실제" 요구가 500MiB에서 2.5 GiB로 변동한 다음 500MiB로 돌아간 경우, TF 프로세스가 종료될 때까지 할당된 GPU 메모리는 2.5 GiB가 될 것입니다.

Footnotes

  1. NVIDIA/k8s-device-plugin: NVIDIA device plugin for Kubernetes

  2. 원문에는 "concurrently" 라고 표현되어 있어서 아마 Time-Sharing 과 같은 동시성을 뜻하는 것 같습니다.

  3. https://www.tensorflow.org/guide%20gpu%5C#limiting_gpu_memory_growth

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment