Ви купили другий GPU в надії, що графік піде вгору і направо. Натомість ваше тренування стало нестабільним, латентність інференсу почала поводитися дивно, а половина вашого «завантаження GPU»
виявилася індикатором очікування. Дашборди виглядають зайнятими. Рахунок часу соромиться.
Ось що ніхто не рекламує: два GPU не означають автоматично «вдвічі більше обчислень». Часто це означає вдвічі більше способів зламатися, вдвічі більше споживання енергії та нову категорію
вузьких місць, яких вчора не було.
Міф: «Два GPU = у 2× швидше»
Міф живе, бо він правдивий в одному вузькому світі: в задачах з «захоплювальною» паралельністю без складної синхронізації, з мінімальними переміщеннями даних і зі стеком програмного забезпечення,
який дійсно ефективно распределяє роботу між пристроями. Такий світ існує. Просто це не той світ, у якому працює більшість команд.
У продакшн-системах масштабування рідко блокується сирими FLOPами. Воно блокується всім, що їх оточує: копіювання пам’яті, накладні витрати на запуск кернелів, бульбашки пайплайна, конкуренція CPU,
топологія PCIe, розміщення NUMA, поведінка драйверів, термальне тротлінг, і операційна реальність, що більше заліза збільшує поверхню для дивних вад.
Тому коли люди кажуть «мульти-GPU», вони зазвичай мають на увазі «я додав складності і тепер торгуюся з фізикою».
Справжні причини, чому два GPU розчаровують
1) VRAM не сумується (у більшості випадків), і це перша зрада
Два 24 ГБ GPU не стають магічно 48 ГБ доступної пам’яті моделі. Якщо ви явно не шардите модель (tensor parallelism, pipeline parallelism, expert parallelism),
кожен GPU потребує власної копії параметрів (або великих їх підмножин), плюс активації, стан оптимізатора і робочу пам’ять.
Data-parallel тренування — це поширений «легкий» режим мульти-GPU: кожен GPU виконує ту саму модель на різних міні-батчах. Ви отримуєте більше пропускної здатності лише якщо встигаєте їх
забезпечувати даними і якщо синхронізація (редукція градієнтів) не з’їдає виграш. Але ємність пам’яті для самої моделі не подвоюється. Залишається потолок на GPU.
Цей потолок стає незручною пасткою планування: команди купують другий GPU «для ємності», а потім виявляють, що потрібен був більший одиночний GPU або інша стратегія паралелізму,
або і те, й інше.
2) Накладні витрати синхронізації: податок, який помічаєш занадто пізно
Більшість мульти-GPU тренувань не обмежені обчисленнями; вони обмежені тим, як швидко GPU можуть домовитися про те, що щойно сталося. У data-parallel це all-reduce градієнтів.
Чим більше GPU, тим більше часу йде на координацію.
Навіть при швидких зв’язках синхронізація не безкоштовна. Вона також має сплески: ви отримуєте серію корисних кернелів, а потім велику фазу комунікації, під час якої завантаження падає і
ви вдаєте, що все «в порядку», бо «GPU зарезервований».
Накладні витрати на комунікацію стають особливо неприємними коли:
- Розмір батчу на GPU стає занадто малим (ефективність кернелів падає, накладні витрати домінують).
- У моделі багато маленьких тензорів (більше викликів редукції, гірша чутливість до затримки).
- Міжз’єднання лише через PCIe і трафік конкурує з хостовим I/O.
- Топологія змушує трафік через різні CPU-сокети (штраф NUMA, що маскується під «GPU comms»).
3) Топологія PCIe: ваші GPU «близько» в шасі, але далеко насправді
Два GPU можуть бути підключені кількома способами, які на замовленні виглядають однаково, але сильно відрізняються за продуктивністю:
- Обидва GPU під тим самим PCIe root complex (зазвичай краще).
- Кожен GPU підключений до іншого CPU-сокета (поширено в двосокетних серверах).
- Поділені лінії або біфуркація, що зменшує ефективну пропускну здатність.
- Трафік маршрутизований через чипсетний хоп (затримки і штрафи пропускної здатності).
Якщо GPU0 «локальний» до CPU0, а GPU1 «локальний» до CPU1, і ваш процес прикріплений до неправильного сокету, вітаю: ви винайшли регрес продуктивності лише за допомогою закупівлі.
4) P2P і NVLink не чарівні; це контракти, які можна випадково порушити
Peer-to-peer (P2P) доступ дозволяє одному GPU читати пам’ять іншого GPU без стадії через оперативку хоста. NVLink піднімає потолок ще вище. Але ви не завжди це отримуєте:
- P2P може бути вимкнено платформними особливостями, налаштуваннями IOMMU, шарами віртуалізації або за замовчуванням у BIOS.
- Доступність NVLink залежить від точного SKU GPU і проводки сервера.
- Навіть коли доступно, ваш фреймворк може не вибрати оптимальний шлях без коректної конфігурації.
Мульти-GPU часто ламається не тому, що залізо повільне, а тому, що стек тихо відкотиться до копій через хост і ваше «швидке міжз’єднання» стає чуткою.
5) Утруднення CPU загострюються, коли додаєте GPU
Один GPU може приховати багато CPU-проблем. Два GPU роблять їх видимими. CPU має:
- Декодувати й аугментувати більше даних за одиницю часу (тиск загрузчиків даних).
- Запускати більше кернелів (накладні витрати драйвера, Python, фреймворку).
- Оркеструвати колективну комунікацію (NCCL налаштування, керування стрімами).
- Обробляти більше переривань та обліку DMA.
Якщо ваш пайплайн вже на межі, подвоєння кількості GPU просто подвоює швидкість, з якою ви досягаєте «чекаємо на вхід».
6) I/O та сховище: тихий вузький горлік, що руйнує «масштабування»
Якщо ви тренуєтеся на зображеннях або на шардених датасетах і не маєте серйозного плану I/O, два GPU — це дуже дорогий спосіб дізнатися, що ваше сховище підходить «для однієї
задачі», але не для двох. Я бачив, як мульти-GPU тренування перетворювало стабільну систему на гуркіт натовпу з безлічі дрібних читань і метаданих операцій.
Додавання GPU підвищує попит на:
- Пропускну здатність читання датасету (MB/s та IOPS).
- Операції з метаданими (безліч дрібних файлів, листинги об’єктних сховищ, індексація tar).
- Записи чекпоінтів (сплескові записи, тиск fsync).
Коли сховище стає обмежувачем, завантаження GPU стає театром: «зайнято» не означає «продуктивно».
7) Мікростатер і нерівномірність кадрів у графіці / інтерактивних задачах
У іграх і візуалізації мульти-GPU історично покладався на трюки типу alternate-frame rendering. Це може підняти середній FPS, але зробити часи кадрів нерівномірними.
Люди помічають нерівномірність. Бенчмарки цього не показують.
Саме тому «видає 120 FPS» може відчуватися гірше за один GPU зі стабільними 75 FPS. Одиниця, що має значення — не «кадри за секунду», а «скільки часу зайняв попередній кадр», повторювано,
під навантаженням.
8) Програмні шляхи мульти-GPU менше протестовані і більш крихкі
Код для одного GPU — це шлях за замовчуванням. Мульти-GPU — це «режим для просунутих», і просунуті режими притягують крайові випадки, як мухи до запалювача багів.
Типові точки крихкості:
- Дедлоки у розподілених колективах, коли один ранк викликає виняток, а інші продовжують чекати.
- Таймаути й зависання, що виникають лише при мережевому джиттері або високому навантаженні.
- Недетермінованість від асинхронного виконання й зменшеної видимості налагодження.
- Скидання драйвера, що вбиває всю роботу, а не лише один пристрій.
9) Математика надійності: два GPU подвоюють шляхи до провалу прогону
Два пристрої означають вдвічі більше вентиляторів, вдвічі більше VRAM, вдвічі більшу ймовірність, що один з них працює на межі температури, і вдвічі більше шансів, що ненадійний райзер або
роз’єм живлення введе переривчасті помилки.
Тренування довгі. Довгі завдання підсилюють рідкісні події. Режим провалу зсувається від «продуктивності» до «чи завершиться це до того, як щось стане злим?»
Одна цитата, що добре витримує час в операційних колах, належить John Allspaw: «Reliability is the feature.» Це вся гра, коли ваша система в продакшні.
10) Енергоспоживання, термальні умови і поведінка boost: другий GPU може уповільнити обидва
Класичний «чому апгрейд повільніший?» момент. Два GPU споживають більше енергії і виділяють більше тепла в той же корпус. Це може спричинити:
- Нижчі boost-частоти через ліміти по енергії.
- Термальне тротлінг, бо потік повітря тепер заблокований другим гарячим блоком.
- Налаштування вентиляторів, скарги на шум і врешті-решт «хтось змінив BIOS».
Якщо шасі не призначене для тривалих навантажень з двома GPU, ви можете опинитися з двома GPU, що працюють повільніше, ніж один у розумному термальному режимі.
Жарт №1: Додавати другий GPU заради швидкості — це як додавати другий кермо для кращого контролю. В основному збільшує кількість думок у машині.
11) Мульти-GPU інференс: пропускна здатність може зрости, але латентність часто погіршується
Для сервінгу важливі p95 і p99 латентності, а не лише токени/сек у тихий вівторок. Розподіл інференсу по GPU (tensor parallel) може покращити пропускну здатність для дуже великих моделей,
але додає між-GPU комунікацію на критичний шлях кожного запиту.
Це означає:
- Більше можливостей для хвостової латентності через синхронізацію і черги.
- Вищу чутливість до джиттера (планування ОС, переривання, «шумні сусіди»).
- Більш складну логіку батчингу, яка може призвести до провалів при пікових сплесках трафіку.
Два GPU чудові для сумарної пропускної здатності при великобатчовому інференсі. Для інтерактивної латентності вони можуть бути жахливими.
12) Відладжуваність погіршується, і ваша інцидент-реакція відчує це
Коли одно-GPU задача гальмує, ви зазвичай швидко знаходите винуватця: або вона bound-пам’яттю, або обчисленнями, або I/O. З двома GPU з’являються нові категорії:
- Нерівномірний розподіл роботи (один GPU чекає на інший).
- Неоптимальна колективна комунікація ( «стінка all-reduce» ).
- Несумісність топології (P2P вимкнено, невідповідний NUMA вузол, поганий PCIe слот).
Неприємна правда: налагодження продуктивності мульти-GPU не «важче в 2×». Воно важче «через більше вимірів, ніж ви можете втримати в голові о 2 ранку».
Факти та історія, які пояснюють цей безлад
- SLI і CrossFire створювалися для графіки, часто використовуючи alternate-frame rendering; вони оптимізували середній FPS, а не рівномірність кадрів.
- Мікростатер став відомою проблемою мульти-GPU, бо ранні мульти-GPU пайплайни давали нерівномірні часи кадрів, навіть коли середній FPS виглядав чудово.
- CUDA мульти-GPU спочатку сильно покладався на PCIe; індустрія швидко зрозуміла, що копіювання через хост — шлях в глухий кут для багатьох навантажень.
- NVIDIA представила NVLink, щоб вирішити проблеми пропускної здатності і затримки між GPU, які PCIe не міг подолати для великих систем.
- NCCL став стандартом для колективів, бо розподілене тренування потребує високопродуктивного all-reduce; наївні реалізації нищили масштабованість.
- «Пулінг пам’яті GPU» не є моделлю за замовчуванням; більшість програмних моделей трактують GPU як окремі адресні простори, якщо ви явно не керуєте шарингом.
- Покоління PCIe мають значення: PCIe 3.0 vs 4.0 vs 5.0 може змінити, чи буде комунікація дрібницею або домінуючою витратою.
- Двосокетні сервери створили топологічні пастки: підключення GPU через сокети може вводити затримки і штрафи пропускної здатності, що виглядає як «неефективність фреймворку».
- Сучасне масштабування deep learning швидко вдарило в «стіну комунікації»; далі додавання GPU дає спадні прибутки, якщо не змінити батч/модель/стратегію паралелізму.
Три корпоративні міні-історії (як це ламається в житті)
Міні-історія 1: Інцидент через хибне припущення
Середня компанія розгорнула новий pipeline тренування рекомендованої моделі. Вони валідовували його на одно-GPU робочій станції: стабільно, передбачувано і «достатньо швидко».
Наступним кроком було «просто додати ще один GPU» на стендовому сервері, щоб скоротити час тренування вдвічі перед дедлайном.
Припущення було чистим і хибним: вони чекали, що data-parallel буде безкоштовним. Вони подвоїли GPU, подвоїли розмір батчу і чекали того ж часу на крок. Натомість тренування
стартувало добре, а потім драматично сповільнилося після перших кількох хвилин.
Причина була не в обчисленнях. Це був I/O. Їхні дані жили в мережевій файловій системі з великою кількістю дрібних файлів, і другий GPU подвоїв навантаження загрузчиків.
Метаданний сервер почав трястися. Інші сервіси, що ділили те саме сховище, теж стали повільніші, бо «тренування» стало ввічливим DDoS з логами.
Інцидент ескалювався, бо симптоми були оманливі: завантаження GPU коливалося на 40–60%, що виглядало «добре» для людей, які плутають utilization з прогресом.
Тим часом час кроку зріс. Вони намагалися «полагодити GPU», перевстановлюючи драйвери і тикдаючи NCCL налаштування — це було як міняти шини, щоб вирішити витік палива.
Рішення було нудним: консолідувати датасет у більші шард-архіви, додати локальний NVMe кеш для тренувань і обмежити конкурентність загрузчиків. Другий GPU не спричинив проблему; він її
просто дуже голосно виявив.
Міні-історія 2: Оптимізація, яка обернулася проти
Інша команда сервувала модель, схожу на LLM, для внутрішніх інструментів. Латентність була критична: інженери використовували її інтерактивно, і все вище кількох секунд відчувалося «зламаним».
У них був один великий GPU — дорогий, але стабільний.
Хтось запропонував розділити модель на два менші GPU за допомогою tensor parallelism. Розрахунки в таблиці виглядали добре: більше сумарної VRAM, дешевше за сервер, «повинно масштабуватися».
Вони побудували це, викотили і спостерігали, як p99 латентність погіршилася, хоча пропускна здатність покращилася в синтетичних тестах.
Корінь проблеми був на критичному шляху: кожен крок генерації токену вимагав між-GPU комунікації. Під реальним трафіком розміри запитів різнилися й батчинг був недосконалий.
Тому вони отримали черги плюс синхронізацію. Система більше часу проводила на координації, ніж на обчисленнях. Гірше того, хвостова латентність зростала, коли один GPU трохи нагрівався і знижував частоту,
бо інший GPU мусив чекати на синхронізаційних точках.
Вони пробували безліч налаштувань: розміри батчів, пріоритети стрімів, прикріплення потоків, регулювання серверу інференсу. Це трохи допомогло, але фундаментальна архітектура була вороже налаштована
до латентності.
Вирішення було контрінтуїтивним, але очевидним заднім числом: повернутися до одного великого GPU для endpointів із вимогою низької латентності, а дво-GPU залишити лише для офлайн-батчів,
де важить пропускна здатність, а хвости не мають значення.
Міні-історія 3: Нудна, але правильна практика, що врятувала день
Команда платформи керувала спільним GPU-кластером для кількох продуктів. Їх дістали таємничі уповільнення і тікети «вчора було швидко». Замість того, щоб ганятися за кожною екзотичною
робочою навичкою, вони впровадили одну практику, що звучить нудно і тому потужна: стандартизували розміщення GPU і документували топологію.
Для кожної моделі сервера вони зробили просту карту: які PCIe слоти відповідають яким NUMA вузлам, які пари GPU мають швидкі P2P шляхи і які BIOS налаштування потрібні для стабільної роботи.
Ці налаштування вони вкинули в процес провізіонінгу. Також додали preflight-тест, який виводив вузол з ротації, якщо P2P несподівано вимкнено.
Через місяці вендор відправив заміну ревізії материнської плати. Все завантажилося. Без тривог. Але мульти-GPU роботи почали масштабуватися погано на підмножині вузлів. Оскільки команда
мала перевірки топології і базові тести пропускної здатності в CI для флоту, вони швидко виявили проблему і ізолювали вузли до того, як клієнти помітили.
Постмортем був коротким. Відповідь — «змінилася маршрутизація апаратури; шлях P2P інший; скоригуйте розміщення і оновіть базу». Нікому не було весело. Ніхто не втратив тиждень.
Ось як виглядає «нудне», коли воно працює.
Швидкий план діагностики
Коли два GPU працюють гірше, не починайте з переписування моделі. Почніть з доведення, куди йде час. Мета — не бути хитрим; мета — бути швидким.
Перш за все: підтвердьте, що проблема реальна (і виміряйте «wall-clock»)
- Порівнюйте час кроку / токени за секунду / запити за секунду, а не «GPU utilization».
- Вимірюйте p50/p95/p99 латентність для інференсу, а не лише середню.
- Тестуйте одно-GPU проти двох GPU з ідентичними версіями ПЗ і тим самим зрізом датасету.
По-друге: визначте клас вузького місця (обчислення, пам’ять, комунікація, CPU, I/O, термальні)
- Якщо GPU зайняті, але масштабування погане: підозрюйте комунікацію і синхронізацію.
- Якщо GPU холостують: підозрюйте вхідний пайплайн, CPU або сховище.
- Якщо продуктивність погіршується з часом: підозрюйте термальний тротлінг, поведінку лімітів енергії або фрагментацію пам’яті/GC.
По-третє: перевірте топологію та припущення про міжз’єднання
- Перевірте швидкість/ширину PCIe і чи увімкнено P2P.
- Перевірте NUMA локальність: потоки CPU, що годують GPU0, зазвичай мають бути на тому самому сокеті, що й GPU0.
- Підтвердіть, що NVLink дійсно присутній і активний (де застосовно).
По-четверте: перевірте нудні системні речі
- Часові частоти і тротлінг (температура, ліміти потужності).
- Помилки драйверів / Xid та скидання.
- Насичення диска й мережі під час чекпоінтів і читання датасетів.
По-п’яте: лише тоді налаштовуйте фреймворк
- NCCL налаштування, розміри DDP bucket-ів, акумуляція градієнтів, змішана точність, опції компіляції.
- Розміри батчів, що тримають GPU ефективними без вибуху комунікацій.
- Перекриття комунікації з обчисленням, коли це підтримується.
Жарт №2: Масштабування мульти-GPU — це коли ви платите за два двигуни і витрачаєте час на налагодження коробки передач.
Практичні завдання: команди, виводи та рішення (12+)
Це не «поради». Це перевірки, які ви запускаєте, коли ви на виклику й хтось клянеться, що другий GPU «нічого не робить».
Кожне завдання включає: команду, що означає її вивід, і яке рішення ви приймаєте далі.
Завдання 1: Підтвердіть, що обидва GPU існують і драйвер їх бачить
cr0x@server:~$ nvidia-smi -L
GPU 0: NVIDIA A10 (UUID: GPU-aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee)
GPU 1: NVIDIA A10 (UUID: GPU-ffffffff-1111-2222-3333-444444444444)
Значення: Якщо GPU відсутній, все інше — шум. Відсутні пристрої можуть бути через живлення, посадку, BIOS або драйвер.
Рішення: Якщо обидва не в списку, зупиніться і виправте апарат/прошивку/драйвер перш ніж налагоджувати програмне масштабування.
Завдання 2: Перевірте швидкість і ширину PCIe (перевірка «чому моя шина повільна?»)
cr0x@server:~$ nvidia-smi -q -d PCI | sed -n '1,120p'
GPU 00000000:65:00.0
PCIe Generation
Current : Gen4
Max : Gen4
Link Width
Current : x8
Max : x16
GPU 00000000:B3:00.0
PCIe Generation
Current : Gen4
Max : Gen4
Link Width
Current : x16
Max : x16
Значення: GPU0 працює на x8, хоч підтримує x16. Це може зменшити пропускання хост↔︎пристрій і вплинути на P2P шляхи.
Рішення: Пересісти GPU, перевірити проводку слотів, налаштування BIOS, райзери і чи інший пристрій не забрав лінії.
Завдання 3: Відобразіть відповідність GPU до NUMA вузлів (щоб уникнути плати за крос-сокет)
cr0x@server:~$ nvidia-smi topo -m
GPU0 GPU1 CPU Affinity NUMA Affinity
GPU0 X SYS 0-31 0
GPU1 SYS X 32-63 1
Значення: GPU0 локальний для NUMA вузла 0; GPU1 локальний для NUMA вузла 1; шлях GPU↔GPU — SYS (через системний/CPU інтерконект).
Рішення: Якщо ваші робочі навантаження сильно синхронізуються між GPU, очікуйте гіршого масштабування. Розгляньте зберігання мульти-GPU ранків на тому самому сокеті або вибір сервера з кращим міжз’єднанням GPU.
Завдання 4: Підтвердіть, що P2P доступ увімкнено (і не вимкнено тихо)
cr0x@server:~$ nvidia-smi topo -p2p n
GPU0 GPU1
GPU0 X OK
GPU1 OK X
Значення: P2P дозволено між GPU. Якщо ви бачите «NS» або «Disabled», ваша комунікація може йти через пам’ять хоста.
Рішення: Якщо P2P не OK, перевірте налаштування IOMMU, режим віртуалізації, BIOS-перемикачі та сумісність драйвера/ядра.
Завдання 5: Перевірте частоти, потужність і терміни (коли продуктивність тане)
cr0x@server:~$ nvidia-smi --query-gpu=index,temperature.gpu,power.draw,power.limit,clocks.sm,clocks.mem,clocks.current.sm --format=csv
index, temperature.gpu, power.draw, power.limit, clocks.sm, clocks.mem, clocks.current.sm
0, 84, 147.23 W, 150.00 W, 1710 MHz, 5001 MHz, 1410 MHz
1, 72, 132.10 W, 150.00 W, 1710 MHz, 5001 MHz, 1680 MHz
Значення: GPU0 близький до термальних лімітів і не утримує цільові SM частоти (current нижче номіналу). Це саме по собі може зламати ефективність синхронізації мульти-GPU.
Рішення: Покращуйте потік повітря, налаштуйте криву вентиляторів, обережно знижуйте ліміт потужності або переставте GPU, щоб уникнути задушення одного іншого.
Завдання 6: Шукайте ECC або помилки пам’яті (перевірка «воно повільне, бо хворе»)
cr0x@server:~$ nvidia-smi -q -d ECC | sed -n '1,120p'
ECC Mode
Current ECC : Enabled
Pending ECC : Enabled
ECC Errors
Volatile
Single Bit
Device Memory : 0
Double Bit
Device Memory : 0
Aggregate
Single Bit
Device Memory : 2
Double Bit
Device Memory : 0
Значення: Є агреговані помилки single-bit. Це може не впасти вас зараз, але корелює з маргінальним обладнанням.
Рішення: Якщо помилки зростають, заплануйте обслуговування і розгляньте виведення GPU з відповідальних за латентність або довгі тренування завдань.
Завдання 7: Перевірте Xid помилки в логах ядра (помилки драйвера/GPU)
cr0x@server:~$ sudo dmesg -T | grep -i -E 'NVRM|Xid' | tail -n 20
[Mon Jan 13 09:41:02 2026] NVRM: Xid (PCI:0000:65:00): 31, Ch 0000000b, engmask 00000101, intr 10000000
[Mon Jan 13 09:41:02 2026] NVRM: GPU 0000:65:00.0: GPU has fallen off the bus.
Значення: «Fallen off the bus» — не налаштування продуктивності. Це стабільність: подача живлення, цілісність PCIe, перегрів або відмова апаратури.
Рішення: Припиніть гнатися за продуктивністю. Стабілізуйте вузол: пересадіть плату, поміняйте кабелі, перевірте PSU, оновіть прошивки і розгляньте RMA.
Завдання 8: Підтвердіть навантаження CPU і пам’яті (загрузчики даних і накладні витрати запуску)
cr0x@server:~$ mpstat -P ALL 1 3
Linux 6.5.0 (server) 01/13/2026 _x86_64_ (64 CPU)
09:52:11 AM CPU %usr %nice %sys %iowait %irq %soft %idle
09:52:12 AM all 68.20 0.00 14.10 0.40 0.00 1.20 16.10
09:52:12 AM 0 98.00 0.00 2.00 0.00 0.00 0.00 0.00
09:52:12 AM 32 96.00 0.00 4.00 0.00 0.00 0.00 0.00
Значення: Деякі CPU насичені і запіненені (ймовірно загрузчики даних або потоки фреймворку). Саме тут часто починається голодування GPU.
Рішення: Підвищуйте ефективність загрузчиків, використовуйте pinned memory розумно, налаштуйте кількість worker-ів і прив’язуйте процеси до правильного NUMA вузла.
Завдання 9: Перевірте пропускну здатність диска і iowait під час тренування
cr0x@server:~$ iostat -xz 1 3
Linux 6.5.0 (server) 01/13/2026 _x86_64_ (64 CPU)
avg-cpu: %user %nice %system %iowait %steal %idle
42.11 0.00 9.33 18.70 0.00 29.86
Device r/s rkB/s rrqm/s %rrqm r_await rareq-sz w/s wkB/s w_await aqu-sz %util
nvme0n1 320.0 86500.0 10.0 3.03 5.10 270.3 55.0 22000.0 7.80 2.10 92.0
Значення: Високий iowait і NVMe ~92% завантаження вказують, що сховище — лімітатор. Два GPU просто зробили чергу глибшою.
Рішення: Перемістіть датасет локально, префетчте, шардуйте, кешуйте або збільшіть пропускну здатність сховища перед додаванням GPU.
Завдання 10: Перевірте мережеву пропускну здатність, якщо датасет або чекпоінти віддалені
cr0x@server:~$ sar -n DEV 1 3
Linux 6.5.0 (server) 01/13/2026 _x86_64_ (64 CPU)
09:55:21 AM IFACE rxpck/s txpck/s rxkB/s txkB/s rxcmp/s txcmp/s rxmcst/s
09:55:22 AM eth0 6200.00 5800.00 930000.00 210000.00 0.00 0.00 12.00
Значення: RX близько до лайн-рейту на 10Gb/25Gb лінку може бути вашим потолком. Якщо ваша робота читає дані віддалено, це жорсткий ліміт.
Рішення: Кешуйте локально, стискайте і шардуйте розумніше або апгрейдьте мережевий/сховищний шлях перед очікуванням виграшу від мульти-GPU.
Завдання 11: Перевірте відповідність процес→GPU (можливо ви використовуєте один GPU двічі)
cr0x@server:~$ nvidia-smi pmon -c 1
# gpu pid type sm mem enc dec command
# Idx # C/G % % % % name
0 24819 C 72 61 0 0 python
0 24820 C 69 58 0 0 python
1 - - - - - - -
Значення: Два процеси працюють на GPU0; GPU1 не використовується. Це поширено коли CUDA_VISIBLE_DEVICES неправильно встановлено або лаунчер налаштований не так.
Рішення: Виправте команду запуску, середовище або призначення GPU від планувальника. Не налаштовуйте NCCL, поки не задієте другий GPU.
Завдання 12: Перевірте уявлення топології у NCCL (коли проблема в комунікації)
cr0x@server:~$ NCCL_DEBUG=INFO NCCL_TOPO_DUMP_FILE=/tmp/nccl-topo.xml python -c "import torch; import torch.distributed as dist; print('ok')"
NCCL INFO NET/Plugin: No plugin found (libnccl-net.so), using internal implementation
NCCL INFO CUDA Dev 0 [0] PCIe/Gen4 x8
NCCL INFO CUDA Dev 1 [1] PCIe/Gen4 x16
NCCL INFO Topo detection done
ok
Значення: NCCL повідомляє ширини лінків і записав дамп топології, який можна дослідити офлайн. x8 лінк — ясно виразний «димовий сигнал».
Рішення: Виправте проблеми з PCIe лінком спочатку; потім знову проганяйте тести масштабування. Ніяке налаштування bucket-ів не вирішить відсутні лінії.
Завдання 13: Перевірте використання пам’яті GPU і тиск фрагментації
cr0x@server:~$ nvidia-smi --query-gpu=index,memory.total,memory.used,memory.free --format=csv
index, memory.total, memory.used, memory.free
0, 24564 MiB, 23890 MiB, 674 MiB
1, 24564 MiB, 1200 MiB, 23364 MiB
Значення: GPU0 майже на OOM, тоді як GPU1 майже порожній. Це вказує на дисбаланс: неправильне призначення пристроїв, модель не шардиться або невідповідність ранків.
Рішення: Виправте призначення пристроїв; перевірте, що кожен ранк використовує свій GPU; розгляньте шардінг, якщо мета — ємність моделі.
Завдання 14: Підтвердіть NUMA локальність для процесу (щоб зупинити віддалений трафік пам’яті)
cr0x@server:~$ numactl --show
policy: default
preferred node: current
physcpubind: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
membind: 0
Значення: Процес прив’язаний до CPU 0–15 і вузла пам’яті 0. Якщо цей ранк керує GPU1 на NUMA вузлі 1, ви платите за віддалений доступ до пам’яті.
Рішення: Закріпіть кожен ранк до сокета, локального для його GPU (або принаймні уникайте крос-сокетного доступу до пам’яті).
Типові помилки: симптом → корінь → виправлення
1) Симптом: Завантаження GPU «високе», але wall-clock гірший
- Корінь: Накладні витрати синхронізації (all-reduce) домінують; utilization враховує час, проведений у блокуванні в комунікаціях або на бар’єрах.
- Виправлення: Збільште батч на GPU (або використайте gradient accumulation), налаштуйте розміри bucket-ів, перекривайте комунікації з обчисленням і підтвердіть P2P/NVLink/топологію.
2) Симптом: Один GPU зайнятий, інший майже простий
- Корінь: Неправильне призначення пристрою (CUDA_VISIBLE_DEVICES, лаунчер, планувальник) або збій ранку, що залишив один процес працювати наодинці.
- Виправлення: Підтвердіть відображення за допомогою
nvidia-smi pmon; зафіксуйте відповідність ранк→пристрій; робіть fast-fail, якщо будь-який ранк виходить.
3) Симптом: Масштабування спочатку нормальне, потім деградує з часом
- Корінь: Термальний тротлінг або поведінка лімітів потужності; іноді фрагментація пам’яті і поведінка аллокатора.
- Виправлення: Моніторьте температури/частоти; покращуйте потік повітря; стандартизовуйте ліміти живлення і налаштування BIOS; зменшуйте пікові сплески при потребі.
4) Симптом: Тренування стає нестабільним — зависання, дедлоки, «NCCL timeout»
- Корінь: Один ранк отримує виняток/OOM і виходить; інші чекають у колективах вічно. Іноді мережевий джиттер або P2P збої додають.
- Виправлення: Увімкніть надійну обробку помилок і таймаути; забезпечте одночасний abort для всіх ранків; збирайте логи по ранках; спростіть топологію.
5) Симптом: Ви додали GPU, щоб вмістити більшу модель, а вона все одно OOM
- Корінь: Data-parallel не об’єднує VRAM; повна модель все ще має вміститися на кожному GPU.
- Виправлення: Використайте шардінг моделі (tensor/pipeline/expert parallel), activation checkpointing, квантизацію або купіть більший одиночний GPU.
6) Симптом: Пропускна здатність інференсу покращується, але p95/p99 латентність гірша
- Корінь: Між-GPU комунікація на критичному шляху; батчинг/черги посилюють джиттер; точки синхронізації створюють хвости.
- Виправлення: Тримайте latency-sensitive endpoint на одному GPU; резервуйте мульти-GPU для батчових/офлайн задач; або переробіть батчинг і маршрутизацію запитів.
7) Симптом: Та сама модель, той самий код, але продуктивність відрізняється на здавалось би однакових серверах
- Корінь: Відмінності в топології PCIe, BIOS за замовчуванням, проблеми переговорів ліній (x8 vs x16) або P2P вимкнено на деяких вузлах.
- Виправлення: Базуйте і застосовуйте перевірки топології під час провізіонінгу; ізолюйте вузли, що не відповідають очікуванням; стандартизовуйте прошивки.
8) Симптом: Файлова система і мережа «рандомно» уповільнюються під час тренування
- Корінь: Широке розгалуження загрузчиків і сплески чекпоінтів; тиск метаданих від дрібних файлів; конкуренція за спільне сховище.
- Виправлення: Шардуйте й кешуйте датасети; зменшіть кількість дрібних файлів; рознесіть чекпоінти; обмежте робітників; виведіть важкий I/O з спільних шляхів.
Чеклісти / покроковий план
Чекліст рішення: купувати другий GPU чи більший одиночний GPU?
- Якщо вам потрібна більша VRAM для однієї моделі, віддавайте перевагу одному більшому GPU, якщо ви не готові впроваджувати і підтримувати model parallelism.
- Якщо вам потрібна більша пропускна здатність для багатьох незалежних задач, два GPU часто відмінні — запускайте два окремі процеси, уникайте синхронізації.
- Якщо вам потрібна нижча латентність, краще один GPU на шлях запиту. Мульти-GPU — це проблема координації.
- Якщо ваша платформа обмежена I/O, не додавайте GPU. Виправте сховище/мережу спочатку, інакше ви просто створите дороге холосте очікування.
- Якщо ваші сервери двосокетні, перевірте топологію перед покупкою; «два GPU» може означати «SYS шлях назавжди».
Покроково: як зробити два GPU не жахливими для тренування
- Базуйте на одно-GPU: виміряйте час кроку, пропускну здатність і частоти GPU у стабільному стані.
- Перевірте шляхи апаратури: PCIe x16 де очікується; P2P OK; NUMA афініті відомі.
- Виправте пайплайн даних: локальний кеш, шардені датасети, розумні worker-и, уникайте дрібних файлів.
- Масштабуйте батч відповідально: збільшуйте глобальний батч лише якщо це не шкодить збіжності; інакше використайте gradient accumulation.
- Зменшіть накладні комунікації: зливайте маленькі тензори коли можливо; налаштуйте DDP bucket-и; перекривайте комунікації з обчисленням.
- Стабілізуйте терміни: сталі ліміти потужності і потік повітря; перевірте, що частоти не падають через 10 хвилин.
- Оперціоналізуйте: таймаути, збір логів по ранках, health-checks для P2P і ширини PCIe лінку.
Покроково: використовувати два GPU ефективно (патерн «окремі задачі»)
- Запускайте незалежні процеси, прикріплені по одному GPU кожний (без колективів).
- Прив’язуйте CPU-ядра і пам’ять на процес до NUMA вузла GPU.
- Обмежуйте запис чекпоінтів, щоб обидва процеси не створювали одночасні I/O сплески.
- Моніторте пропускну здатність по задачах і частоти по пристроям; забезпечуйте термальний запас.
Питання й відповіді
1) Чи бувають два GPU кращими за один?
Так — часто. Це краще, коли ви можете запускати два незалежні навантаження, або коли ваша стратегія model parallel зріла і міжз’єднання/топологія це підтримують.
Це гірше, коли вас змушують часті синхронізації або коли пайплайн обмежений I/O чи CPU.
2) Чому VRAM не додається автоматично між GPU?
Бо кожен GPU — окремий домен пам’яті. Більшість режимів тренування за замовчуванням реплікують параметри на кожному пристрої. Пулінг пам’яті вимагає явного шардінгу і міжз’єднань,
що змінює модель виконання і режими відмов.
3) Якщо у мене є NVLink, чи все одно будуть проблеми мульти-GPU?
NVLink допомагає з пропускною здатністю і затримкою між GPU, але не виправляє вузькі місця CPU, сховища, неправильні розміри батчів, термальний тротлінг або крихкі програмні шляхи.
Воно зменшує один податок; не скасовує їх усіх.
4) Чому мій другий GPU недовантажений у PyTorch?
Поширені причини: неправильний лаунчер (не створює ранків), CUDA_VISIBLE_DEVICES неправильно встановлено, прив’язка процесів до одного GPU, або збій одного ранку.
Перевірте за допомогою nvidia-smi pmon і переконайтеся, що кожен ранк обирає унікальний пристрій.
5) Чи можуть два GPU зробити гру плавнішою?
Історично мульти-GPU підвищував середній FPS, але погіршував pacing кадрів (мікростатер). Сучасна підтримка обмежена і часто не вартує клопоту.
Один потужніший GPU зазвичай правильне рішення для стабільних часів кадрів.
6) Чому мульти-GPU інференс так сильно б’є по латентності?
Бо комунікація між GPU стає частиною критичного шляху кожного запиту. Будь-який джиттер — черга, термальний дрейф, планування ОС — перетворюється на хвостову латентність.
Пропускна здатність може зростати, а p99 погіршується. У продакшні помічають саме p99.
7) Який найпоширеніший прихований вузький горлік при додаванні GPU?
Вхідний пайплайн: сховище і CPU. Два GPU можуть витягувати дані швидше, ніж ваша файлова система, об’єктне сховище або препроцесинг можуть надати. GPU тоді «ефективно чекають».
8) Як я зрозумію, що я обмежений PCIe?
Симптоми включають погане масштабування незважаючи на високу обчислювальну здатність, часті хост↔пристрій передачі і топологію зі шляхами SYS або зменшеною шириною лінку.
Перевірте nvidia-smi -q -d PCI за поколінням і шириною, а також підтвердіть стан P2P через nvidia-smi topo.
9) Чи треба вмикати всі NCCL-ручки, що знайду?
Ні. Спочатку підтвердіть топологію, P2P, ширину PCIe і розміщення NUMA. Потім налаштовуйте. Якщо фізична проводка неправильна, NCCL налаштування — просто різні способи бути повільним.
10) Якщо я вже купив два GPU, як краще їх використовувати?
Якщо ви не готові до model parallel, найвищий ROI часто — запуск двох незалежних задач по одному GPU на кожну, замість примусового синхронного тренування або розділеного інференсу.
Наступні кроки, які ви справді можете зробити
Якщо ваш дво-GPU сетап працює гірше, ставтеся до цього як до SRE-інциденту: визначте обмежувальний ресурс, підтвердіть припущення і лише потім змінюйте архітектуру.
Ось практична послідовність, що працює частіше, ніж має на це право:
- Виміряйте те, що вам важливо: час кроку, пропускну здатність і хвостову латентність — виберіть одне й оптимізуйте для нього.
- Доведіть топологію: швидкість/ширина PCIe, P2P увімкнено, NUMA афініті коректне.
- Стабілізуйте частоти: ліміти потужності, терміни і будь-які ознаки тротлінгу або Xid помилок.
- Виправте «корм»: сховище, мережа, CPU препроцесинг, шардинг, кешування, сплески чекпоінтів.
- Виберіть правильну стратегію мульти-GPU: незалежні задачі, data parallel або справжній model parallel — не прикидайте, ніби вони взаємозамінні.
Якщо ви купуєте залізо: для більшості команд найменш ризикований шлях по ефективності на інженерний час — один більший GPU замість двох менших, якщо лише ваше навантаження
природно не ділиться на незалежні задачі. У таблиці рідко присутній пункт «налагодження розподіленого зависання о 3 ранку». Розклад цього не враховує.