Od czego zacząć: czego naprawdę potrzebuje Twoje AI
Różnica między „AI jako eksperyment” a „AI w produkcji”
Infrastruktura pod AI wygląda zupełnie inaczej, gdy kilka osób testuje modele na potrzeby PoC, a inaczej, gdy te same modele obsługują tysiące zapytań na minutę w systemie krytycznym. Mieszanie tych dwóch perspektyw prowadzi prosto do przepalonych budżetów i wąskich gardeł wydajności.
AI jako eksperyment to sytuacja, w której:
- modele są często zmieniane,
- zestawy danych rosną, ale nadal mieszczą się na pojedynczych maszynach lub w prostym klastrze,
- ważniejsza jest elastyczność i szybkość „od pomysłu do wyniku” niż absolutna stabilność czy SLA,
- część zadań można spokojnie wrzucać w kolejkę i wykonać nocą.
AI w produkcji wymusza inne priorytety:
- wymagane są jasno zdefiniowane SLA (czas odpowiedzi, dostępność),
- pipeline danych i trenowania musi być powtarzalny i automatyzowalny,
- infrastruktura musi wytrzymać awarie pojedynczych komponentów bez zatrzymania całego systemu,
- koszt jednostkowy inferencji zaczyna być istotny (szczególnie przy dużym wolumenie zapytań).
Jeśli zespół nie zacznie od uściślenia, czy inwestuje w środowisko eksperymentalne, produkcyjne, czy hybrydę (częste w średnich firmach), to dobór CPU, GPU, storage i sieci będzie zbiorem przypadkowych decyzji. A przypadki w infrastrukturze AI kończą się zwykle tym, że GPU za setki tysięcy złotych stoją bezczynnie, bo blokuje je pojedynczy serwer NFS lub łącze 1 GbE.
Typy obciążeń AI a wymagania infrastruktury
Większość projektów AI da się rozbić na kilka podstawowych typów obciążeń. Każdy z nich ma inny „profil apetytu” na CPU, GPU, RAM, sieć i storage. Uproszczenie wszystkich do „potrzebujemy kilku mocnych GPU” jest prostym przepisem na wąskie gardła wydajności.
Najczęstsze obciążenia:
- Eksploracja danych (EDA, feature engineering) – dominuje CPU, RAM i I/O do storage. Tu wąskim gardłem staje się zwykle pojedynczy dysk lub ograniczony RAM, nie brak GPU.
- Trening modeli:
- dla klasycznych modeli ML (XGBoost, Random Forest, klasyfikatory liniowe) – mocny CPU i dużo RAM będą ważniejsze niż GPU,
- dla NLP, wizji komputerowej, dużych sieci neuronowych – GPU staje się kluczowe, ale tylko jeśli dane „nadążają” za akceleratorami.
- Inferencja (wnioskowanie z gotowych modeli):
- batch (hurtowe przetwarzanie) – zwykle można zredukować wymagania sieciowe i skupić się na przepustowości GPU/CPU,
- real-time (API online) – czas reakcji zależy od sieci, obciążenia CPU, planisty kontenerów i opóźnień do baz danych.
- Pipeline ETL/ELT dla danych treningowych – to osobny świat: narzędzia typu Spark/Flink, masowe I/O do hurtowni danych, integracja z feature store. AI często jest tylko ostatnim etapem.
Dla różnych typów zadań nawet ten sam model będzie mieć inne wymagania. Klasyczny przykład: model rekomendacyjny. Trening może wymagać klastra GPU i szybkiego rozproszonego storage, a inferencja – dużej pamięci RAM i szybkich połączeń z bazą user events, ale już niekoniecznie dziesiątek GPU.
Scenariusze zastosowań a profil zasobów
Poszczególne typy zastosowań AI narzucają charakterystyczne profile obciążeń:
- Klasyfikacja i regresja na tabelach – dominują:
- CPU (trening i inferencja),
- RAM (duże macierze, encodery kategorii),
- storage sekwencyjny (pliki Parquet/CSV).
GPU przydaje się rzadziej, chyba że pracujemy z ogromnymi tabelami lub wykorzystujemy GPU-owe biblioteki (RAPIDS, cuML).
- NLP (szczególnie duże modele językowe):
- VRAM GPU jako główne ograniczenie (pojemność modelu i batch size),
- przepustowość pamięci GPU i interconnect (NVLink/InfiniBand) przy treningu rozproszonym,
- sieć przy serwowaniu modeli jako API (przepustowość i opóźnienia).
- Wizja komputerowa (detekcja, segmentacja, klasyfikacja obrazów):
- GPU dla treningu,
- storage – wiele małych plików, często losowy dostęp, rosnące wymagania na IOPS,
- CPU dla augmentacji i przetwarzania obrazu (czasem węższe gardło niż GPU).
- Systemy rekomendacyjne:
- trening – duże macierze, embeddingi, często potrzeba wielu GPU lub mocnych CPU,
- inferencja – wymagania sieciowe (zapytania online) + szybki dostęp do cech użytkownika (bazy NoSQL, cache in-memory).
Bez rozpoznania, do której z powyższych kategorii należy główny use case, trudno racjonalnie dobrać proporcje CPU, GPU, RAM, storage i sieci. Profil obciążenia powinien być pierwszym dokumentem, zanim ktokolwiek zacznie porównywać specyfikacje kart GPU.
Ocena dojrzałości organizacji i stopnia skomplikowania środowiska
Rozważając infrastrukturę pod AI, trzeba skonfrontować ambicje z realną dojrzałością operacyjną zespołu:
- Pojedynczy serwer – wystarczający dla małego zespołu badawczo-rozwojowego, PoC i wczesnych eksperymentów. Ograniczenia:
- brak prawdziwej wysokiej dostępności,
- trudna współdzielona praca (kolejki na GPU, ręczne zarządzanie projektami),
- skalowanie wymaga wymiany serwera, a nie prostego dołożenia kolejnych.
- Mały klaster on-premise – kilka serwerów GPU/CPU, współdzielony storage:
- wymaga podstawowego poziomu automatyzacji (provisioning, monitoring),
- wprowadza potrzebę planisty zasobów (Slurm, Kubernetes),
- daje możliwość rozdzielenia środowisk: eksperymenty, staging, produkcja.
- Integracja z chmurą – elastyczna skala, ale także:
- złożone modele kosztowe (płatność za GPU, storage, sieć, transfer danych),
- konieczność rozsądnej polityki danych (co na miejscu, co w chmurze),
- potencjalne wąskie gardła na łączu internetowym przy hybrydzie.
Rozwiązaniem nie jest zawsze „idź w chmurę” ani „zbuduj własny klaster GPU”. Rozsądna ścieżka często wygląda tak: pojedynczy mocny serwer + wybrane GPU w chmurze do treningów szczytowych, a dopiero później, przy rosnącym obciążeniu, przejście na stały klaster lub większe rezerwacje zasobów w chmurze.
Dlaczego bez profilowania obciążeń planowanie infrastruktury to strzał w ciemno
Najgorszy scenariusz: organizacja kupuje drogi sprzęt „pod AI”, nie mierząc wcześniej, gdzie faktycznie pojawiają się wąskie gardła wydajności. Rezultat? GPU czeka na dane z wolnego storage, CPU spędza czas na synchronicznym czekaniu na odpowiedzi bazy, a użytkownicy obwiniają „słabą kartę graficzną” albo „framework”.
Profilowanie obciążeń powinno obejmować co najmniej:
- czas przygotowania batcha danych (CPU, RAM, I/O),
- czas samego kroku treningowego lub inferencji na GPU/CPU,
- czas operacji I/O do storage i zewnętrznych usług (bazy, message queue),
- zużycie zasobów (GPU utilization, CPU usage, IOPS, throughput sieci).
Bez takich danych wybór pomiędzy „dorzucić GPU” a „przebudować storage” jest zgadywaniem. W wielu projektach szybszy storage lub reorganizacja danych przynosi większy zysk niż wymiana kart graficznych.
Krótki przykład: mocne GPU zablokowane przez powolny storage
Typowy scenariusz z praktyki: firma inwestuje w serwer z kilkoma wysokiej klasy GPU, zakładając, że to rozwiąże problem długiego trenowania sieci konwolucyjnych na obrazach. Serwer zostaje podłączony do istniejącego środowiska – współdzielony NFS z macierzą dyskową, która od lat obsługuje również backupy.
Po kilku tygodniach okazuje się, że GPU przez większość czasu mają obciążenie 20–30%. Analiza metryk pokazuje, że:
- czas wczytywania i augmentacji batchy zdjęć zajmuje więcej niż sam krok treningowy,
- serwer NFS nie wyrabia z liczbą losowych odczytów małych plików,
- w godzinach wykonywania backupów wydajność drastycznie spada.
W efekcie potencjał GPU jest marnowany. Realnym rozwiązaniem nie jest kupno kolejnych kart, tylko:
- przeniesienie danych treningowych na lokalne NVMe,
- zgrupowanie obrazów w większe pliki (np. TFRecord),
- dostosowanie pipeline’u augmentacji tak, aby lepiej wykorzystywać CPU i cache.
Taki przypadek dobrze pokazuje, że źródłem wąskiego gardła w systemach AI bardzo często bywa storage i organizacja danych, a nie same akceleratory.
Kluczowe wąskie gardła w systemach AI – mapa ryzyka
Siedem głównych punktów krytycznych infrastruktury pod AI
Przy planowaniu infrastruktury pod AI wygodnie jest myśleć o niej jak o łańcuchu: najsłabszy ogniwo determinuje ogólną wydajność. W obciążeniach AI takie „ogniwa” można z grubsza pogrupować w siedem obszarów.
CPU i planowanie wątków
CPU jest odpowiedzialny za:
- dekodowanie i wstępne przetwarzanie danych (np. obrazów, tekstu),
- obsługę frameworków (PyTorch, TensorFlow) i ich wątków roboczych,
- koordynację pracy GPU,
- komunikację z systemem plików, bazami, kolejkami wiadomości.
Jeśli CPU jest zbyt słaby lub źle skonfigurowany (np. wątki nie są przypięte do rdzeni, ignorowana jest topologia NUMA), to GPU przez znaczną część czasu nic nie robi, czekając na dane. Objawia się to niskim wykorzystaniem GPU i wysokim obciążeniem pojedynczych rdzeni CPU.
GPU: liczba, pamięć i topologia połączeń
GPU stał się symbolem „infrastruktury AI”, ale sam w sobie też bywa źródłem wąskich gardeł:
- niewystarczająca pamięć VRAM wymusza małe batch size lub złożone techniki rozdzielania modelu,
- słaba komunikacja między GPU (brak NVLink/InfiniBand) ogranicza skalowanie treningu rozproszonego,
- niewłaściwy dobór GPU do zadań inferencyjnych prowadzi do przepłacania za FLOPS, z których model i tak nie korzysta.
Dobór liczby i typu GPU bez analizy charakterystyki modelu (rozmiar, typ operacji, docelowy batch size) i topologii połączeń kończy się często underprovisioningiem (model nie mieści się w VRAM) albo overprovisioningiem (piękne, ale niewykorzystane akceleratory).
RAM i pamięć GPU
Brak RAM lub VRAM nie zawsze objawia się od razu spektakularnym błędem. Częściej przybiera formę „cichej” degradacji wydajności:
- page faults – częste odwołania do stron, które nie mieszczą się w cache procesora,
- swap – system operacyjny zaczyna agresywnie przenosić dane z RAM na disk,
- w GPU – fallback do wolniejszej pamięci hosta (PCIe) lub fragmentacja VRAM utrudniająca alokację dużych tensorów.
W praktyce użytkownik widzi spadające tempo treningu, rosnące opóźnienia inferencji i okresowe zatrzymania, które trudno powiązać z jednym, oczywistym błędem. Monitoryng RAM/VRAM jest krytycznym elementem wczesnego wykrywania takich problemów.
Storage: IOPS, przepustowość sekwencyjna i opóźnienia
Storage jest jednym z najbardziej niedoszacowanych elementów infrastruktury pod AI. Typowe problemy:
- duża liczba małych plików (obrazy, teksty) skutkuje wysokim obciążeniem operacjami metadanych,
- współdzielony NFS lub Ceph bez odpowiedniej konfiguracji dla obciążeń AI generuje wysokie opóźnienia losowych odczytów,
- brak lokalnego cache na węzłach GPU zmusza każdy batch danych do przechodzenia przez sieć.
Wiele zespołów skupia się na teoretycznej przepustowości (MB/s), ignorując IOPS i latency. Przy obciążeniach z wieloma małymi plikami to właśnie IOPS i operacje metadata stają się dominującym ograniczeniem.
Sieć i ruch w obrębie data center
Sieć i ruch w obrębie data center
Sieć rzadko jest pierwszym podejrzanym, gdy model „idzie wolno”. Tymczasem w treningu rozproszonym i przy dużych zbiorach danych to właśnie ona często ogranicza skalowanie horyzontalne.
Przy obciążeniach AI kluczowe są trzy elementy:
- przepustowość – ile danych można przesłać w jednostce czasu (Gb/s),
- opóźnienia – ile trwa pojedynczy „round trip” pakietu,
- jitter – zmienność opóźnień, która potrafi rozsynchronizować węzły.
W praktyce problemy ujawniają się, gdy:
- trening rozproszony korzysta z wielu GPU na różnych serwerach, a synchronizacja gradientów leci po zatkanym 10 GbE,
- pipeline inferencyjny musi przy każdym zapytaniu pobierać cechy użytkownika z oddalonego klastra bazy,
- współdzielony system plików (NFS, Ceph, Lustre) wykorzystuje tę samą sieć, która obsługuje resztę ruchu produkcyjnego.
Nowym standardem w środowiskach GPU staje się 25/40/100 GbE lub InfiniBand, ale sam upgrade „z 10 na 100 GbE” nie rozwiązuje problemu, jeśli:
- przełączniki są źle skonfigurowane (brak QoS, kolejki, priorytetyzacja ruchu RDMA),
- brak jest segmentacji sieci (np. osobna sieć dla storage, osobna dla ruchu kontrolnego i użytkowego),
- rutery brzegowe i firewalle stają się nowymi punktami przeciążenia.
Komunikacja między węzłami treningowymi
Przy treningu rozproszonym głównym źródłem problemów nie jest „sieć w ogóle”, tylko konkretny wzorzec komunikacji między węzłami. Dwa najczęstsze scenariusze:
- data parallelism – każdy węzeł trenuje kopię modelu na innym fragmencie danych; co krok wymagane jest zebranie i zredukowanie gradientów (all-reduce),
- model parallelism – model jest podzielony na części między różne GPU/maszyny; co warstwę wymagane jest przesłanie aktywacji.
W pierwszym przypadku przepustowość i opóźnienia determinują, jak szybko można robić kolejne kroki treningu. W drugim – sieć staje się „przedłużeniem magistrali pamięci” i praktycznie każdy mikrobatch „dotyka” sieci. Źle dobrana topologia (GPU łączone wyłącznie przez PCIe + 10 GbE) potrafi zabić skalowanie niemal całkowicie.
Przy większych klastrach GPU nie da się już ignorować:
- RDMA (InfiniBand, RoCE) – komunikacja z pominięciem stosu TCP/IP,
- dedykowanych bibliotek do kolektywnej komunikacji (NCCL, Gloo, MPI),
- topologii sieci (fat-tree, dragonfly) i oversubscription na poziomie przełączników.
Częsty błąd: założenie, że „jak dokupimy kolejne serwery GPU, to trening przyspieszy liniowo”. Jeżeli komunikacja all-reduce zaczyna dominować w czasie kroku treningowego, dodawanie węzłów generuje wzrost narzutu sieciowego, a nie większą przepustowość.
Warstwa aplikacyjna i orkiestracja
Infrastruktura to nie tylko sprzęt; istotną rolę odgrywa sposób uruchamiania i izolacji zadań. Źródłem wąskich gardeł stają się tu:
- narzut konteneryzacji i wirtualizacji (szczególnie przy braku optymalizacji dla GPU),
- planer zadań (Slurm, Kubernetes), który źle pakuje workloady na węzły,
- serwisy pomocnicze – logowanie, monitoring, serwisowanie modeli, rejestr obrazów.
Prosty przykład: inferencja modelu LLM uruchomiona w wielu replikach na Kubernetesie. Jeżeli:
- każdy pod ma przydzielony mały fragment GPU (np. przez nvidia.com/gpu: 1/4),
- węzeł ma ograniczony RAM i słabe parametry I/O,
- horyzontalne autoskalowanie bazuje wyłącznie na CPU usage lub liczbie requestów,
to Kubernetes łatwo doprowadzi do sytuacji, w której GPU są pofragmentowane i niedowykorzystane, a jednocześnie rośnie latencja przez thrashing pamięci i przeciążenie storage.
Warstwa danych: bazy, kolejki, cache
Nawet idealnie dobrany klaster GPU nie pomoże, jeśli dane docierają do modeli przez „szyjkę od butelki” w postaci bazy lub kolejki. Główne punkty bólu:
- monolityczne bazy relacyjne, które muszą obsłużyć zapytania online do cech użytkownika,
- zbyt wolne lub źle dobrane indeksy (brak indeksów dla najczęstszych zapytań feature store),
- kolejki i systemy eventowe (Kafka, RabbitMQ) jako jedyne źródło prawdy dla strumieni danych.
W obciążeniach AI up-front trzeba zdecydować:
- które dane można trzymać w cache in-memory (Redis, Memcached, wektorowe cache na GPU/CPU),
- które muszą być trwale przechowywane i w jakiej formie (kolumnowe, time-series, obiektowe),
- jaką latencję i jaką dostępność trzeba zagwarantować (SLA, SLO, SLI).
Jeśli feature store siedzi w bazie, która ma 95. percentyl odpowiedzi na poziomie kilkudziesięciu milisekund, to inferencja „real-time” na poziomie kilku milisekund po prostu się nie wydarzy – niezależnie od tego, jak szybki jest sam model.

