Bez kategorii

Niski odczyt GPU nie oznacza wolnej karty. Dlaczego zadania w Kubernetesie utknęły w kolejce

Wykres monitoringu pokazuje jednocyfrową aktywność GPU, a nowe zadanie w klastrze Kubernetes wciąż czeka na przydział sprzętu. Wbrew pozorom te dwa zjawiska często występują obok siebie: niski odczyt wykorzystania jednostek obliczeniowych nie oznacza, że karta jest dostępna dla kolejnego procesu.

Rozróżnienie to ma kluczowe znaczenie przy obsłudze modeli sztucznej inteligencji. Domyślnie Kubernetes traktuje zasób nvidia.com/gpu jako niepodzielny. Pod proszący o kartę otrzymuje ją na wyłączność. Nawet jeśli usługa generuje minimalny ruch i przez większość czasu wykonuje niewiele operacji, scheduler uznaje urządzenie za w pełni zajęte i nie skieruje na nie kolejnego zadania.

Z raportu firmy Cast AI wynika, że średnie wykorzystanie obliczeniowe GPU w analizowanych klastrach produkcyjnych wyniosło zaledwie 5 proc. Dane te opisują jednak wyłącznie średnią aktywność jednostek wykonawczych (SM), a nie wolną pojemność gotową do natychmiastowego zagospodarowania. Raport nie dowodzi też, że bezczynne karty i kolejki oczekujących zadań występowały jednocześnie w tych samych środowiskach.

Rozbieżność między monitoringiem a schedulerem

Powszechny wskaźnik wykorzystania GPU informuje jedynie o tym, jak intensywnie rdzenie karty przetwarzały dane w danym oknie czasowym. Nie uwzględnia on jednak stanu pamięci VRAM ani reguł alokacji w klastrze.

Usługa wnioskowania, która odbiera jedno zapytanie na minutę, wykaże znikome obciążenie obliczeniowe, ale załadowany do pamięci model pozostanie w niej na stałe. Z perspektywy schedulera karta jest zablokowana. Aby trafnie ocenić sytuację, konieczne jest rozróżnienie kilku odrębnych metryk:

  • Aktywność obliczeniowa – wskazuje czas pracy jednostek SM, lecz nie informuje o rezerwacji karty ani dostępności pamięci.
  • Zajętość VRAM – określa przestrzeń zajętą przez wagi modelu, bufory i pamięć podręczną KV. Model może blokować pamięć bez wykonywania obliczeń.
  • Czas oczekiwania poda – sygnalizuje brak możliwości uruchomienia zadania, ale nie wskazuje, czy przyczyną jest brak kart, brak VRAM czy reguły rozmieszczania.
  • Opóźnienia i przepustowość – mierzą jakość działania aplikacji, nie mówiąc nic o efektywności podziału zasobów.

Cztery źródła pozornego braku zasobów

Zanim zapadnie decyzja o dokupieniu kolejnych instancji GPU, warto zweryfikować rzeczywistą przyczynę blokady zadań. W praktyce problem rzadko sprowadza się do prostego braku mocy obliczeniowej.

1. Wyłączna rezerwacja karty. Domyślny mechanizm przydziału w Kubernetesie uniemożliwia współdzielenie GPU między podami, nawet gdy pojedynczy proces potrzebuje ułamka możliwości sprzętu. Dopiero wdrożenie technik takich jak time-slicing pozwala udostępnić schedulerowi więcej slotów na jednej karcie.

2. Ograniczenia pamięci VRAM. Model może nie obciążać procesora graficznego, ale zajmować całą dostępną pamięć. Sam serwer inferencyjny vLLM domyślnie rezerwuje 90 proc. VRAM już na etapie inicjalizacji kontekstu CUDA, jeszcze przed odebraniem pierwszego zapytania. Jeśli parametr ten nie zostanie skorygowany, próba uruchomienia kolejnego modelu na tej samej karcie zakończy się błędem braku pamięci (OOM), niezależnie od dostępnej mocy obliczeniowej.

3. Reguły rozmieszczania podów. Zadanie może tkwić w stanie oczekiwania mimo fizycznie wolnych GPU w klastrze, jeśli manifest wymaga konkretnego typu węzła, selektora etykiet lub brakuje mu odpowiednich tolerancji dla nałożonych ograniczeń (taints).

4. Wąskie gardła poza GPU. Niska aktywność karty bywa skutkiem opóźnień na wcześniejszych etapach: powolnego przygotowywania danych przez procesor CPU, wąskiej przepustowości magistrali PCIe, transferu sieciowego lub oczekiwania na odczyt z dysku. W takim scenariuszu karta czeka na dane, a zwiększenie liczby GPU nie przyniesie poprawy.

Metody współdzielenia a kompromisy architektoniczne

Jeśli przyczyną blokady jest wyłączna alokacja przy małym zapotrzebowaniu na pamięć i obliczenia, rozwiązaniem może być podział karty. Każdy mechanizm wiąże się jednak z innymi ograniczeniami:

  • Time-slicing – pozwala wielu procesom współdzielić czas pracy GPU i działa na większości generacji kart. Nie zapewnia jednak sprzętowej izolacji pamięci ani ochrony przed awariami sąsiednich procesów. Suma wymagań pamięciowych wszystkich podów musi bezwzględnie mieścić się w fizycznej pamięci VRAM.
  • Multi-Instance GPU (MIG) – dzieli kartę na poziomie sprzętowym na w pełni izolowane instancje z własną pamięcią i rdzeniami. Wymaga jednak nowszych architektur (Ampere lub nowszych) i oferuje sztywne, z góry zdefiniowane profile podziału.
  • Multi-Process Service (MPS) – umożliwia równoległe wykonywanie poleceń CUDA na tych samych jednostkach SM z mniejszym narzutem przełączania kontekstu, lecz nie daje pełnej izolacji sprzętowej.

Współdzielenie karty zwiększa liczbę dostępnych slotów, ale nie gwarantuje niższych opóźnień ani wyższej przepustowości. Przy rosnącym ruchu nakładające się zadania mogą konkurować o zasoby, co najczęściej uwidacznia się we wzroście opóźnień w ogonie rozkładu (metryki p95 i p99).

Optymalizacja wymaga całościowego podejścia

Oszczędności w infrastrukturze GPU rzadko wynikają z zastosowania pojedynczej funkcji. W przypadku platformy edukacyjnej ALLEN Digital, opisanym przez Cast AI, redukcja kosztów o 71 proc. była efektem złożonego zestawu działań: przejścia na instancje Spot, dopasowania limitów CPU i pamięci, upakowania zadań oraz time-slicingu. Samo współdzielenie kart odpowiadało jedynie za część tego wyniku.

Raport Cast AI podaje również przykład klastra z 136 kartami H200, w którym średnie wykorzystanie GPU wyniosło 49 proc. po usprawnieniu zarządzania zasobami. To wynik konkretnego środowiska, a nie gwarantowany efekt możliwy do osiągnięcia w każdym klastrze.

Kupno dodatkowych jednostek GPU jest uzasadnione dopiero wtedy, gdy po wykluczeniu wąskich gardeł w CPU, pamięci VRAM i konfiguracji schedulera fizyczna karta rzeczywiście osiąga granice swojej wydajności.