Народження 3D-акселераторів: коли GPU став окремим світом

Було корисно?

Якщо вам колись доводилося шукати причину в тікеті «GPU повільний» три години, щоб виявити, що вузьке місце — однопотоковий цикл підтвердження команд на CPU, ви вже розумієте головну ідею:
графічне обладнання не просто стало швидшим. Воно стало окремим. Інша пам’ять. Інше планування. Інші режими відмов. Інша правда.

Сучасний GPU — це не «акселератор», прикручений до ПК. Це повноцінна система зі своїми обмеженнями та власною операційною гравітацією. Цей розкол почався в 1990-х,
коли 3D-карти перестали бути милими доповненнями й почали перетворюватись на незалежні світи, які професійно малюють трикутники.

Від blitter до світу: момент, коли графіка перестала бути «просто картою»

Ранні ПК-відеоісторії були фундаментально про CPU. «Графічна карта» виконувала вивід на дисплей і трохи 2D-ускорення — bit blit-и, малювання ліній, можливо апаратний курсор.
Але пайплайном володів CPU. Якщо ви хотіли 3D, ви робили математику на CPU і штовхали пікселі в буфер кадру, ніби друкуєте сторінку.

Потім ігри стали амбіційнішими і CPU перетворився на вузьке місце планування. Не тому, що CPU «повільні» як такі, а тому, що 3D-рендеринг — це конвеєр:
трансформації, освітлення, відсікання, растеризація, текстурування, блендінг, тести z-буфера. Робіть це на 30–60 кадрів на секунду для тисяч трикутників з кількома текстурами —
і ваш CPU стає недоплачуваним стажером із купою форм.

Прорив полягав не лише в швидкості. Він полягав у спеціалізації. 3D-акселератори взяли конкретні частини того пайплайну й реалізували їх у залізі — спочатку як блоки з фіксованим функціоналом.
Ці блоки були детерміністичними, масово паралельними (на той час) і оптимізованими під пропускну здатність та локальність. Вони не були універсальними, але й не мали бути. У них була одна робота.

Коли такі блоки з’явилися, вони відтягнули центр тяжіння від CPU. Потреби GPU — пропускна здатність VRAM, складність драйверів, DMA-подача команд, перемикання контекстів — стали
першорядними інженерними обмеженнями. Тут «GPU став окремим світом» перестає бути метафорою і стає вашим досвідом при реагуванні на інциденти.

Жарт №1: GPU — це колега, який неймовірно швидкий, але говорить тільки пакетами; якщо ви ставите одне питання за раз, обом буде сумно.

Історичні факти, що мають значення в операціях

Ось конкретні історичні точки, які не є дрібницями — вони пояснюють, чому сучасні GPU поводяться так, як поводяться, особливо під навантаженням і в продакшені.

  1. 3D-карти середини 1990-х відвантажували растеризацію і мапінг текстур, тоді як CPU часто все ще обробляв геометричні трансформації. Цей розподіл створив патерн «вузьке місце при подачі команд», який досі існує.
  2. 3dfx Voodoo (1996) популяризував спеціалізоване 3D-залізо і ввів багатьох у концепт окремого 3D-пайплайну — часто як другої карти, а не основного дисплея.
  3. Direct3D vs OpenGL — це було не лише про API-релігію. Це вплинуло на моделі драйверів, припущення рушіїв і те, як швидко фічі ставали загальними — тобто, на те, що вендори оптимізували.
  4. AGP (кінець 1990-х) намагався надати графіці дружній шлях до головної пам’яті через GART (Graphics Address Remapping Table). Це був ранній урок «спільна пам’ять — не безкоштовна».
  5. Програмовані шейдери (початок 2000-х) перемістили GPU від фіксованого функціоналу до програмованого пайплайну. Це початок GPU як загального масово-паралельного обчислювального двигуна.
  6. Hardware T&L (transform and lighting) перемістив основну геометрію на GPU, зменшивши навантаження CPU, але збільшивши складність драйверів і команд.
  7. Уніфіковані шейдерні архітектури пізніше замінили окремі вершинові/піксельні конвеєри, покращивши утилізацію — але зробивши продуктивність менш передбачуваною без профілювання.
  8. Мульті-GPU (ерa SLI/CrossFire) дала неприємний операційний урок: «більше карт» може означати «більше синхронізації», плюс більше дивностей драйвуера, а не лінійне прискорення.

Старий 3D-пайплайн: чому фіксований функціонал змінив усе

Щоб зрозуміти народження 3D-акселераторів, потрібно розуміти, що саме вони пришвидшували: пайплайн, що природно розбивається на повторювані математичні кроки.
Ранній архітектурний бet полягав у тому, що ці кроки були достатньо стабільними, щоб їх зафіксувати в апаратурі.

Блоки з фіксованим функціоналом: передбачувані, швидкі й дивно крихкі