CPU i RAM – niedoceniany fundament pod obciążenia AI
Dlaczego CPU bywa pierwszym realnym wąskim gardłem
W większości projektów początkowy odruch to: „kupmy GPU, reszta się jakoś ułoży”. Problem w tym, że CPU:
- przygotowuje dane (dekodowanie, tokenizacja, augmentacja),
- zarządza pipeline’ami (kolejki batchy, workerzy, wątki I/O),
- obsługuje serwowanie modeli (HTTP/gRPC, serializacja JSON/protobuf),
- koordynuje trening rozproszony (proces nadrzędny, synchronizacja).
Jeżeli CPU nie nadąża, GPU wygląda na „za słabe”, mimo że w rzeczywistości czeka na dane. To typowy przypadek, w którym perfy pokazują 100% użycia jednego rdzenia i dużo wolnych zasobów na pozostałych – efekt blokujących wywołań I/O lub słabo zrównoleglonego kodu.
Dobór liczby rdzeni i klas CPU do obciążeń AI
Przy doborze CPU ma znaczenie zarówno liczba rdzeni, jak i ich wydajność jednowątkowa. Z grubsza można wyróżnić trzy kategorie obciążeń:
- ciężkie przetwarzanie danych (obraz, dźwięk, duże ETL) – dużo rdzeni, dobra przepustowość pamięci,
- lekka inferencja z dużą liczbą requestów – liczy się przede wszystkim wydajność na wątek i cache procesora,
- koordynacja dużej liczby zadań (orkiestracja, schedulery, mikroserwisy) – potrzeba wielu rdzeni, ale niekoniecznie „najszybszych na rynku”.
Przy serwerach GPU sensowne minimum to najczęściej procesory klasy serwerowej z kilkunastoma–kilkudziesięcioma rdzeniami na socket, z dużą liczbą linii PCIe i obsługą szybkiego RAM. Oszczędzanie na CPU przy drogich GPU zwykle kończy się nieproporcjonalną stratą wydajności całego systemu.
NUMA, topologia i przypinanie wątków
W nowoczesnych serwerach z wieloma socketami CPU pojawia się problem NUMA (Non-Uniform Memory Access). Koszt dostępu do pamięci lokalnej dla danego procesora jest niższy niż do pamięci „zdalnej” (przywiązanej do innego socketu). Z punktu widzenia AI oznacza to, że:
- proces trenujący model powinien być przypięty do rdzeni blisko GPU, z których korzysta,
- bufory danych wykorzystywane przez dany GPU powinny trafiać do jego „lokalnej” pamięci NUMA,
- niekontrolowane migrowanie procesów między socketami generuje losowe skoki opóźnień.
Przy mocnych serwerach z wieloma GPU brak zarządzania NUMA prawie zawsze prowadzi do straty kilku–kilkunastu procent wydajności. Nie jest to spektakularna awaria, tylko stały, trudny do wyśledzenia „podatek”.
RAM: ile naprawdę jest potrzebne i kiedy „więcej nie pomaga”
RAM bywa traktowany jak coś, co „po prostu musi być dużo”. W praktyce sensowne pytanie brzmi: ile danych musi być jednocześnie w pamięci w najgorszym przypadku? Na to wpływa m.in.:
- wielkość batcha treningowego i liczba workerów wczytujących dane,
- cache na poziomie frameworka (prefetching, pinned memory dla transferu na GPU),
- inne procesy na serwerze (bazy, cache, sidecary, monitoring).
Jeżeli RAM się „przelewa”, a system zaczyna aktywnie korzystać ze swapu, symptomy są dość charakterystyczne:
- skokowe wydłużanie kroków treningowych,
- okresowe „zawieszki” inferencji,
- rosnące opóźnienia odczytu danych z dysku (page cache zostaje wypchnięty).
Przekroczenie pewnego progu (zwykle >1.5–2x realnej potrzeby) przestaje cokolwiek zmieniać. Z punktu widzenia opłacalności lepiej wtedy zainwestować w szybszy storage lub dodatkowy węzeł niż w kolejny „nadmiarowy” bank RAM.
Zarządzanie pamięcią i uniknięcie silent degradation
Żeby uniknąć cichej degradacji wydajności, przydatnych jest kilka praktyk:
- ustalenie twardych limitów pamięci na kontenery/procesy (cgroups, limit resources w Kubernetesie) z marginesem bezpieczeństwa,
- monitorowanie page faults, cache hit ratio i wykorzystania swapu,
- ścisłe kontrolowanie liczby równoległych workerów I/O i procesów augmentacji.
Przykład z życia: zespół dorzuca kolejne procesy augmentacji zdjęć, licząc na liniowy wzrost throughputu. Do pewnego momentu przyspieszenie rzeczywiście j
