Десь між “чому моя модель виконується 45 хвилин на один прогін?” і “чому мій десктоп просто перезавантажився під час тренування?” ви дізнаєтеся правду: ШІ потребує не просто обчислень. Він потребує правильного типу обчислень, підживлених правильною системою зберігання, охолодженням і реалістичними очікуваннями.
Сучасні навантаження ШІ не масштабуються лінійно з «більше ядер». Вони залежать від пропускної здатності пам’яті, продуктивності матричної арифметики та непомітного інфраструктурного “підключення” навколо них. Саме тому ваша GPU — спочатку створена для шейдингу пікселів — тепер поводиться як маленький суперкомп’ютер, який можна купити в магазині й поставити поруч із мискою вашого кота.
Чому GPU перемогли в ШІ
ШІ любить три речі: велику кількість паралельної арифметики, передбачувані шаблони доступу до пам’яті (або такі, які можна зробити передбачуваними), і величезну пропускну здатність. CPU відмінні для роботи ОС і тисячі дрібних рішень за секунду. GPU відмінні для виконання того самого оператора на великій кількості даних одночасно.
Нейронні мережі — особливо трансформери — фактично є висококласними конвеєрами лінійної алгебри з епізодичними нелінійностями як прикраса. Кожного разу, коли ви бачите термін на кшталт “GEMM” (загальне множення матриць), це місце, де GPU почувається щасливо. GPU не “думує”. Він виконує математику. Швидко. Паралельно. Знову й знову.
Є ще економіка. GPU масово виробляються для ігор, професійної графіки та робочих станцій. Це означає, що ланцюжки постачання, масштаб виробництва та конкуренція підняли продуктивність і знизили ціну (порівняно зі спеціалізованими прискорювачами). Ви можете купити величезну кількість обчислень у коробці, яка все ще поміщається під столом. “Домашній суперкомп’ютер” — це не маркетинг; це трохи незграбний, але точний опис.
Практична порада: якщо ви намагаєтеся запускати ШІ локально і витрачаєте гроші, інвестуйте спочатку в VRAM та стабільне живлення. Сировинна кількість ядер — пастка, якщо ви не можете вмістити модель або підживити її даними.
Що насправді таке GPU (і чому ШІ його любить)
SIMT, warps і чому ваш kernel “повинен бути нудним”
Сучасні графічні процесори виконують потоки групами (warps). AMD має подібну концепцію (wavefronts). У межах warp потоки виконують одну і ту ж інструкцію одночасно — тільки над різними даними. Якщо ваш код розгалужується (різні потоки беруть різні гілки), GPU серіалізує ці гілки. Це перша крута межа продуктивності. Саме тому багато високопродуктивних GPU-ядр виглядають так, ніби їх писала людина, яка не довіряє творчості.
Фреймворки ШІ уникають розгалуженої логіки на гарячому шляху. Вони збирають великі операції у ф’юзені ядра: “множення, додавання, layernorm, активація” — усе в один прохід, де можливо. Це зменшує кількість звернень до пам’яті, покращує кеш-поведінку і утримує SMs зайнятими.
Tensor core: апарат, що змінив правила гри
Tensor-ядра (і подібні матричні рушії) — спеціалізовані блоки для матричної математики з форматами нижчої точності: FP16, BF16, а тепер і FP8 в нових архітектурах. Це не “шляхом скорочення”. Це інженерія: нейронні мережі часто толерантні до зменшеної точності, особливо під час інференсу. Ця толерантність конвертується в значне прискорення.
Але зменшена точність не безкоштовна. Вона може дестабілізувати тренування, якщо неправильно обробляти масштабування й накопичення. Змішане тренування працює, бо фреймворки обережно тримають певні операції у вищій точності (наприклад накопичувачі), одночасно переміщуючи більшу частину математики у нижчу точність.
VRAM: справжній межовий ресурс
На десктопі VRAM — це жорстка межа. Коли ви її перевищуєте, ви або падаєте з помилкою, або відкотитесь на CPU, або починаєте використовувати повільніші шляхи пам’яті, які перетворюють ваш “суперкомп’ютер” на сумний обігрівач. Якщо ви запам’ятаєте одне: для великих моделей VRAM — це бюджет, а не маркетингова назва GPU.
Короткий жарт №1: VRAM — як шафа: ви не помічаєте її, поки не переїдете і не виявите, що ваше пальто живе на кухні.
PCIe і “проблема шини”
GPU не є автономною всесвітом. Дані мають дістатися до нього. CPU готує завдання і запускає ядра. Підсистема зберігання читає датасети. Шина PCIe переносить дані. Якщо ви навчаєте або виконуєте інференс з великими батчами, ви легко можете стати обмеженими шиною. Ось чому системи з “однаковим GPU” можуть поводитися дуже по-різному.
У мульти-GPU системах NVLink (коли доступний) може зменшити біль. Без нього часто доводиться платити високу ціну за пересилання тензорів через PCIe.
Історичні факти, що пояснюють сучасний хаос
ШІ на GPU не з’явилося через одну моментальну ідею інженера. Воно виникло, коли зіткнулися кілька індустрій: ігри, наукові обчислення і веб-масштабне машинне навчання. Ось конкретні історичні моменти, які роблять сучасний ландшафт менш загадковим:
- Ранні 2000-ті: дослідники використовували графічні API (OpenGL/DirectX) для загального обчислення, бо математика на GPU була дешева і доступна.
- 2006: з’явився CUDA і зробив GPU програмованими без необхідності прикидатися, що ваша нейромережа — це шейдер пікселя.
- 2012: навчання AlexNet на GPU стало переломним моментом для практичного впровадження глибокого навчання.
- Середина 2010-х: cuDNN перетворив “GPU для глибокого навчання” з героїчних кастомних ядер у те, що фреймворк може абстрагувати.
- 2017: трансформери показали, що моделі з увагою гарно масштабуються і дуже потребують матричної пропускної здатності — це ідеально під GPU.
- 2018–2020: змішане тренування стало масовим, протягнувши FP16/BF16 у щоденні робочі процеси.
- З 2022: зросло споживче зацікавлення локальним інференсом; квантізація й ефективні реалізації уваги стали звичними термінами для хобістів.
- Протягом усього часу: пропускна здатність пам’яті зростала як центральне обмеження; HBM у дата-центрових GPU стала визначальною відмінністю.
Парафразована ідея (не дослівно): “Все ламається, постійно.” — Werner Vogels, у підході до надійності, що системи потрібно проєктувати з очікуванням помилок.
Справжні вузькі місця: обчислення, VRAM, пропускна здатність, сховище та «ой»
1) Обчислення — це не одне число
Маркетинг GPU підкреслює TFLOPS. Це корисно, але неповно. Продуктивність ШІ залежить від:
пропускної здатності в низькій точності (FP16/BF16/FP8), використання tensor-ядр, ефективності ядер та того, як часто ви блокуєтесь на пам’яті.
Дві карти можуть мати схожі TFLOPS і все одно поводитися по-різному, бо одна має вищу пропускну здатність пам’яті, більші кеші, краще планування або просто кращу підтримку ядер у вашій версії фреймворку.
2) VRAM та фрагментація
Вичерпання VRAM видно відразу. Фрагментація підступніша: у вас може бути “достатньо загальної вільної пам’яті”, але бракує суцільних блоків для великого виділення. Деякі аллокатори можуть пом’якшити це (у PyTorch є налаштування), але найкраще рішення — проєктувати навантаження так, щоб уникнути патологічних шаблонів виділення: повторно використовувати буфери, тримати форми стабільними і не міняти розмір моделей “на гарячому” у довго працюючому процесі.
3) Пропускна здатність пам’яті: мовчазний обмежувач
Багато операцій ШІ є обмеженими пам’яттю: ви переміщуєте тензори більше, ніж виконуєте над ними математику. Якщо ваша завантаженість низька, але контролер пам’яті GPU зайнятий, ймовірно ви обмежені пропускною здатністю. Це натякає на:
зменшення точності, кращу ф’юзацію, ефективніші реалізації уваги або зменшення проміжних активацій (checkpointing) під час тренування.
4) Сховище та вхідний конвеєр
Тренування часто обмежується завантаженням даних, декодуванням і аугментацією. Швидкий GPU може простоювати, бо Python декомпримує JPEG як у 2009-му. NVMe допомагає, але не рятує однониткову попередню обробку. Виправлення включають:
кешування попередньо оброблених датасетів, паралельні data loader-и, pinned memory і перенесення важкої аугментації на GPU.
5) Живлення, терміка і частоти
Якщо ваша GPU “повільна”, перевірте, чи вона не тротлить. Користувацькі системи відомі обмеженнями живлення й тепловим насиченням. 450W карта, яка страждає через нестабільний PSU або засмічений радіатор, — це не проблема обчислень; це проблема інфраструктури в мініатюрі.
6) Категорія “ой”: драйвери, версії та припущення
Більшість інцидентів у продакшені з GPU у ШІ — це не екзотичні апаратні збої. Це невідповідності:
драйвер проти версії CUDA, runtime контейнера проти драйвера хоста, фреймворк проти здібностей обчислення, і припущення на кшталт “в мене на ноуті працювало”.
Короткий жарт №2: Найшвидший спосіб зменшити латентність моделі — оновити слайд-презентацію — нічого не зрівняється з інференсом у 0 мс.
Практичні завдання: команди, результати, рішення
Нижче — практичні завдання, які я дійсно використовую при діагностиці продуктивності та надійності GPU для ШІ. Кожне містить команду, реалістичний зразок виводу, що це означає, і яке рішення прийняти далі. Вони орієнтовані на Linux, бо саме там відбувається більшість серйозної роботи з GPU, навіть якщо все почалося на десктопі.
Завдання 1: Перевірити, чи драйвер бачить вашу GPU (і яку саме)
cr0x@server:~$ nvidia-smi -L
GPU 0: NVIDIA GeForce RTX 4090 (UUID: GPU-3a6b1c2d-xxxx-xxxx-xxxx-9c2e4b2f1a7d)
Що це означає: Ядро драйвера завантажене і пристрій перелічено. Якщо ця команда не працює — все інше не має значення.
Рішення: Якщо відсутній, виправте встановлення драйвера, налаштування secure boot або модуль ядра перед тим, як торкатися фреймворків.
Завдання 2: Перевірити версію драйвера і сумісність CUDA
cr0x@server:~$ nvidia-smi
+---------------------------------------------------------------------------------------+
| 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 RTX 4090 Off | 00000000:01:00.0 On | N/A |
| 30% 54C P2 120W / 450W | 8200MiB / 24564MiB | 78% Default |
+-------------------------------+----------------------+----------------------------------+
Що це означає: У вас встановлений драйвер; він повідомляє “CUDA Version”, яку підтримує API драйвера. Це не гарантує, що ваш інструментарій всередині контейнера співпадає, але це базова відправна точка.
Рішення: Якщо фреймворк скаржиться на CUDA — узгодьте образ контейнера/версію тулкіта з можливостями драйвера хоста.
Завдання 3: Підтвердити ширину та швидкість PCIe (поширений прихований обмежувач)
cr0x@server:~$ nvidia-smi -q | sed -n '/PCI/,/Clocks/p'
PCI
Bus : 0x01
Device : 0x00
Domain : 0x0000
Bus Id : 00000000:01:00.0
PCIe Generation
Max : 4
Current : 4
Link Width
Max : 16x
Current : 8x
Clocks
Graphics : 2520 MHz
Що це означає: GPU працює на Gen4, але лише x8 ліній. Це може бути нормально для чистого обчислення, але може стати вузьким місцем для інтенсивних передач даних або мульти-GPU комунікації.
Рішення: Якщо навантаження залежить від передач, переінсталюйте карту, перевірте налаштування BIOS для lane bifurcation або перемістіть її в повний x16 слот.
Завдання 4: Слідкувати за завантаженням і тиском на пам’ять в реальному часі
cr0x@server:~$ nvidia-smi dmon -s pucm -d 1
# gpu pwr gtemp mtemp sm mem enc dec mclk pclk
# Idx W C C % % % % MHz MHz
0 330 71 - 92 78 0 0 10501 2520
0 338 72 - 94 81 0 0 10501 2520
Що це означає: Високе завантаження SM і високе використання пам’яті свідчить про активне використання обчислень. Якщо SM низький, але споживання енергії високе, ви можете бути обмежені пропускною здатністю або затримками в інших місцях.
Рішення: Якщо SM низький, перевірте CPU-конвеєр, диск I/O або накладні витрати на запуск ядер замість придбання ще однієї потужнішої GPU.
Завдання 5: Визначити процеси, що займають VRAM
cr0x@server:~$ nvidia-smi --query-compute-apps=pid,process_name,used_gpu_memory --format=csv
pid, process_name, used_gpu_memory [MiB]
18422, python, 17340 MiB
19107, python, 6200 MiB
Що це означає: У вас кілька процесів споживають VRAM. Це важливо, бо навіть “вільні” моделі можуть резервувати пам’ять.
Рішення: Вирішіть, чи об’єднати в один процес (сервер з розподілом моделей) або забезпечити ізоляцію через окремі GPU / MIG / планування.
Завдання 6: Перевірити вузькі місця на CPU і розподіл навантаження
cr0x@server:~$ mpstat -P ALL 1 2
Linux 6.5.0 (server) 01/13/2026 _x86_64_ (32 CPU)
01:10:54 PM CPU %usr %nice %sys %iowait %irq %soft %idle
01:10:55 PM all 120.0 0.0 12.0 1.0 0.0 2.0 865.0
01:10:55 PM 7 98.0 0.0 1.0 0.0 0.0 0.0 1.0
01:10:55 PM 12 97.0 0.0 1.0 0.0 0.0 0.0 2.0
Що це означає: Декілька ядер CPU завантажені на повну, тоді як багато інших простоюють. Це типово для Python data loader-ів або вузьких місць у токенізації.
Рішення: Паралелізуйте попередню обробку, збільшіть кількість робітників даталоадера, перенесіть токенізацію з критичного шляху або використайте компільований бекенд токенізатора.
Завдання 7: Виміряти пропускну здатність диска для датасетів/чекпоінтів
cr0x@server:~$ fio --name=seqread --filename=/mnt/nvme/testfile --size=4G --rw=read --bs=1M --iodepth=16 --numjobs=1 --direct=1
seqread: (g=0): rw=read, bs=(R) 1024KiB-1024KiB, (W) 1024KiB-1024KiB, (T) 1024KiB-1024KiB, ioengine=libaio, iodepth=16
fio-3.35
seqread: (groupid=0, jobs=1): err= 0: pid=22144: Thu Jan 13 13:12:01 2026
read: IOPS=3150, BW=3076MiB/s (3224MB/s)(4096MiB/1332msec)
Що це означає: Ви можете читати ~3 ГБ/с послідовно. Чудово для великих суцільних датасетів, менш інформативно для дрібних файлів.
Рішення: Якщо ваш конвеєр читає багато дрібних файлів, перейдіть на більші шарди або додайте кеш; сирий NVMe не врятує від метаданихних штормів.
Завдання 8: Виявити проблему з дрібними файлами (метадані та випадковий I/O)
cr0x@server:~$ fio --name=randread4k --filename=/mnt/nvme/testfile --size=4G --rw=randread --bs=4k --iodepth=64 --numjobs=1 --direct=1
randread4k: (g=0): rw=randread, bs=(R) 4096B-4096B, (W) 4096B-4096B, (T) 4096B-4096B, ioengine=libaio, iodepth=64
fio-3.35
randread4k: (groupid=0, jobs=1): err= 0: pid=22401: Thu Jan 13 13:13:12 2026
read: IOPS=420k, BW=1641MiB/s (1720MB/s)(4096MiB/2494msec)
Що це означає: Випадкова читальна продуктивність сильна. Якщо тренування все ще заважається, вузьке місце може бути у CPU-декодуванні або накладних витратах фреймворку, а не в диску.
Рішення: Профілюйте попередню обробку і dataloader. Не купуйте дисків, щоб вирішити проблеми з Python.
Завдання 9: Перевірити тиск на пам’ять і своп (повільна катастрофа)
cr0x@server:~$ free -h
total used free shared buff/cache available
Mem: 125Gi 96Gi 2.1Gi 1.4Gi 27Gi 18Gi
Swap: 32Gi 14Gi 18Gi
Що це означає: Відбувається свопінг. Це може знищити пропускну здатність і спричинити дивну недовантаженість GPU, бо CPU працює з пагінгом.
Рішення: Зменшіть batch size, зменшіть пам’ять даталоадера, зменшіть передвибірку або додайте оперативної пам’яті. Якщо ви свопите під час тренування — ви не тренуєтеся; ви торгуєтесь з ядром.
Завдання 10: Підтвердити передачу GPU в Docker
cr0x@server:~$ docker run --rm --gpus all nvidia/cuda:12.3.2-base-ubuntu22.04 nvidia-smi -L
GPU 0: NVIDIA GeForce RTX 4090 (UUID: GPU-3a6b1c2d-xxxx-xxxx-xxxx-9c2e4b2f1a7d)
Що це означає: Runtime контейнера під’єднано і він може дістатися GPU через драйвер хоста.
Рішення: Якщо це не працює — виправте NVIDIA Container Toolkit / конфігурацію runtime перш ніж звинувачувати PyTorch.
Завдання 11: Підтвердити, що PyTorch бачить CUDA (і з якою версією побудовано)
cr0x@server:~$ python -c "import torch; print(torch.cuda.is_available()); print(torch.version.cuda); print(torch.cuda.get_device_name(0))"
True
12.1
NVIDIA GeForce RTX 4090
Що це означає: CUDA доступна у вашому Python-середовищі. Версія CUDA, що показана, — це та, під яку зібрано PyTorch, а не обов’язково тулкіт хоста.
Рішення: Якщо False, у вас невідповідність залежностей або відсутні бібліотеки; виправте це перед тим, як тонко налаштовувати щось інше.
Завдання 12: Впіймати ECC/Xid помилки в логах (апарат чи софт — відділяємо)
cr0x@server:~$ sudo dmesg -T | egrep -i 'nvrm|xid|cuda|pcie' | tail -n 8
[Tue Jan 13 13:02:44 2026] NVRM: Xid (PCI:0000:01:00): 31, pid=18422, name=python, Ch 0000003a
[Tue Jan 13 13:02:44 2026] NVRM: Xid (PCI:0000:01:00): 31, GPU has fallen off the bus.
Що це означає: “Fallen off the bus” часто пов’язано з проблемами живлення/цілісності PCIe, іноді з багами драйверів, іноді з перегріванням. Рідко це “код вашої моделі”.
Рішення: Перевірте PSU, кабелі, riser-и, слот PCIe, термальну ситуацію і спробуйте змінити драйвер. Також зменшіть ліміт потужності для перевірки стабільності.
Завдання 13: Перевірити ліміт енергії GPU і встановити стабільну межу
cr0x@server:~$ nvidia-smi -q | sed -n '/Power Readings/,/Clocks/p'
Power Readings
Power Management : Supported
Power Draw : 438.12 W
Power Limit : 450.00 W
Default Power Limit : 450.00 W
cr0x@server:~$ sudo nvidia-smi -pl 380
Power limit for GPU 00000000:01:00.0 was set to 380.00 W from 450.00 W.
Що це означає: Ви можете встановити ліміт потужності, щоб зменшити транзієнтні сплески і поліпшити стабільність, часто з невеликою втратою продуктивності.
Рішення: Якщо ви бачите випадкові перезавантаження або Xid помилки, обмежте потужність під час розслідування; у продакшені краще “трохи повільніше”, ніж “іноді мертвий”.
Завдання 14: Перевірити температури і стан тротлінгу
cr0x@server:~$ nvidia-smi --query-gpu=temperature.gpu,clocks.sm,clocks_throttle_reasons.active --format=csv
temperature.gpu, clocks.sm [MHz], clocks_throttle_reasons.active
83, 2100, Active
Що це означає: Причини тротлінгу активні; при 83°C ви можете стикатися з термічними або енергетичними обмеженнями залежно від карти й охолодження.
Рішення: Покращіть потік повітря, перепосадіть кулер, відрегулюйте криву вентиляторів або зменшіть ліміт потужності. Не “оптимізуйте ядра”, коли GPU фізично занижує частоти.
Завдання 15: Помітити накладні витрати на запуск ядер і прості з боку CPU (швидко і грубо)
cr0x@server:~$ python -m torch.utils.bottleneck train.py
...
CPU time total: 312.45s
CUDA time total: 128.77s
Top CPU ops: DataLoader, tokenizer_encode, python overhead
Top CUDA ops: aten::matmul, aten::scaled_dot_product_attention
Що це означає: Ви витрачаєте більше часу на CPU, ніж на GPU. Ваш GPU не є вузьким місцем; він чекає.
Рішення: Виправте вхідний конвеєр, батчову токенізацію або використайте швидший dataloader замість гонитви за “кращими налаштуваннями GPU”.
Завдання 16: Підтвердити NUMA-локальність (тихий вбивця продуктивності в двопроцесорних системах)
cr0x@server:~$ nvidia-smi topo -m
GPU0 CPU Affinity NUMA Affinity
GPU0 X 0-15,32-47 0
Що це означає: GPU ближчий до підмножини ядер CPU/NUMA вузла. Якщо ваш процес працює на невідповідному NUMA вузлі, трафік PCIe переходить між сокетами.
Рішення: Закріпіть процес/потоки даталоадера на відповідні ядра за допомогою taskset або systemd CPUAffinity для стабільної продуктивності.
Завдання 17: Перевірити мережу як вузьке місце (для віддалених датасетів чи об’єктного сховища)
cr0x@server:~$ ip -s link show eth0
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP mode DEFAULT group default qlen 1000
RX: bytes packets errors dropped missed mcast
9876543210 6543210 0 421 0 0
TX: bytes packets errors dropped carrier collsns
8765432109 5432109 0 0 0 0
Що це означає: Відкинуті пакети на RX можуть призводити до повторних передач і сплесків у завантаженні даних, особливо якщо ви стрімите дані.
Рішення: Виправте стан мережі або кешуйте дані локально; не перетворюйте “тренування” на тест витривалості мережі.
Швидкий план діагностики
Коли продуктивність падає або латентність інференсу дивна, потрібен короткий шлях до істини. Ось порядок, що швидко знаходить вузькі місця в реальному світі.
Перш за все: чи GPU взагалі використовується?
- Запустіть
nvidia-smiі перевірте GPU-Util та Memory-Usage. - Якщо GPU-Util близький до 0% під час вашого нібито “GPU-наванттаження”, ви або на CPU, або блокуєтеся на даних, або відбувається падіння/перезапуск.
- Рішення: виправте доступність CUDA, розміщення пристрою у фреймворку або затримки даталоадера перед тим, як змінювати архітектуру моделі.
Друге: GPU голодний чи задихається?
- Використайте
nvidia-smi dmon -s pucm -d 1для моніторингу енергії/температури/SM/пам’яті. - Низький SM при високій пам’яті або високій потужності свідчить про пропускні затримки чи неефективні ядра.
- Високий SM, але низька пропускна здатність означає, що частоти тротляться або навантаження надто маленьке (batch size, довжина послідовності).
- Рішення: оберіть правильний важіль — batch size, ф’юзені ядра уваги, точність або охолодження/потужність.
Третє: перевірте VRAM і поведінку аллокатора
- Шукайте OOM помилки, але також слідкуйте за “біля-OOM” поведінкою, коли продуктивність падає через часті виділення.
- Рішення: зменшіть batch, увімкніть квантізацію для інференсу, використайте gradient checkpointing для тренування або оберіть меншу модель.
Четверте: виміряйте вхідний конвеєр
- CPU завантаження і iowait:
mpstat,iostat,pidstatякщо встановлено. - Диск: базовий
fio, потім профілюйте формат файлів і час декодування. - Рішення: шардуйте датасети, кешуйте попередньо оброблені результати або переносьте попередню обробку на GPU.
П’яте: підтвердіть цілісність платформи
- Перевірте
dmesgна Xid та PCIe помилки. - Перевірте живлення і тротлінг по теплу.
- Рішення: розглядайте стабільність як функцію. Обмежте потужність, покращіть охолодження і перестаньте використовувати сумнівні PSU “бо воно завантажується”.
Три корпоративні історії з практики
Міні-історія 1: Інцидент через хибне припущення
У них був “простий” план: взяти модель, яка працювала в staging, розгорнути її в production на GPU-боксі і вважати справу завершеною. Команда припустила, що якщо torch.cuda.is_available() повертає True, GPU-шлях “активний і швидкий”. Це не тест; це привітання.
У продакшені латентність поступово росла протягом тижня. Потім почали з’являтися тайм-аути під навантаженням. Графіки були заплутані: CPU завантаження високе, GPU завантаження низьке. Хтось наполягав, що то “просто трафік” і пропонував додати більше GPU-інстансів. Вони це зробили — і проблема лишилася. Дорого.
Справжній режим відмови: сервіс інференсу запускав кілька worker-процесів, кожен завантажував модель окремо. VRAM був майже повністю зайнятий, не лишалося запасу для сплесків активацій. Фреймворк почав відкотитись на повільніші шляхи, а іноді процеси OOM-илися і перезапускалися. Балансувальник бачив флапінг інстансів. Латентність виглядала як “нормальне навантаження”, але насправді це була хмарка перезапусків.
Виправлення були нудні: один процес з завантаженою моделлю на GPU, батчування запитів з жорстким лімітом і конфігурація з гарантованим бюджетом VRAM. Вони також додали алерт на “GPU memory used > 90% протягом 10 хвилин” і ще один на “GPU-Util < 20% при високому QPS”. Інцидент закінчився не героїчними діями, а меншою кількістю процесів.
Міні-історія 2: Оптимізація, яка відбилася бумерангом
Інша команда хотіла знизити витрати на інференс. Вони ввімкнули агресивну квантізацію і поміняли ядро уваги на швидше. Бенчмарки на одному промпті виглядали чудово. CFO отримав електронну таблицю. Рол-аут пішов на половину флоту.
Через два дні з’явилися скарги клієнтів: відповіді мали тонкі помилки, особливо на довгих контекстах. Гірше — сервіс став нестабільним при певних комбінаціях запитів. Метрики GPU не кричали “проблема”. Це був тип відмови, що примушує сумніватися в розумі.
Корінь проблеми був двоякий. По-перше, схема квантізації погано взаємодіяла з певними шарами, і якість падала на крайових випадках — те, що мікро-бенчмарки не покривали. По-друге, “швидше” ядро використовувало більше тимчасової робочої пам’яті при довгих послідовностях. За змішаного трафіку це спричиняло короткочасні сплески VRAM, що штовхали процес до фрагментації аллокатора і іноді до OOM.
Відкат відновив стабільність. Подальній виправний шлях: селективна квантізація (не повсюдна), класифікація запитів за довжиною, і політика запасу VRAM. Вони також змінили тестування продуктивності: більше не було демонстрацій на одному промпті. Тепер бенчмарки включають довгі контексти, змішані розміри пакетів і найгірші сценарії пам’яті. Оптимізація — це інженерія, а не екстремальний спорт.
Міні-історія 3: Нудна, але правильна практика, що врятувала день
Компанія, що запускала внутрішні тренувальні завдання, мала правило: кожна GPU-нод ранок/ніч виконувала “пробний прогін” здоров’я. Це нічого захопливого — просто перевірка драйвера, короткий стрес-тест, перегляд dmesg на нові Xid-повідомлення, перевірка NVMe SMART і запис базової пропускної здатності для маленького тренувального циклу.
За тиждень одна нода почала показувати періодичні правильні повідомлення PCIe. Ніхто спочатку не помітив, бо тренувальні джоби зазвичай повторювалися і переходили далі. Але sweep помітив зміну: базовий тренувальний цикл ноди став нестабільним, а dmesg показав свіжі PCIe AER-повідомлення.
Вони відключили ноду зі scheduler-у і відкрили шасі. Кабель живлення до адаптера GPU був злегка незакріплений — достатньо, щоб “здавалося нормальним” до моменту пікового навантаження. Під реальним тренуванням GPU іноді відвалювався з шини, спричиняючи помилки робіт, які виглядали як випадкові крахи софту.
Оскільки вони трактували апаратні сигнали як першокласну телеметрію, проблема була виявлена рано, виправлена за 15 хвилин і вони уникли тижня обвинувачень у бік бібліотек. Профілактичне обслуговування непопулярне, бо нудне; ефективне воно тому, що реальність теж нудна.
Поширені помилки: симптом → причина → виправлення
1) Симптом: GPU-Util низький, CPU високий, роботи повільні
Корінь: Вузьке місце в вхідному конвеєрі (токенізація, декодування, аугментація) або синхронна CPU-попередня обробка.
Виправлення: Збільште кількість робітників даталоадера, шардуйте/кешуйте датасет, використайте швидші токенізатори, передтокенізуйте або перенесіть попередню обробку на GPU. Підтвердіть профілем і mpstat.
2) Симптом: Випадкові “CUDA out of memory” незважаючи на видиму “достатню” VRAM
Корінь: Фрагментація від змінних форм або численних виділень, плюс короткочасні сплески при довгих послідовностях або великих батчах.
Виправлення: Стабілізувати форми (bucketing), зменшити батч/довжину послідовності, забезпечити запас пам’яті, повторно використовувати буфери, перезапускати довго живучі процеси або налаштувати аллокатор у фреймворку.
3) Симптом: Швидкість тренування непередбачувана між прогоном
Корінь: Тротлінг через тепло/потужність, фонові процеси, що використовують GPU, або відмінності NUMA-локальності.
Виправлення: Перевірте стан тротлінгу, обмежте потужність, покращіть охолодження, ізолюйте GPU і закріпіть CPU-потоки до NUMA-вузла GPU.
4) Симптом: “GPU has fallen off the bus” / Xid помилки
Корінь: Проблеми живлення, нестабільний PCIe-зв’язок, riser-и, перегрів або драйвери.
Виправлення: Перевірте кабелі/PSU, переставте GPU, оновіть або поміняйте гілку драйвера, тимчасово зменшіть ліміт потужності для стабільності, перевірте налаштування BIOS.
5) Симптом: Продуктивність гірша в Docker, ніж на хості
Корінь: Невідповідний стек runtime/драйвера, обмеження CPU, недостатній shared memory або накладні витрати файлової системи.
Виправлення: Перевірте docker run --gpus all ... nvidia-smi, встановіть адекватний --shm-size, уникайте overlayfs для інтенсивного I/O і забезпечте контейнер правильною CUDA-збіркою.
6) Симптом: Масштабування на кілька GPU жахливе
Корінь: Комунікаційні накладні (PCIe), погана стратегія паралелізму, малі батчі або CPU-вузькі місця на кожному ранку.
Виправлення: Збільшіть глобальний батч, використайте gradient accumulation, забезпечте швидкий інтерконект якщо доступний, профілюйте комунікацію. Не припускайте, що додавання GPU автоматично вдвічі скоротить час.
7) Симптом: NVMe швидкий, але dataloader все ще повільний
Корінь: Дрібні файли + накладні витрати Python + декомпресія домінують, а не суцільна пропускна здатність диска.
Виправлення: Використайте шардові формати, послідовні читання, memory-mapping, кешування або попередньо декомпресовані датасети. Вимірюйте випадковий I/O і час CPU.
8) Симптом: Піки латентності інференсу при змішаному трафіку
Корінь: Неблоковані довжини послідовностей, неконтрольоване динамічне батчування, сплески VRAM або конкуренція CPU при токенізації.
Виправлення: Встановіть обмеження на запити, класифікуйте по довжині, обмежте batch/kv-cache, резервуйте запас VRAM і вимірюйте tail latency окремо.
Чек-листи / покроковий план
Покроково: зібрати адекватну GPU-систему “домашнього суперкомп’ютера”
- Оберіть GPU за VRAM насамперед. Якщо цільова модель ледве вміщається — вона не вміщається. Плануйте запас.
- Купіть PSU, який не соромно повернути. Хороші блоки краще витримують транзієнти. Стабільність важливіша за теоретичні пікові показники.
- Охолодження не опціональне. Забезпечте проплив повітря в корпусі і чисті фільтри. Гарячі GPU тротлять; тротлінг бреше про продуктивність.
- Використовуйте NVMe для датасетів і чекпоінтів. Але не розраховуйте, що це виправить CPU-попередню обробку.
- Встановіть надійну гілку драйвера. І не оновлюйте її необережно на машині, що нагадує продакшн.
- Перевірте стек від краю до краю. Запустіть
nvidia-smi, потім перевірку passthrough у контейнері, потім виявлення GPU фреймворком. - Закріпіть версії. Збережіть
pip freezeабо використайте lockfile. Відтворюваність — тихий супутник інженерії продуктивності.
Покроково: забезпечити стабільний інференс на одній GPU
- Встановіть бюджет VRAM. Резервуйте запас для сплесків. Лічіть 90–95% VRAM як “небезпечний рівень”.
- Обмежте розмір запитів. Встановіть жорсткі ліміти на довжину контексту й кількість вихідних токенів. Tail latency вам подякує.
- Батчуйте свідомо. Мікробатчування може підвищити пропускну здатність, але неконтрольоване динамічне батчування може вибухнути VRAM.
- Квантізуйте стратегічно. Використовуйте квантізацію, щоб вмістити модель і збільшити пропускну здатність, але тестуйте довгі контексти й крайові випадки.
- Слідкуйте за tail-метриками. Середні значення ховають біль. Відстежуйте p95/p99 і корелюйте з VRAM та довжиною послідовностей.
Покроково: забезпечити надійне тренування на одній GPU
- Почніть з малого прогону. Перевірте, що loss знижується, чекпоінти записуються і dataloader не зависає.
- Правильно використовуйте змішану точність. Якщо бачите NaN — виправте масштабування і стабільність перед тим, як звинувачувати GPU.
- Контролюйте пам’ять. Зменшіть batch size, використайте gradient accumulation і розгляньте checkpointing для зменшення активацій.
- Зробіть I/O нудним. Розмістіть датасети на швидкому локальному сховищі, зменшіть кількість дрібних файлів і по можливості передтокенізуйте.
- Знімайте базові показники. Вимірюйте images/sec або tokens/sec на відомому зразку. Перевіряйте після змін. Без бази — немає діагностики.
Правило: Якщо ви не можете пояснити вузьке місце одним реченням — ви ще не досліджували.
Питання й відповіді (FAQ)
1) Мені справді потрібна GPU для ШІ вдома?
Для малих моделей — ні. Для сучасних LLM, генерації зображень і всього, що не є іграшкою — так, якщо ви не любите чекати. GPU перетворює “хвилини” на “секунди”, прискорюючи щільну лінійну алгебру, що лежить в основі цих моделей.
2) Чи завжди більше VRAM краще за швидшу GPU?
Для локального інференсу VRAM зазвичай є граничним фактором. Трохи повільніша карта, яка комфортно вміщає модель, часто перевершить швидшу карту, яка змушує вас відвантажувати на CPU або вдаватися до агресивних компромісів.
3) Чому моя GPU стоїть на 10% завантаження під час тренування?
Найчастіше: CPU-завантажений конвеєр даних, токенізація, аугментація або повільна файлова система. Підтвердіть за допомогою метрик CPU і профайлера. Виправлення конвеєру зазвичай піднімає завантаження “безкоштовно”.
4) Який найшвидший спосіб покращити локальну продуктивність LLM?
Квантізація (щоб вмістити модель у VRAM і підвищити пропускну здатність), ефективні ядра уваги і розумне батчування. Також: припиніть свопінг на хості; пагінг робить усе виглядати зламаним.
5) Чому я отримую “CUDA out of memory”, коли використання VRAM здається не максимальним?
Фрагментація аллокатора й тимчасові піки. Ваш монітор може показувати “вільну пам’ять”, але аллокатор може не мати достатнього суцільного блоку, або тимчасова робоча пам’ять перевищує ліміт.
6) Чи важлива швидкість PCIe для інференсу?
Для одно-GPU інференс-сервера, де модель і KV-cache живуть у VRAM, PCIe часто не є головним обмежувачем. Воно важливіше, коли ви часто стрімуєте великі тензори, робите offload на CPU або використовуєте модельний паралелізм на кількох GPU.
7) Чи запускати ШІ в Docker чи напряму на хості?
Docker підходить і часто кращий для відтворюваності — якщо ви перевірили passthrough GPU і налаштування shared memory й файлової системи. Міф “контейнер повільніший” зазвичай означає “мій контейнер неправильно налаштовано”.
8) У чому практична різниця між “GPU compute” і “tensor cores”?
Tensor-ядра сильно прискорюють матричні операції в нижчій точності. Якщо ваш фреймворк ефективно їх використовує, ви побачите значні прискорення з FP16/BF16/FP8. Якщо ні — ваша “швидка GPU” виглядає підозріло посередньо.
9) Чи можу я тренувати великі моделі на одній споживчій GPU?
Ви можете тренувати щось, але “велике” — відносне. Техніки як змішана точність, gradient accumulation і checkpointing розтягують можливості. Проте VRAM — це стіна, а час навчання може бути другою стіною.
10) Як дізнатися, чи моя GPU тротлить?
Перевірте температуру, споживання потужності і причини тротлінгу в nvidia-smi. Якщо частоти падають під навантаженням або тротлінг активний — покращуйте охолодження або зменшуйте ліміт потужності. Не бенчмаркуйте тротлену GPU і не називайте це “науковим підходом”.
Практичні подальші кроки
Якщо ви хочете, щоб ваша GPU поводилась як домашній суперкомп’ютер, а не примхливий прилад, зробіть три речі цього тижня:
- Встановіть базову лінію. Оберіть один репрезентативний інференс-промпт і один маленький тренувальний прогін, зафіксуйте tokens/sec або steps/sec і збережіть це версиовано.
- Інструментуйте реальність. Слідкуйте одночасно за завантаженням GPU, VRAM, CPU і дисковим I/O. Кореляція краща за здогадки.
- Впровадьте бюджети. Запас VRAM, ліміти на розмір запитів, обмеження потужності за потреби. Ви не зможете “оптимізувати” фізику.
Революція GPU у ШІ — не магія. Це дуже специфічний тип паралельної математики на залізі, яке стало надзвичайно ефективним, бо геймери вимагали красивіших вибухів. Ваше завдання — підживити його чистими даними, тримати його холодним і перестати вірити міфам про продуктивність, які розкриваються, як тільки ви запустите nvidia-smi.