Фіксований функціонал означає, що в силіконі є виділені блоки: налаштування трикутника, растеризація, семплювання текстур, блендінг, тестування глибини.
Ви даєте параметри — він виконує задачу. Це швидко, бо немає накладних расходов на декодування інструкцій, а шляхи даних налаштовані під конкретну операцію.
Це також крихко: коли індустрія хоче нову модель освітлення чи інший комбайнер текстур, ви не можете «залатати» апаратне забезпечення.

Операційно епоха фіксованого функціоналу породила специфічний набір проблем: одна обхідна логіка драйвера могла вирішити, чи працюватиме ваш рушій на 60 FPS або впаде при запуску.
З фіксованим залізом вендори наштовхували сумісні шари в драйвери, і драйвер став м’яким емулятором відсутніх можливостей.
Така спадщина ніколи повністю не зникла; вона просто перемістилась шарами.

Подача команд: початок асинхронності GPU

CPU не «викликає GPU» як функцію. Він будує буфери команд і подає їх. GPU споживає їх, коли може.
Ця асинхронна модель зародилася рано, бо це був єдиний спосіб тримати й CPU, й GPU зайнятими.

Саме тому налагодження продуктивності складне. Ваш CPU може чекати на fence; GPU може чекати на дані; час кадру може домінуватися завантаженням текстур, про яке ви забули.
Якщо ви ставитесь до GPU як до синхронного копроцесора, ви неправильно діагностуєте вузьке місце і «полагодите» не ту компоненту.

Ключова концепція: тримати «гарні» дані поруч із місцем їхнього використання

Текстури та буфери кадру поглинають багато пропускної здатності. Ранні акселератори зробили різку, але правильну ставку: тримати їх у локальній VRAM на карті.
Це зменшує затримки і уникати насичення системної шини. Це також створює новий ресурс для управління: тиск VRAM, резидентність, пейджинг, фрагментація.

VRAM, пропускна здатність і чому GPU потребував власного королівства пам’яті

GPU став окремим світом, бо він потребував власної економіки. Ця економіка вимірюється в байтах за секунду, а не в GHz.
CPU-інженери люблять частоти; GPU-інженери рахують байти в секунду, а потім все одно скаржаться.

Чому існує VRAM: передбачувана пропускна здатність краща за хитромудрість

GPU потрібно читати текстури, записувати колорові буфери, читати буфери глибини і робити це паралельно. Цей шаблон доступу не схожий на CPU.
CPU процвітають на кешах і предиктах переходів; GPU процвітають на стрімах і приховуванні затримок через паралелізм. VRAM проєктований для широких шин і високої пропускної здатності.

Ранні підходи «використовувати системну RAM для текстур» (включно з AGP-текстуруванням) виглядали привабливо на папері. На практиці шина ставала горлом,
а варіація затримок викликала підвисання. Це повторюваний урок: спільні ресурси — це місце, куди йде продуктивність під конкурентним навантаженням.

Резидентність і пейджинг: мовчазний рушій підвисань

Коли у вас є окрема VRAM, потрібно мати політику щодо того, що там зберігається. Коли VRAM заповнена, щось мусить бути вигнано.
Якщо звільнення відбувається під час кадру — отримуєте піки. Якщо під час малювання — отримуєте стаги.
Сучасні API дають більш явний контроль (і більше відповідальності), але режим відмови старий: забагато текстур, забагато render target-ів, замало пам’яті.

Математика пропускної здатності, яка змінює рішення

Інженери люблять сперечатися про «compute vs memory bound». У графіці часто перемагає пропускна здатність. Якщо ваш шейдер простий, але текстури великі і render target високої роздільності,
ваш GPU може нудьгувати в очікуванні даних.

В операційних термінах: якщо ви бачите низьку утилізацію GPU при високому часі кадру, можливо, ви обмежені пам’яттю, PCIe або подачею команд. Правильний інструмент — вимір, а не інтуїція.

AGP до PCIe: війни шин і уроки

Системний інтерконект визначає, наскільки можлива «світова відокремленість». Коли GPU був на PCI, він конкурував з усім іншим. AGP дав йому швидший, більш прямий шлях,
плюс механізми на кшталт GART для мапування системної пам’яті. Потім з’явився PCIe і перетворив GPU на периферію з високою пропускною здатністю та масштабованими лініями.

AGP: спеціальне ставлення, спеціальні режими відмов

AGP був «специфічним для графіки», а отже мав «специфічні графічні баги». На практиці ви могли отримати нестабільність, яка проявлялась тільки коли гра агресивно стріміла текстури.
Такий тип відмови — улюблене місце менеджерів інцидентів, бо виглядає як випадкова корупція, поки не помітиш кореляцію зі спайками пропускної здатності.

PCIe: масштабовано, але не чарівно

PCIe дає лінії, швидкості лінку і звітність помилок. Він також дає нові способи помилитися: переговори на нижчій ширині лінку, події перетренування, скориговані помилки, що тихо погіршують продуктивність,
і скидання пристрою під навантаженням.

Якщо ви не моніторите стан PCIe, ви поводитесь з GPU як з чорним ящиком. Саме так ви починаєте «оптимізувати шейдери», щоб виправити глючний райзер.

Драйвери: де хороші ідеї зустрічаються з фізикою і дедлайнами

Драйвер — це договір між двома світами. Він перекладає виклики API у буфери команд, керує пам’яттю, планує роботу, обробляє стани енергозбереження
і намагається залишатися стабільним, поки додатки роблять креативні речі з невизначеною поведінкою.

Саме тому «в мене працює на моєму машині» особливо марно в світі GPU. Версія драйвера, версія ядра, прошивка, мікрокод і навіть BIOS материнської плати можуть змінити поведінку.
Ви можете бути технічно праві і все одно впасти.

Цитата, яку варто тримати на стикері

«Сподівання — не стратегія.» — Генерал Гордон Р. Салліван

Ставтесь до надійності GPU так само, як до надійності сховища: вважайте шлях щасливого сценарію демонстрацією, а не контрактом. Інструментуйте, перевіряйте і явно фіксуйте версії.

API формували апаратне забезпечення

Direct3D і OpenGL не лише відкривали можливості; вони формували пріоритети команд по виготовленню силікону. Фіксовані пайплайни добре вкладались у ранні API.
Пізніше моделі шейдерів змусили до програмованості, і апаратне забезпечення еволюціонувало, щоб запускати малі програми в масштабі.

Операційна порада: якщо ваш стек використовує високорівневу абстракцію (рушій, рантайм, фреймворк), абстракція може протікати старими припущеннями про те, як працюють GPU.
Коли щось ламається, спочатку читайте логи драйвера та повідомлення ядра, а не маркетингову презентацію.

Три корпоративні міні-історії з реального світу

Міні-історія №1: інцидент через неправильне припущення

Медіакомпанія експлуатувала флот серверів для транскодування з підтримкою GPU. Пайплайн був переважно стабільний: ingest, decode, фільтри, encode, публікація.
Одного ранку латентність завдань подвоїлась, черга почала зростати. Дашборди CPU і GPU здавалися «в порядку», що зазвичай означає — ви витратите час даремно.

Позиція on-call була такою: «Якщо утилізація GPU низька, GPU не є вузьким місцем». Тож вони масштабували CPU-ноди, підвищували кількість воркерів і налаштовували пул потоків.
Черга продовжувала зростати. Ноди з GPU не показували очевидних червоних прапорців, крім випадкових падінь пропускної здатності PCIe — ігнорували це, бо не мали базової лінії.

Насправді причиною було оновлення прошивки на підмножині серверів, яке після гарячих перезавантажень виразно зменшувало ширину PCIe-лінку.
GPU «не були зайняті», бо їх морили голодом: DMA-перекази та завантаження фреймів відео були повільнішими, тож пайплайн проводив більше часу в очікуванні копій.
Виглядало, ніби GPU просто холостує, але система була обмежена через I/O.

Виправлення було нудним: перерахунок інвентарю та забезпечення параметрів PCIe, додати алерти на зміну ширини/швидкості лінку і фіксувати оновлення прошивки в вікнах техобслуговування з валідацією.
Урок був гострим: низька утилізація може означати голод, а не запас. Розглядайте «простій» як симптом, а не остаточний висновок.

Міні-історія №2: оптимізація, яка призвела до відкату

Команда фінтеху мала дашборд реального часу з візуалізацією складних 3D-сцен — бо хтось вирішив, що 2D-графіки не «іммерсивні».
Вони оптимізували шляхом агресивного батчінгу викликів малювання й рідкісної загрузки більших текстурних атласів. FPS у лабораторії покращився.

У продакшені користувачі почали скаржитися на періодичні підвисання: додаток йшов плавно, потім «завмирав» на півсекунди. Графіки CPU показували спайки.
Профілювання GPU показало довгі стаги у непередбачувані моменти. Команда звинувачувала збирач сміття, потім мережу, потім «Windows» — що не було кореневою причиною.

Реальна проблема була в тиску VRAM і зміні резидентності. Більші атласи зменшили частоту завантажень, але коли завантаження відбувалося, воно було масивним,
і система іноді мусила вигнати render target-и, щоб упхнути нові дані. Драйвер робив неявний пейджинг і синхронізацію у найгірший можливий момент.
Оптимізація зросила пікове споживання пам’яті і зробила події стагів рідшими, але катастрофічно більшими.

Вони виправили це, тримаючи атласи нижче порогу резидентності, розбиваючи завантаження на менші шматки і явно бюджетуючи VRAM.
Середній FPS трохи впав; хвостова латентність покращилась драматично. Користувачі надають перевагу стабільним 45 FPS над «іноді 90, іноді заморожено».

Міні-історія №3: нудна, але правильна практика, яка врятувала день

SaaS-компанія пропонувала віртуальні робочі станції з підтримкою GPU. Нічого гламурного: CAD, відеомонтаж, кілька ноутбуків для ML.
Вони мали суворий процес змін для драйверів і прошивок GPU: поступове розгортання, канарки та автоматичний відкат при підвищенні рівня помилок.
Це не подобалося розробникам, бо уповільнювало «отримання останніх приростів продуктивності».

Якось кварталі нова версія драйвера покращила пропускну здатність у кількох бенчмарках і виправила відому графічну артефактність.
Вона також внесла рідкісне скидання GPU під певною комбінацією мультимоніторних розкладок і високих частот оновлення.
Баг не проявлявся в синтетичних тестах. Він проявився в реальних робочих потоках клієнтів — бо реальність завжди проявляє.

Канаркова група його зловила. Логи ядра показали помилки типу Xid і скидання, корельовані зі змінами конфігурації дисплея.
Розгортання зупинили на невеликому відсотку нод, клієнтів автоматично перемістили, і інцидент обмежився кількома сесіями.

Практика, що їх врятувала, не була хитрою. Це було контрольоване розгортання плюс спостережуваність.
Нудна правильність — ось як не дати GPU перетворити чергу підтримки на перформанс-арт.

Практичні завдання: команди, виводи, значення та рішення

Ви не зможете налагодити GPU, дивлячись лише на одне число утилізації. Потрібні докази: швидкість лінку, тиск пам’яті, помилки драйвера, подача команд CPU і поведінка по теплу/енергії.
Нижче — практичні, виконувані завдання на поширених системах Linux. Кожне включає: команду, приклад виводу, що це означає і яке рішення приймати.

1) Визначити GPU і драйвер, що використовується

cr0x@server:~$ lspci -nnk | grep -A3 -E "VGA|3D controller"
01:00.0 VGA compatible controller [0300]: NVIDIA Corporation GA102 [GeForce RTX 3090] [10de:2204] (rev a1)
	Subsystem: Micro-Star International Co., Ltd. [MSI] Device [1462:3897]
	Kernel driver in use: nvidia
	Kernel modules: nvidiafb, nouveau, nvidia_drm, nvidia

Значення: Підтверджує, який пристрій і який драйвер ядра активні. Якщо ви очікували датацентричний GPU, а бачите споживчу модель — ви вже дебажите закупівлю, а не продуктивність.

Рішення: Якщо використовується неправильний драйвер (наприклад, nouveau), виправте вибір драйвера перед тим, як чіпати код додатку.

2) Перевірити швидкість і ширину PCIe-лінку (критично для «GPU простий, але повільно»)

cr0x@server:~$ sudo lspci -s 01:00.0 -vv | grep -E "LnkCap:|LnkSta:"
LnkCap:	Port #0, Speed 16GT/s, Width x16, ASPM L1, Exit Latency L1 <64us
LnkSta:	Speed 8GT/s (downgraded), Width x8 (downgraded)

Значення: Карта підтримує PCIe Gen4 x16, але працює на Gen3 x8. Це може суттєво урізати пропускну здатність для передач.

Рішення: Розбирайтеся з налаштуваннями BIOS, райзерами, розташуванням слота або цілісністю сигналу. Не «оптимізуйте ядра», щоб компенсувати зниження лінку.

3) Шукати скориговані помилки PCIe і перетренування лінку

cr0x@server:~$ sudo dmesg -T | grep -iE "pcie|aer|corrected|link"
[Mon Jan 13 09:22:10 2026] pcieport 0000:00:01.0: AER: Corrected error received: 0000:01:00.0
[Mon Jan 13 09:22:10 2026] nvidia 0000:01:00.0: PCIe Bus Error: severity=Corrected, type=Physical Layer

Значення: Скориговані помилки можуть бути запахом проблем з продуктивністю і стабільністю. Проблеми фізичного рівня часто вказують на проблеми з кабелями/райзером/слотом.

Рішення: Якщо помилки корелюють з навантаженням, заплануйте апаратний огляд і розгляньте переміщення GPU в інший слот/нод.

4) Спостерігати утилізацію GPU, пам’ять, енергоспоживання й частоти (NVIDIA)

cr0x@server:~$ nvidia-smi
Tue Jan 13 09:25:01 2026
+---------------------------------------------------------------------------------------+
| NVIDIA-SMI 550.54.14              Driver Version: 550.54.14      CUDA Version: 12.4   |
|-----------------------------------------+----------------------+----------------------+
| GPU  Name                  Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf            Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|                                         |                      |               MIG M. |
|=========================================+======================+======================|
|  0  NVIDIA RTX 3090                 Off | 00000000:01:00.0 Off |                  N/A |
| 30%   72C    P2              310W / 350W|  22500MiB / 24576MiB |     18%      Default |
+-----------------------------------------+----------------------+----------------------+

Значення: Низький GPU-Util при дуже високому використанні VRAM натякає на тиск пам’яті, синхронізацію або I/O-голодування — не обов’язково запас потужності.

Рішення: Якщо VRAM майже заповнений, профілюйте алокації і зменшуйте пікову резидентність (менші батчі, стрімінг, зниження роздільності render target-ів).

5) Дивитись статистику GPU в реальному часі, щоб ловити спайки й тротлінг

cr0x@server:~$ nvidia-smi dmon -s pucvmt
# gpu   pwr gtemp mtemp   sm   mem   enc   dec  mclk  pclk  fb   bar1
# Idx     W     C     C    %     %     %     %   MHz   MHz  MB    MB
    0   315    74     -   22    55     0     0  9751  1695 22510  256

Значення: Потужність і частоти показують, чи ви тротлите. Якщо pclk падає, а температура зростає — ви термічно або енергетично обмежені.

Рішення: Покращіть охолодження, відрегулюйте енергокапи або зменшіть тривале навантаження. Не гоньтесь за «мікрооптимізаціями», поки працюєте на знижених частотах.

6) Шукати скидання GPU або збої драйвера в логах

cr0x@server:~$ sudo journalctl -k -b | grep -iE "nvrm|xid|amdgpu|gpu fault|reset"
Jan 13 09:18:44 server kernel: NVRM: Xid (PCI:0000:01:00): 79, GPU has fallen off the bus.
Jan 13 09:18:44 server kernel: nvidia: probe of 0000:01:00.0 failed with error -1

Значення: «Fallen off the bus» свідчить про серйозну проблему PCIe/апаратури/прошивки, а не про баг додатку.

Рішення: Ставте це як апаратну нестабільність: пересіть, перемістіть у інший слот, перевірте живлення, оновіть прошивку обережно і карантинуйте нод.

7) Перевірити IOMMU-групи і відображення віртуалізації (поширено на GPU-серверах)

cr0x@server:~$ for d in /sys/kernel/iommu_groups/*/devices/*; do echo "$d"; done | grep -E "01:00.0|01:00.1"
/sys/kernel/iommu_groups/18/devices/0000:01:00.0
/sys/kernel/iommu_groups/18/devices/0000:01:00.1

Значення: GPU і його аудіофункція в одній IOMMU-групі. Це типовo; passthrough вимагає ізоляції груп для безпеки і стабільності.

Рішення: Якщо несподівані пристрої ділять групу, налаштуйте BIOS ACS або розташування плат до спроби чистого passthrough.

8) Виміряти вузькі місця на боці CPU при подачі команд

cr0x@server:~$ pidof my-renderer
24817
cr0x@server:~$ sudo perf top -p 24817
Samples:  61K of event 'cpu-clock', 4000 Hz, Event count (approx.): 15250000000
Overhead  Shared Object      Symbol
  18.22%  libc.so.6          pthread_mutex_lock
  12.91%  my-renderer        SubmitCommandBuffer
   9.77%  libvulkan.so.1     vkQueueSubmit

Значення: Велика частка часу у локах і функціях подачі команд вказує, що обмежує CPU, а не продуктивність шейдерів.

Рішення: Зменшіть накладні витрати на подачу: батчінг станів, багатопотокова підготовка команд, уникайте блокувань per-draw.

9) Підтвердити впливи huge page / тиску пам’яті на GPU-ворклоади

cr0x@server:~$ vmstat 1 5
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 6  0      0  81264  10240 512000    0    0     0    12 2310 5400 72 18  8  2  0
 8  0      0  62400   9984 498112    0    0     0    40 2600 6800 78 19  2  1  0

Значення: Велика кількість runnable-потоків (r) і низький idle (id) вказують на конкуренцію CPU. Це не обов’язково погано, але означає, що «GPU повільний» може бути через голод CPU.

Рішення: Прив’язуйте потоки, зменшуйте пересичення CPU або переносіть GPU-завдання на ноди з запасом CPU.

10) Перевірити обмеження cgroup CPU (контейнеризовані GPU-додатки)

cr0x@server:~$ cat /sys/fs/cgroup/cpu.max
200000 100000

Значення: Цей контейнер обмежений еквівалентом 2 CPU (200ms на 100ms період). Це може обмежувати подачу команд і підготовку даних.

Рішення: Підвищте CPU-ліміти для GPU-ворклоадів; голодний CPU робить GPU «недоутилізованим» і вводить у замішання всіх.

11) Перевірити файлову систему і I/O wait при стрімінгу ресурсів

cr0x@server:~$ iostat -xz 1 3
avg-cpu:  %user   %nice %system %iowait  %steal   %idle
          55.12    0.00    8.22   20.45    0.00   16.21

Device            r/s     rkB/s   rrqm/s  %rrqm r_await rareq-sz     w/s     wkB/s w_await aqu-sz  %util
nvme0n1         950.0  120000.0     0.0   0.00    7.20   126.32   110.0   24000.0   3.10   7.20   92.0

Значення: Високий iowait і висока зайнятість NVMe означають, що стрімінг активів може блокувати рендеринг/обчислювальні пайплайни в очікуванні даних.

Рішення: Попередньо завантажуйте гарячі активи, збільшуйте кеш, переходьте на швидше сховище або реструктуруйте стрімінг, щоб не блокувати рендер-потік.

12) Відслідковувати процеси, що споживають пам’ять на GPU (NVIDIA)

cr0x@server:~$ nvidia-smi pmon -c 1
# gpu        pid  type    sm   mem   enc   dec   command
# Idx           #   C/G     %     %     %     %   name
    0       24817     C    20    88     0     0   my-renderer
    0       25102     C     2     6     0     0   python

Значення: Другий процес використовує VRAM. Це може викликати пейджинг і створювати латентні спайки для основного ворклоаду.

Рішення: Забезпечте ізоляцію (виділені GPU на ворклоад, політики планування або MIG, де доступно) і перестаньте вважати VRAM «спільною за замовчуванням».

13) Підтвердити наявність вузлів пристроїв і права доступу (класична контейнерна помилка)

cr0x@server:~$ ls -l /dev/nvidia*
crw-rw-rw- 1 root root 195,   0 Jan 13 09:10 /dev/nvidia0
crw-rw-rw- 1 root root 195, 255 Jan 13 09:10 /dev/nvidiactl
crw-rw-rw- 1 root root 195, 254 Jan 13 09:10 /dev/nvidia-modeset

Значення: Вузли пристроїв існують. Якщо контейнер їх не бачить — це проблема конфігурації runtime, а не «CUDA зламалась».

Рішення: Виправте passthrough GPU для контейнера, правила cgroup для пристроїв або права udev.

14) Підтвердити, що версії модулів ядра збігаються з інстальованим стеком

cr0x@server:~$ modinfo nvidia | head
filename:       /lib/modules/6.5.0-18-generic/updates/dkms/nvidia.ko
version:        550.54.14
license:        NVIDIA
description:    NVIDIA kernel module

Значення: Версія модуля ядра має збігатися з userspace-інструментами. Невідповідності можуть викликати тонкі збої або відсутні можливості.

Рішення: Якщо є невідповідність, перевстановіть драйвер чисто і перезавантажтесь. Не латайте розбіжність у драйверному стеку.

15) Виявити сигнали термального тротлінгу в системних сенсорах

cr0x@server:~$ sensors | sed -n '1,30p'
k10temp-pci-00c3
Adapter: PCI adapter
Tctl:         +88.8°C

nvme-pci-0100
Adapter: PCI adapter
Composite:    +73.9°C

Значення: Високі температури CPU і NVMe можуть непрямо впливати на GPU-ворклоади (тротлінг CPU, тротлінг I/O), навіть якщо сам GPU виглядає в порядку.

Рішення: Вирішіть питання обдування шасі та керування вентиляторами; сервер з GPU — це пристрій для керування теплом, який прикидається комп’ютером.

Жарт №2: Якщо ви не моніторите ширину PCIe-лінку, ваша оптимізація продуктивності — це по суті інтерпретативний танець з графіками.

План швидкої діагностики: що перевіряти в першу/другу/третю чергу

Коли хтось каже «GPU — вузьке місце», ваша задача — не стати людською кнопкою повторної спроби. Ось швидкий план, що допоможе швидко знайти реальні обмеження.

Першим: чи здорова платформа?

  • Ширина/швидкість PCIe-лінку: перевірте на зниження. Якщо знижено — зупиніться і виправте апарат/прошивку/слотування.
  • Логи ядра: шукайте скидання GPU, помилки AER, «fallen off the bus», зависання.
  • Живлення і термали: перевірте, що частоти стабільні під навантаженням і живлення не обмежене несподівано.

Другим: чи «голодує» GPU від навантаження?

  • Подача з CPU: профілюйте vkQueueSubmit / glDraw* накладні витрати і локи.
  • Обмеження контейнерів: перевірте cgroup CPU і memory cap-и, що душать підготовку даних.
  • Сховище та стрімінг активів: iowait і %util диска; завислий лоадер може виглядати як «переривчастий GPU».

Третім: чи обмежений GPU пам’яттю або плануванням?

  • Тиск VRAM: майже повна VRAM + стуттер = ризик резидентного чату.
  • Контенція мульти-орендарів: інші процеси займають VRAM або SM-час.
  • Тротлінг живлення/температури: стійко низькі частоти попри попит.

Четвертим: тільки потім оптимізуйте шейдери/ядра

  • Вимірюйте, чи ви обмежені обчисленнями або пам’яттю за допомогою профайлерів у вашому стеку.
  • Зменшуйте overdraw, оптимізуйте шаблони доступу до пам’яті та налаштовуйте розміри батчів — після перевірки, що система вам не брешить.

Поширені помилки: симптоми → корінна причина → виправлення

Ось режими відмов, які повторюються, коли GPU «стає своїм світом» і команди забувають, що вони оперують двома системами, а не однією.

1) Симптом: низька утилізація GPU, але високий час кадру

Корінна причина: вузьке місце при подачі команд на CPU, вузькість при PCIe-передачах або синхронізаційні стаги.

Виправлення: Профілюйте CPU за допомогою perf, перевірте стан PCIe-лінку та огляньте fence/barrier-и. Батчіть роботи; зменшуйте накладні витрати per-draw; уникайте великих щокадрових передач.

2) Симптом: періодичні підвисання кожні кілька секунд

Корінна причина: вигнання/пейджинг VRAM, спайки стрімінгу текстур або фонова програма, що краде VRAM.

Виправлення: Зменшіть пікове використання VRAM, префетчіть, розбийте завантаження на частини, забезпечте ізоляцію GPU і явно бюджетуйте пам’ять, де API дозволяють.

3) Симптом: випадкові скидання GPU під навантаженням

Корінна причина: проблеми з подачею живлення, цілісністю сигналу PCIe, баги драйвера або перегрів.

Виправлення: Перевірте dmesg/journal на підписи скидань, тимчасово зменшіть power cap для тесту стабільності, переставте або замініть залізо і контролюйте розгортання драйверів.

4) Симптом: падіння продуктивності після «оновлення драйверів для швидкості»

Корінна причина: нова поведінка планувальника, інший компілятор шейдерів, регресія в управлінні пам’яттю.

Виправлення: A/B тестування з канарками, фіксація відомо-робочих версій і підтримка відтворюваних середовищ збірки/рантайму.

5) Симптом: працює на bare metal, ламається в контейнерах

Корінна причина: відсутні вузли пристроїв, неправильні runtime-hook-и, обмеження cgroup для пристроїв або невідповідність userspace/kernel драйверів.

Виправлення: Підтвердьте наявність /dev/nvidia* і права доступу, упевніться, що версії драйверів збігаються, і перегляньте конфігурацію runtime для GPU у контейнері.

6) Симптом: «Додали другу GPU і нічого не покращилось»

Корінна причина: робота не паралелізується, домінує синхронізація, накладні витрати на дуплікацію VRAM або подача команд CPU стає обмеженням.

Виправлення: Профілюйте масштабування. Якщо ви не можете розділити роботу — не купуйте складність. Віддавайте перевагу одному швидшому GPU або правильної паралельності завдань.

7) Симптом: раптовий обрив продуктивності після підвищення роздільності

Корінна причина: вибух по заповненню пікселями/overdraw, насичення пропускної здатності render target-ів або виснаження VRAM.

Виправлення: Зменшуйте overdraw, використовуйте більш ефективні формати, налаштовуйте AA/тіні і перевіряйте кількість та розмір render target-ів.

Чеклісти / покроковий план

Чекліст A: Підняття GPU-ноду як слід

  1. Перерахунок апаратного забезпечення: модель GPU, потужність PSU, план повітряного потоку шасі.
  2. Встановіть і зафіксуйте версію драйвера; зафіксуйте версію ядра і версії прошивок.
  3. Перевірте ширину/швидкість PCIe-лінку при завантаженні і після warm reboot.
  4. Запустіть стійкий тест навантаження і спостерігайте за потужністю, частотами, температуру та логами помилок.
  5. Налаштуйте алерти на скидання GPU, помилки AER і зниження лінку.
  6. Встановіть базові лінії: типовa утилізація, використання VRAM і пропускна здатність на ворклоад.

Чекліст B: Коли продуктивність «таємничо» гірша

  1. Підтвердіть, що нічого не змінилося: драйвер, ядро, прошивка, налаштування BIOS, runtime контейнера.
  2. Перевірте здоров’я платформи: стан PCIe-лінку і скориговані помилки.
  3. Перевірте стан GPU: термали, тротлінг, скидання.
  4. Перевірте обмеження CPU: perf, ліміти cgroup, пересичення.
  5. Перевірте тиск VRAM і інших орендарів GPU.
  6. Перевірте сховище/I/O, якщо залучений стрімінг.
  7. Лише потім: налаштуйте ядра/шейдери і стратегію батчінгу.

Чекліст C: Контроль змін у продакшн-стеку GPU

  1. Розгортайте оновлення драйверів по канарках з представницькими ворклоадами.
  2. Збирайте логи ядра і телеметрію GPU під час вікна канарки.
  3. Визначте тригери відкату: скидання, рівні помилок, регресії хвостової латентності.
  4. Розгортайте партіями; тримайте відому-робочу версію доступною.
  5. Документуйте очікування стану лінку (PCIe Gen і ширина) для кожної платформи.

Поширені питання (FAQ)

1) Що саме було «3D-акселератором» до терміну GPU?

Виділена плата, яка відвантажувала частини 3D-рендеринг-пайплайну — часто растеризацію, мапінг текстур і блендінг — тоді як CPU все ще робив значну геометричну роботу.

2) Чому раннє 3D-залізо віддавало перевагу фіксованому функціоналу?

Бо це давало передбачувану продуктивність на транзистор. Індустрія знала кроки пайплайну і могла запроектувати їх у чип для пропускної здатності та ефективності.
Програмованість з’явилась, коли фіксовані блоки перестали встигати за еволюцією технік рендерингу.

3) Чому VRAM має таке значення порівняно з системною RAM?

VRAM сконструйований для дуже високої пропускної здатності і широких інтерфейсів, що відповідають шаблонам доступу GPU. Системна RAM може бути швидкою, але перетин шини додає затримку і конкуренцію,
а запити GPU карають непередбачуваність.

4) Якщо утилізація GPU низька, чи можу я припустити, що GPU не є вузьким місцем?

Ні. Низька утилізація може означати голодування (подача з CPU, передачі PCIe, I/O), очікування синхронізації або проблему резидентності пам’яті.
Ставтеся до утилізації як до підказки, а не висновку.

5) Який найпоширеніший «прихований» вузький елемент GPU у продакшені?

Зниження або деградація продуктивності лінку PCIe через переговори або помилки. Це поширено, бо команди не фіксують стан лінку і не ставлять на нього алерти.

6) Чому драйвери GPU так часто фігурують у інцидентах?

Бо драйвер відповідає за величезний обсяг політик: управління пам’яттю, планування, компіляцію та сумісність.
Це також шар, який має адаптувати старі припущення до нового заліза, іноді в умовах сильного тиску по часу.

7) Який розумний підхід до мульти-тенантності на GPU?

Віддавайте перевагу жорсткій ізоляції: виділені GPU для кожного ворклоаду або апаратне партиціювання, якщо підтримується. Якщо ділити — моніторте споживання процесів,
встановлюйте квоти/бюджети і очікуйте контенції та хвостової латентності, якщо ворклоад не розроблений для шарінгу.

8) Як швидко відрізнити compute-bound від bandwidth-bound?

Почніть з телеметрії: споживана потужність і частоти (тиск обчислень) плюс використання VRAM і спостережувана пропускна здатність. Потім підтвердіть профайлингом:
якщо підвищення частот не допомагає, але зменшення трафіку пам’яті — допомагає, ви, ймовірно, bandwidth-bound.

9) Що змінилося з появою програмованих шейдерів?

GPU перестав бути набором фіксованих блоків і став масово-паралельним програмованим механізмом. Це відкрила нові можливості і перемістила складність:
компілятори, планування та переносимість продуктивності стали операційними аспектами.

10) Чому «GPU став окремим світом» важливо для SRE?

Бо тепер ви оперуєте двома різними системами з різними моделями ресурсів: CPU/RAM/сховище проти GPU/VRAM/PCIe/драйвер/прошивка.
Інциденти часто виникають на межі — там, де припущення помилкові і видимість погана.

Наступні кроки, які ви справді можете виконати

Якщо ви запускаєте GPU-ворклоади в продакшені — або збираєтеся — ставтесь до GPU як до підсистеми сховища або мережевого фрагмента: вимірювана, схильна до відмов і з власними уподобаннями.
Народження 3D-акселераторів навчило індустрію, що «графіка» — це пайплайн з власною фізикою. Сучасні GPU лише зробили цей пайплайн програмованим і простішим у неправильному використанні.

  1. Зробіть базовий моніторинг стану PCIe-лінку (швидкість і ширина) і ставте алерти на зміни.
  2. Збирайте логи ядра централізовано і індексуйте підписи скидань GPU і помилок AER.
  3. Бюджетуйте VRAM на ворклоад; вважайте майже повну VRAM ризиком надійності, а не знаком майстерності.
  4. Фіксуйте і розгортайте драйвери через канарки; вимірюйте хвостову латентність, а не лише середню пропускну здатність.
  5. Профілюйте подачу команд CPU перед тим, як чіпати GPU-ядра — бо морити GPU голодом — найпростіший спосіб виглядати «ефективним» на дашборді.

А потім зробіть те, чого більшість команд уникає: запишіть ваші припущення про світ GPU (пам’ять, планування, вартість передач) і протестуйте їх. У продакшені припущення — невпорядковані інциденти.

← Попередня
Вживані GPU після майнінгу: як перевірити перед оплатою
Наступна →
Debian 13: nftables + Docker — припиніть несподіванки від автоматичних правил (і виправте це) (випадок №39)

Залишити коментар