Ви вимикаєте VM. GPU мав би повернутися на хост як добре натренований бумеранг. Натомість він повертається… неправильно.
Наступний запуск VM: чорний екран. dmesg хоста: «скидання не вдалося». Ваш кластерний автоскейлер байдуже планує роботу на цей труп.
Якщо вам казали «увімкніть IOMMU і буде добре», вам продали заспокійливу напівправду. IOMMU забезпечує ізоляцію.
Він не гарантує скидання, повторну ініціалізацію або те, що пристрій взагалі повернеться з того стану, в який потрапив під навантаженням.
Це екосистема багу скидання GPU: частково особливості кремнію, частково нюанси специфікації PCIe, частково реальність драйвера і частково біль оператора.
Що мають на увазі під «багом скидання GPU»
«Баг скидання GPU» — це не один баг. Це загальна назва для будь-якої ситуації, коли GPU не можна надійно скинути і повторно використати
без перезавантаження хоста (або фізичного відключення живлення). Він найчастіше проявляється в таких сценаріях:
- VFIO-прохід GPU (KVM/QEMU/libvirt), коли GPU прив’язують до VM, потім відв’язують і знову прив’язують.
- Контейнеризовані GPU-навантаження, коли драйвер хоста намагається відновитися після зависання ядра або некоректного DMA.
- Багатокористувацькі вузли з GPU з MIG/SR-IOV/vGPU, де семантика скидання відрізняється в залежності від режиму і прошивки.
- Шторми AER PCIe, фліпання лінку або GPU, що переходить у низькопотенційний стан і не повертається коректно.
Основна проблема проста: GPU — це не чемна мережева карта PCIe. Це складний SoC з кількома внутрішніми рушіями
(графіка, обчислення, копіювання, відео, дисплей), власною прошивкою і агресивним керуванням живленням. Коли ви «скидаєте PCIe-пристрій»,
ви не обов’язково скидаєте весь цей внутрішній стан — або робите це в неправильний момент, залишаючи пристрій
напівживим у стані, який плутає драйвер при наступній прив’язці.
Жарт №1: GPU не «падають», вони входять у стан роздумів, де переглядають свої стосунки з вашим драйвером.
Цікаві факти та історичний контекст (коротко, по суті)
- PCIe FLR (Function Level Reset) з’явився, щоб стандартизувати скидання на рівні функції, але багато ранніх реалізацій були частковими або дивними.
- Споживчі GPU оптимізувалися під один OS-інстанс на завантаження, задовго до того, як віртуалізація вимагала «постійного від’єднання/під’єднання».
- Позначка AMD «reset bug» з’явилася у спільноті VFIO, тому що деяким моделям потрібне було повне скидання шини або цикл живлення для відновлення.
- Процес збереження стану NVIDIA мав сенс для HPC-продуктивності, але ускладнює поведінку при «розриві і повторному зв’язуванні», коли ви очікуєте чистого скидання.
- IOMMU спочатку створювався для трансляції DMA і захисту, а не як менеджер життєвого циклу пристрою.
- Режими живлення PCIe як D3hot/D3cold можуть ламати повторну ініціалізацію, коли прошивка/BIOS і ОС не погоджуються, хто відповідає за пробудження.
- ACS (Access Control Services) стали важливими, тому що споживчі платформи часто групують кілька пристроїв разом, блокуючи безпечний passthrough.
- AER (Advanced Error Reporting) може бути порятунком для діагностики, але також може залити логи і погіршити стабільність вузла, коли пристрій некоректний.
Неприємний висновок: «скидання» — це не однорідне поняття. Це переговори між прошивкою платформи, топологією PCIe,
можливістю пристрою і поведінкою драйвера. І GPU — найпереговорливіші пристрої, які ви можете хостити.
Чому ізоляція IOMMU не гарантує відновлюваності
IOMMU — це обмежувальний бар’єр. Він відображає DMA-адреси пристрою у домен трансляції, щоб пристрої не могли писати у довільну
фізичну пам’ять. Це важливо для безпеки та стабільності. Він також дозволяє VFIO безпечно передавати пристрій гостьовій ОС.
Але IOMMU не:
- гарантує, що пристрій можна повернути у чистий стан при відв’язуванні
- змушує пристрій коректно виконувати FLR
- скидає внутрішній стан прошивки, мікроконтролерів або лінії живлення
- виправляє зламану топологію PCIe, де GPU ділить домен скидання з іншими пристроями
- не захищає від очікувань постачальника драйвера щодо порядку ініціалізації
В термінах продакшну: IOMMU зупиняє GPU, що втікає, від DMA-атак на ваш хост. Він не зупиняє GPU від того, щоб бути впертим при відновленні,
який відмовляється перезавантажитися, поки хтось не відключить живлення.
Два рівні ізоляції, які не слід плутати
Оператори плутають їх, бо вони виглядають поруч на діаграмах:
- Ізоляція DMA (IOMMU): «Чи може цей пристрій звертатися лише до дозволеної пам’яті?»
- Ізоляція життєвого циклу (reset domain): «Чи можна цей пристрій незалежно скинути і повторно ініціалізувати?»
Багато платформ дають вам перший, але тихо провалюються в другому. Ось де живе «IOMMU недостатньо».
Домени скидання: прихована залежність
GPU стоїть за root port, можливо за switch, іноді за PLX-чіпом, іноді ділить лінії з іншими пристроями.
Навіть якщо GPU у власній групі IOMMU, він може ділити лінію скидання або домен живлення з чимось іншим.
Коли ви робите bus reset, ви можете скинути сусідів. Коли ви робите FLR, GPU може його ігнорувати.
Коли ви нічого не робите, драйвер намагається «м’яко скинути» внутрішні рушії і іноді програє.
Якщо ви працюєте з багатокористувацькими навантаженнями, ставте «незалежне скидання» як вимогу при закупівлі, а не як побічну думку.
Тут нудні апаратні вибори платформи перемагають хитрі прапори ядра.
Цитата (парафразована ідея)
Парафразована ідея: надія — не стратегія — проектуйте системи так, щоб відмови були очікуваними, а відновлення — рутинним.
— Джин Кранц (оперативний керівник, програма «Аполлон»)
Механізми скидання PCIe: FLR, bus reset, hot reset і чому GPU особливі
Function Level Reset (FLR)
FLR — це концептуально найчистіше: скинути лише одну PCIe-функцію (наприклад 0000:65:00.0), не ламаючи всю шину.
ОС може запитати це через sysfs, і VFIO використовує це, коли доступно.
Реальність: деякі GPU реалізують FLR так, що скидається конфігураційний простір, але не внутрішній стан прошивки, який вам справді важливий.
Або FLR працює лише коли пристрій у певному стані живлення. Або «працює», але рушії застрягають.
Bus reset / secondary bus reset
Це скидає сегмент шини, що нижчий по ієрархії. Більш жорсткий метод, ніж FLR. Більше побічних ефектів теж.
Якщо ваш GPU стоїть за PCIe-бріджем або switch’ом, bus reset іноді може змусити його поводитися правильно.
Підводний камінь очевидний: ви можете скинути інші кінцеві точки за тим же бриджем. Якщо вам пощастить, це нічого важливого.
Якщо ні — ви щойно перезавантажили свій HBA сховища посеред піку I/O. Удачі з поясненням такого графіка фінансу.
Hot reset
Hot reset ближчий до «імітації відключення/підключення на рівні лінку». Він може спрацювати, коли FLR не допомагає.
Він також може зазнати невдачі, якщо платформа не може коректно перевчити лінк або якщо прошивка пристрою застрягає під час тренування лінку.
Фундаментальне скидання / цикл живлення
Ядерна опція. Якщо GPU не оживає без відключення живлення, це вже не програмна проблема скидання.
Це проблема життєвого циклу платформи. У датацентрі це вирішують так:
- вузли з BMC-контрольованим живленням слотів PCIe (рідко, але золото)
- GPU-партіції, що переносять перезавантаження вузла
- підтримка перезапуску робочих навантажень і проєктування розкладу навколо відновлення
Чому GPU особливі (і дратівливі)
GPU містять кілька внутрішніх «субпристроїв» за однією PCIe-функцією: рушії копіювання, контролери пам’яті, відео-рушії,
дисплей-рушії, процесори безпеки і велику частину прошивки, яка ініціалізує все. Скидання, що не реініціалізує прошивку і стан контролера пам’яті, — це скидання лише за назвою.
Додайте управління живленням: GPU агресивно переходять у низькопотенційні стани в прості. Якщо ви відв’язуєте GPU під час входу
в глибокий стан живлення (або коли активний runtime PM), ви можете отримати пристрій, який перераховується, але не відповідає коректно.
Сумні сценарії відмов, які ви побачите в продакшні
1) «Скидання не вдалося» після вимкнення VM; наступне приєднання зависає
Класичний симптом VFIO: VM працює нормально. Ви її вимикаєте. Відв’язуєте GPU. Заново прив’язуєте до іншої VM. Libvirt каже, що все гаразд.
Гість завантажується до чорного консолі. Логи хоста показують невдале скидання, або драйвер відмовляється прив’язуватися.
2) GPU застряг у D3cold (або перемикається між станами живлення)
Пристрій присутній у lspci, але не ініціалізується. Іноді в логах ядра з’являється «не вдалося змінити стан живлення».
Часто це взаємодія з runtime power management: ядро намагається призупинити пристрій, потім ви намагаєтесь його скинути — і виходить безлад.
3) AER-спам, скидання лінку і «заморожені» вузли
GPU починає генерувати коректовані/нефатальні помилки PCIe. AER заливає dmesg. CPU витрачає час на обробку перервань.
Навіть якщо навантаження тривають, латентність вузла стає недовіреною.
4) Драйвер вважає GPU зайнятим вічно
Драйвер ядра намагається загасити пристрій, але внутрішні рушії застрягають. Він чекає сигналів з fence, які ніколи не приходять.
Ви намагаєтеся вивантажити модуль — і він блокується. Це не «аморальний баг драйвера»; драйвер робить єдину безпечну річ:
відмовляється вдавати, що апарат у порядку.
5) Сюрпризи мультифункцій: аудіо-функція, контролер USB-C тощо
Багато GPU експонують кілька функцій (графіка + HDMI audio + USB-контролер для VirtualLink/USB-C).
Скидання однієї функції без інших (або непослідовне прив’язування) може залишити пристрій у неконсистентному стані.
6) «Працює вранці» — збої пізніше
Під легким тестовим навантаженням усе скидається чисто. Під тривалими обчисленнями плюс частими циклами прив’язки/відв’язки скидання деградують.
Це часто трапляється, коли прошивка заходить у менш протестований стан після довгого часу роботи, або коли пам’ять GPU інтенсивно використовується і шляхи завершення не ідеальні.
Швидкий план діагностики
Це версія, яку ви запускаєте, коли дзвонить сторож і ви не хочете ставати PCIe-археологом.
Мета: визначити, чи у вас проблема з можливістю скидання, керуванням живлення,
прив’язкою драйвера або топологією/доменом скидання.
Перше: підтвердьте, що саме впало — скидання, прив’язка чи лінк
- Перевірте
dmesgна наявність «скидання не вдалося», «AER», «link down», «device not ready». - Перевірте в sysfs доступні методи скидання для PCIe-функції.
- Перевірте, чи пристрій у D3cold/D3hot.
Друге: валідуйте ризики топології і домену скидання
- Знайдіть upstream bridge/root port і подивіться, що ще за ним ділить шлях.
- Підтвердіть членство в IOMMU group, але на цьому не зупиняйтесь.
- Шукайте PCIe switch/bridge, який може бути реальним об’єктом скидання.
Третє: оберіть найменш руйнівну дію з відновлення
- Спробуйте function reset (FLR), якщо доступно.
- Спробуйте цикл unbind/bind (якщо драйвер підтримує чисту реініціалізацію).
- Спробуйте hot reset або secondary bus reset, якщо GPU ізольований за власним bridge/switch.
- Якщо помилки тривають або починаються шторми AER: злити вузол (drain), перезавантажити хост.
Якщо ви не можете відновити без перезавантаження частіше, ніж іноді, перестаньте вважати це «помилкою оператора».
Це архітектурне обмеження. Будуйте планування та обслуговування навколо цього.
Практичні завдання: команди, виводи, рішення (12+)
Усі приклади припускають хост Linux з root-доступом і GPU за адресою 0000:65:00.0.
Замініть адреси і назви драйверів відповідно.
Завдання 1: Ідентифікуйте GPU і його функції (чи бракує аудіо/USB-функції?)
cr0x@server:~$ lspci -nn | egrep -i 'vga|3d|nvidia|amd|audio|usb'
65:00.0 VGA compatible controller [0300]: NVIDIA Corporation Device [10de:2231] (rev a1)
65:00.1 Audio device [0403]: NVIDIA Corporation Device [10de:1aef] (rev a1)
Що це означає: Ваш «GPU» — це принаймні дві функції. Плани passthrough/скидання мають враховувати обидві.
Рішення: Якщо ви пробросуєте 65:00.0, також подумайте про 65:00.1, щоб зберегти консистентність пристрою, або явним чином прив’яжіть її до безпечного драйвера.
Завдання 2: Перевірте, чи IOMMU справді ввімкнений (не припускайте)
cr0x@server:~$ dmesg | egrep -i 'iommu|dmarmr|intel-iommu|amd-vi' | head
[ 0.912345] DMAR: IOMMU enabled
[ 0.912678] DMAR: Host address width 46
Що це означає: Ядро вважає, що IOMMU увімкнений.
Рішення: Якщо ви цього не бачите, виправте параметри завантаження/BIOS; стабільність VFIO без IOMMU — фантазія.
Завдання 3: Перевірте членство в IOMMU group (необхідно, але не достатньо)
cr0x@server:~$ gpu=0000:65:00.0; group=$(readlink /sys/bus/pci/devices/$gpu/iommu_group); echo $group; ls -l $group/devices
../../kernel/iommu_groups/42
total 0
lrwxrwxrwx 1 root root 0 Feb 4 10:01 0000:65:00.0 -> ../../../../devices/pci0000:60/0000:60:01.0/0000:65:00.0
lrwxrwxrwx 1 root root 0 Feb 4 10:01 0000:65:00.1 -> ../../../../devices/pci0000:60/0000:60:01.0/0000:65:00.1
Що це означає: Функції GPU ділять ту саму IOMMU group, що нормально.
Рішення: Якщо в групі є несуміжні пристрої, ви не зможете безпечно пробросити їх без змін платформи (або приймаючи ризик).
Завдання 4: Знайдіть upstream bridge/root port (підказка домену скидання)
cr0x@server:~$ gpu=0000:65:00.0; echo "GPU path:"; readlink -f /sys/bus/pci/devices/$gpu
GPU path:
/sys/devices/pci0000:60/0000:60:01.0/0000:65:00.0
Що це означає: Upstream порт — 0000:60:01.0.
Рішення: Перевірте, що ще знаходиться за 60:01.0. Якщо це спільний switch, bus reset може спричинити побічні ефекти.
Завдання 5: Перерахуйте все, що за тим же upstream портом
cr0x@server:~$ upstream=0000:60:01.0; find /sys/bus/pci/devices/$upstream/ -maxdepth 2 -name '0000:*' -printf '%f\n'
0000:65:00.0
0000:65:00.1
Що це означає: За цим портом знаходяться лише функції GPU.
Рішення: Bus reset на downstream-сегменті ймовірно безпечний (але все одно перевірте відсутність прихованого switch з іншими портами).
Завдання 6: Перевірте, чи ядро вважає FLR доступним
cr0x@server:~$ gpu=0000:65:00.0; lspci -s ${gpu#0000:} -vv | egrep -i 'Capabilities:.*FLR|Reset'
Capabilities: [1b0] Vendor Specific Information: Len=14
Що це означає: Цей вивід не доводить підтримку FLR; деякі пристрої не рекламують його чисто для grep.
Рішення: Користуйтеся sysfs далі; не покладайтеся на маркетингові списки можливостей.
Завдання 7: Спробуйте function reset через sysfs (найменш руйнівний)
cr0x@server:~$ gpu=0000:65:00.0; sudo sh -c "echo 1 > /sys/bus/pci/devices/$gpu/reset"
sh: 1: cannot create /sys/bus/pci/devices/0000:65:00.0/reset: Permission denied
Що це означає: Ви забули про root (або редирект shell не мав привілеїв).
Рішення: Використайте root shell або sudo tee для запису у sysfs.
cr0x@server:~$ gpu=0000:65:00.0; echo 1 | sudo tee /sys/bus/pci/devices/$gpu/reset
1
Що це означає: Ядро прийняло запит на скидання.
Рішення: Негайно перевірте dmesg на успіх/невдачу; прийняття не означає завершення.
Завдання 8: Підтвердьте результат скидання в dmesg (успіх vs «скидання не вдалося»)
cr0x@server:~$ dmesg -T | tail -n 20
[Sun Feb 4 10:05:01 2026] pci 0000:65:00.0: resetting
[Sun Feb 4 10:05:02 2026] pci 0000:65:00.0: reset failed
Що це означає: Платформа/пристрій не змогли завершити запитаний шлях скидання.
Рішення: Переходьте до hot reset / bus reset лише якщо GPU ізольований за власним bridge; інакше злити вузол і перезавантажити.
Завдання 9: Перевірте стан живлення (D0 vs D3), щоб виявити runtime PM пастки
cr0x@server:~$ gpu=0000:65:00.0; cat /sys/bus/pci/devices/$gpu/power_state
D3cold
Що це означає: Пристрій у глибокому вимкненні.
Рішення: Розгляньте відключення runtime PM для пристрою або забезпечте, щоб він був у D0 перед відв’язкою/скиданням.
Завдання 10: Тимчасово вимкніть runtime PM для GPU (тестова зміна)
cr0x@server:~$ gpu=0000:65:00.0; echo on | sudo tee /sys/bus/pci/devices/$gpu/power/control
on
Що це означає: Runtime PM примусово встановлено на «on» (без autosuspend) для цієї функції.
Рішення: Повторіть тести відв’язки/прив’язки. Якщо стабільність покращиться, зробіть це постійно через udev-правило або systemd unit (обережно).
Завдання 11: Відв’яжіть від поточного драйвера (підготовка до перев’язки або VFIO)
cr0x@server:~$ gpu=0000:65:00.0; readlink /sys/bus/pci/devices/$gpu/driver
../../../../bus/pci/drivers/nvidia
cr0x@server:~$ gpu=0000:65:00.0; echo $gpu | sudo tee /sys/bus/pci/drivers/nvidia/unbind
0000:65:00.0
Що це означає: Пристрій від’єднано від драйвера nvidia.
Рішення: Якщо unbind блокується або дає помилки, драйвер може очікувати на апарат; злити вузол і перезавантажити часто — єдиний чистий вихід.
Завдання 12: Прив’яжіть до vfio-pci (для passthrough) і перевірте прив’язку
cr0x@server:~$ gpu=0000:65:00.0; sudo modprobe vfio-pci
cr0x@server:~$ gpu=0000:65:00.0; vendor=$(cat /sys/bus/pci/devices/$gpu/vendor); device=$(cat /sys/bus/pci/devices/$gpu/device); echo $vendor $device
0x10de 0x2231
cr0x@server:~$ echo 10de 2231 | sudo tee /sys/bus/pci/drivers/vfio-pci/new_id
10de 2231
cr0x@server:~$ gpu=0000:65:00.0; readlink /sys/bus/pci/devices/$gpu/driver
../../../../bus/pci/drivers/vfio-pci
Що це означає: vfio-pci тепер володіє пристроєм.
Рішення: Якщо прив’язка не вдається або повертається назад, у вас є конкуренти-драйвери (initramfs, udev-правила або Xorg), що претендують на GPU.
Завдання 13: Перевірте на AER-помилки, що передбачають майбутні невдачі скидання
cr0x@server:~$ dmesg -T | egrep -i 'AER|pcieport|error' | tail -n 15
[Sun Feb 4 10:06:10 2026] pcieport 0000:60:01.0: AER: Corrected error received: 0000:60:01.0
[Sun Feb 4 10:06:10 2026] pcieport 0000:60:01.0: AER: PCIe Bus Error: severity=Corrected, type=Physical Layer
Що це означає: Існують проблеми на рівні лінку, навіть якщо GPU «працює».
Рішення: Трактуйте постійний AER як апаратну/платформну проблему: перевірте посадку, riser’и, кабелі (для зовнішнього PCIe), налаштування BIOS або замініть вузол.
Завдання 14: Перевірте швидкість/ширину лінку (деградовані лінки корелюють із дивними скиданнями)
cr0x@server:~$ gpu=0000:65:00.0; sudo lspci -s ${gpu#0000:} -vv | egrep -i 'LnkSta:|LnkCap:'
LnkCap: Port #0, Speed 16GT/s, Width x16
LnkSta: Speed 8GT/s (downgraded), Width x8 (downgraded)
Що це означає: Ваш GPU працює на деградованому лінку.
Рішення: Спочатку вирішіть фізичні/топологічні проблеми. Дебаг скидання на деградованому лінку — все одно, що дебаг сховища на помираючому SATA-кабелі: ви нічого корисного не дізнаєтесь.
Завдання 15: Спробуйте зробити downstream bus reset лише якщо топологія безпечна
cr0x@server:~$ upstream=0000:60:01.0; echo 1 | sudo tee /sys/bus/pci/devices/$upstream/reset
1
Що це означає: Ви запросили скидання upstream-порту/бріджа, що може скинути downstream-сегмент.
Рішення: Якщо інші пристрої ділять цей сегмент, не робіть цього на живому вузлі. Якщо GPU ізольований, це може відновити «завислий» пристрій.
Завдання 16: Перевірте, чи пристрій відгукується після скидання (швидкий індикатор здоров’я)
cr0x@server:~$ gpu=0000:65:00.0; lspci -s ${gpu#0000:} -nn
65:00.0 VGA compatible controller [0300]: NVIDIA Corporation Device [10de:2231] (rev a1)
Що це означає: Пристрій все ще перераховується, що є мінімально необхідною ознакою.
Рішення: Якщо він зникає повністю, ви маєте справу з тренуванням лінку/доменом живлення; плануйте перезавантаження хоста і розслідування платформи/прошивки.
Що працює: стратегії пом’якшення, що витримують реальні навантаження
1) Віддавайте перевагу GPU і платформам з перевіреною поведінкою скидання
Це не філософія. Це операційне питання. Якщо вам потрібні часті переназначення (multi-tenant VFIO, CI farm, епhemeral GPU VM),
ваше обладнання має підтримувати надійний FLR або передбачуваний bus reset без побічних ефектів.
Датацентр-клас GPU і сервери зазвичай поводяться краще, бо вони спроєктовані для флотських операцій і віддаленого відновлення.
Споживчі платформи можуть працювати, але ви підписуєтесь на хобі з параметрами ядра, ACPI-хаками і випадковими перезавантаженнями.
2) Тримайте GPU прив’язаним до одного світу якомога довше
Кожне відв’язування/прив’язування — шанс потрапити на поганий шлях. Якщо можна запланувати «GPU лишається з VM на весь її життєвий цикл», робіть так.
Якщо можна прив’язати GPU до вузла і переміщати роботи замість GPU — робіть це. Якщо можна уникати VFIO і використовувати контейнери на хості,
робіть це (за умови, що ви довіряєте моделі багатокористувацького доступу і маєте контролі ізоляції).
3) Вимкніть runtime PM для passthrough-GPU (селективно)
Runtime PM економить ватти. Він також вводить стани, що ускладнюють скидання/перев’язку. Для passthrough-GPU надійність важливіша за елегантність.
Примусово встановлюйте D0 під час переходів життєвого циклу або повністю вимикайте runtime PM для пристрою.
4) Трактуйте «скидання не вдалося» як проблему здоров’я вузла, а не випадковий глюк
Якщо GPU не вдається скинути один раз, ймовірність повторення зростає за схожих умов. Позначайте вузол як нездоровий, зливайте робочі навантаження
і перезавантажуйте за розкладом, а не в пік.
5) Використовуйте контрольовану «сходи скидання»
Не стрибайте відразу до bus reset. Використовуйте ескалацію:
- Переконайтеся, що жоден процес не використовує GPU (або коректно зупиніть VM).
- Відв’яжіть драйвер (хост) або від’єднайте пристрій (VFIO).
- Спробуйте FLR через sysfs.
- Спробуйте hot/bus reset лише якщо ізоляція підтверджена.
- Якщо все ще зламано: перезавантажте вузол; якщо повторюється — змінюйте прошивку/платформу.
6) Узгодьте налаштування прошивки/BIOS з очікуваннями щодо скидання
BIOS/UEFI може підірвати вас налаштуваннями живлення і опціями PCIe. Типові покращення (залежить від платформи):
- Вимкніть глибокі PCIe-стани для слота, якщо бачите проблеми з D3cold.
- Увімкніть Above 4G Decoding для великих BAR-пристроїв і сучасних GPU.
- Оновлюйте VBIOS GPU і системний BIOS разом; невідповідні покоління створюють «працює, поки не перестане» поведінку.
7) Для кластерів: будьте толерантні до перезавантажень і отримуйте перевагу
Якщо ваш флот достатньо великий, економічно коректна відповідь часто така: прийміть, що деякі скидання GPU потребують перезавантаження,
і зробіть перезавантаження вузла нормальним засобом відновлення з швидким перепризначенням робіт.
Жарт №2: Найнадійніше скидання GPU — це те, яке виконує блок живлення, що коротко «забуває», що подавало живлення.
Три міні-історії з корпоративного світу
Міні-історія 1: Інцидент, спричинений хибним припущенням
Середня SaaS-компанія побудувала сервіс інференсу на GPU. Вони хотіли жорстку ізоляцію орендарів, тож використали VFIO passthrough:
по одній VM на клієнтське навантаження, GPU переназначали під час життєвого циклу VM. Команда платформи ввімкнула IOMMU, перевірила IOMMU-групи і написала
автоматику, що від’єднувала і знову прив’язувала пристрої між VM.
Це пройшло стаджинг. Пройшло лоад-тести. Розгортання почалося тихо і виглядало нормально кілька днів — саме так платформа втрачала довіру перед катастрофою.
Перший інцидент почався як «деякі завдання зависають». Потім стало «половина GPU не розподіляється». VM були здорові.
Libvirt повідомляв успішне від’єднання/під’єднання. Але пристрої GPU не ініціалізувалися у наступній VM після від’єднання.
Оператори знайшли «скидання не вдалося» в dmesg і спостерігали, як unbind блокується. Кілька вузлів почали логувати коректовані PCIe-помилки,
що поступово перетворилося на шторми.
Хибне припущення було простим: «групи IOMMU означають безпечне повторне використання». Ізоляція була правильною. Відновлюваність — ні.
Моделі GPU у тому флоті можна було передавати, але їхня поведінка скидання була ненадійна при повторному навантаженні.
Вони не були зламані для десктопного використання; вони просто не створювалися для такого циклу життєвого циклу.
Виправлення було операційним і архітектурним: вони припинили повторно використовувати GPU між життєвими циклами VM. GPU залишався прикріпленим до VM,
поки VM не було знищено, а вузли перезавантажувалися під час контрольованого вікна технічного обслуговування перед поверненням у пул.
Планування потужності стало трохи чеснішим. Інциденти різко впали.
Міні-історія 2: Оптимізація, що обернулася проти
Фінансово-аналітична фірма виконувала важкі обчислення вночі. Вони хотіли зменшити витрати на електроенергію і ввімкнули агресивне
runtime power management. Ідея була розумною: GPU простоюють між сплесками, автопауза — економія ватів.
Через два тижні вони отримали новий клас відмов: вузли, які виглядали здоровими, але відмовлялися запускати GPU-завдання після простою.
Планувальник призначав задачу, задача не могла відкрити пристрій, повтори стрибали вузлами, і з часом кластер виглядав «завантаженим», але майже нічого не робив.
Класичний міраж завантаження.
Коренем проблеми було те, що GPU входили у глибокі стани живлення, які погано взаємодіяли з шляхами реініціалізації драйвера після довгого простою.
Шлях скидання іноді спрацьовував, іноді — ні. Частка відмов була невелика, але радіус ураження великий через хвилю повторних спроб.
Вони відключили runtime PM для функцій GPU, що використовуються для обчислень. Витрати на електроенергію трохи зросли. Продуктивність зросла більше.
Найважливіше — кластер перестав брехати про свою доступність.
Урок: оптимізація під енергоефективність без плану відновлення схожа на оптимізацію продуктивності сховища шляхом вимкнення контрольних сум.
Ви отримаєте цифри. Вам не сподобається рахунок, коли прийде реальність.
Міні-історія 3: Нудна, але правильна практика, що врятувала день
Дослідницька організація працювала на багатокористувацькому GPU-кластері з міксом поколінь обладнання. Вони вивчили важким шляхом, що
«проблеми скидання GPU» нерівномірно розподілені; кілька вузлів завжди гірші.
Їхня нудна практика: вузли міткувалися класом «надійність скидання GPU» на основі спостережуваної поведінки. Завдання, що вимагали частих рестартів або епемерного провізування,
планувалися лише на вузлах з високою надійністю скидання. Довготривалі завдання могли працювати будь-де, але з чекпоінтингом і планом преемпції.
Вони також мали суворий процес відновлення: вузол, що задокументував невдачу скидання, негайно зливався, перезавантажувався і повертався до сервісу лише після проходження стандартизованого циклу тестів attach/detach.
Ніякого геройського дебагу в робочий час.
Коли нова версія драйвера ввела більш часті крайові випадки скидання для однієї сімейства GPU, вплив був локалізований.
Планувальник уникав ризикових вузлів, цикл drain-and-reboot запобіг довгим AER-штормах, і користувачі здебільшого бачили перезапуск задачі, а не її зависання.
Це не було гламурно. Це було правильно.
Типові помилки (симптом → причина → виправлення)
1) Симптом: «скидання не вдалося» після відв’язки; GPU не переприв’язується
Причина: Пристрій не підтримує надійну FLR; шлях скидання драйвера неповний; GPU застряг у внутрішньому стані прошивки.
Виправлення: Уникайте частого відв’язування/прив’язування; прив’язуйте GPU на весь життєвий цикл VM; використовуйте bus reset лише з ізольованим downstream-портом; інакше перезавантажуйте вузол.
2) Симптом: GPU присутній у lspci, але прив’язка драйвера не вдається з таймаутами
Причина: GPU у D3cold або платформа не може його розбудити; конфлікт runtime PM.
Виправлення: Примусово встановіть /sys/bus/pci/devices/…/power/control в on; відрегулюйте налаштування BIOS PCIe живлення; забезпечте, щоб пристрій був у D0 перед повторною прив’язкою.
3) Симптом: Збільшення коректованих помилок AER; випадкові відмови задач
Причина: Проблеми цілісності сигналу/лінку, проблеми з riser, деградований лінк, маргінальний слот.
Виправлення: Пересадіть GPU, замініть riser/кабель, перевірте ширину/швидкість лінку, оновіть прошивку; карантинуйте вузол, якщо проблема постійна.
4) Симптом: Вивантаження драйвера GPU зависає назавжди
Причина: Драйвер чекає, поки апаратні рушії не спокійні; мікроконтролер GPU заклинив.
Виправлення: Не боріться з цим. Зливайте та перезавантажуйте. Потім розслідуйте, чому відбуваються заклинювання (терміка, прошивка, навантаження, розгін, живлення).
5) Симптом: VFIO працює лише один раз після завантаження
Причина: Скидання працює при холодному завантаженні, але не після використання гостем; відсутній вендорний quirk для скидання або потрібен bus reset/цикл живлення.
Виправлення: Перевірте можливість скидання перед розгортанням; плануйте перезавантаження хоста між призначеннями; віддавайте перевагу обладнанню з відомо доброю поведінкою скидання.
6) Симптом: Вимкнення VM спричиняє нестабільність хоста або скидання інших пристроїв
Причина: Ви застосували bus reset на бридж, спільному з іншими кінцевими точками (сховище, NIC).
Виправлення: Промапте топологію; ізолюйте GPU за виділеними root port; не робіть bus reset на спільних сегментах у продакшні.
7) Симптом: «Працювало в staging», але ламається при частому churn
Причина: Тести не покривали тривалого часу роботи, великого навантаження VRAM або повторних attach/detach циклів; стани прошивки залежать від навантаження.
Виправлення: Додайте soak-тести з attach/detach циклами; класифікуйте вузли за спостережуваною надійністю скидання; автоматизуйте ремедіацію.
Чек-листи / покроковий план
Чек-лист A: Перед масштабним розгортанням VFIO GPU passthrough
- Переконайтеся, що IOMMU увімкнено в BIOS і ядрі; підтвердіть повідомлення DMAR/AMD-Vi.
- Підтвердіть функції GPU і переконайтеся, що всі враховані (графіка/аудіо/USB).
- Змапте IOMMU-групи і топологію; ідентифікуйте upstream-порти і спільні сегменти.
- Запустіть soak-тест циклу відв’язки/прив’язки (десятки до сотень циклів) під реальним навантаженням (навантаження VRAM + обчислення).
- Визначте контракт відновлення: «відновлення без перезавантаження» або «перезавантаження прийнятне». Запишіть це у runbook.
- Реалізуйте карантин вузла: якщо скидання не вдалося один раз — видаліть вузол із планування до ремедіації.
Чек-лист B: Безпечна «сходи» відновлення під час інциденту
- Зупиніть або перемістіть навантаження; переконайтеся, що жоден процес не використовує GPU.
- Зберіть докази: хвіст
dmesg,lspci -vvстан лінку, стан живлення, поточна прив’язка драйвера. - Спробуйте FLR через sysfs reset на функції.
- Якщо досі не працює і лише якщо топологія безпечна: скиньте upstream порт/брідж.
- Якщо почався AER-шторм або повторні відмови: злити вузол, перезавантажити, відправити вузол на глибоке розслідування.
Чек-лист C: Зробіть це нудним (найнадійніший варіант)
- Маркуйте вузли по сімейству GPU/прошивці та спостережуваній поведінці скидання.
- Плануйте навантаження з великим churn лише на «хороші для скидання» вузли.
- Вимикайте runtime PM для passthrough-GPU, якщо немає доказів безпечності.
- Контролюйте версії ядра/драйверів/прошивки; впроваджуйте зміни через канарки і плани відкату.
- Автоматизуйте цикл перезавантаження + тест здоров’я; ставте перезавантаження як інструмент обслуговування, а не ознаку слабкості.
FAQ
Q1: Якщо GPU у власній IOMMU-групі, чому його не завжди можна скинути?
Групування IOMMU стосується меж доступу DMA. Здатність до скидання залежить від підтримки PCIe-скидання, доменів живлення, стану прошивки
і топології. Вони пов’язані, але не тотожні.
Q2: Це лише проблема AMD?
Ні. У різних постачальників — різні закономірності, але відмови скидання трапляються в усіх сімействах GPU. Спільнота VFIO історично
підкреслювала випадки AMD «reset bug», але NVIDIA та інші також можуть клинити в залежності від моделі, прошивки та шляху драйвера.
Q3: SR-IOV або MIG усувають проблеми скидання?
Вони змінюють проблему. Функції розподілу можуть зменшити churn по всьому пристрою, що допомагає. Але все одно залишаються семантики скидання
на рівні фізичної функції, і помилки прошивки/драйвера можуть випливати під важкими багатокористувацькими умовами.
Q4: Чи можна виправити це лише програмно через параметри ядра?
Іноді можна покращити поведінку (особливо навколо керування живленням або прив’язки драйвера), але не можна програмно вирішити проблему пристрою,
який потребує фундаментального апаратного скидання. Розглядайте вибір апаратури і топологію як пріоритетні.
Q5: Яке скидання найбезпечніше спробувати першим?
Function-level reset (FLR) через sysfs зазвичай найменш руйнівний. Якщо воно не допомагає, наступні кроки залежать від топології. Bus reset
може спрацювати, але несе побічні ризики.
Q6: Чому GPU іноді працює після перезавантаження хоста, але не після відв’язки/прив’язки VM?
Холодне завантаження встановлює чисту відправну точку: прошивка ініціалізується заново, лінії живлення перезапускаються, лінк коректно тренується.
Цикл відв’язки/прив’язки часто покладається на часткові скидання і шляхи teardown драйвера, які можуть не повністю реініціалізувати внутрішній стан GPU.
Q7: Чи варто вимикати AER, щоб припинити спам в логах?
Зазвичай ні. AER повідомляє про симптоми. Вимкнення ховає докази, поки лінк продовжує некоректно працювати.
Якщо AER-шторми викликають операційні проблеми, карантинуйте вузол і виправте підлягаючу проблему лінку/живлення/платформи.
Q8: Чи прийнятно планувати перезавантаження як метод відновлення?
Так, якщо ви це правильно спроєктуєте. У кластерах «перезавантажити, щоб відновити завислий GPU» може бути цілком нормальним, якщо задачі перезапускаються,
вузли безпечно зливаються, а шлях перезавантаження швидкий і автоматизований.
Q9: Чому іноді відв’язка драйвера зависає?
Тому що драйвер намагається безпечно завершити роботу: чекає, щоб DMA припинився і рушії заспокоїлися. Якщо GPU заклинив, драйвер
не може відповідально визнати його вільним. Таке зависання часто захищає вас від корупції пам’яті.
Q10: Який єдиний найкращий метрик для алерту?
Сигналізуйте про невдачі скидання і повторювані події AER на root-портах GPU. Вони сильно корелюють з тим, що «цей вузол потім витратить ваш час».
Далі автоматизуйте карантин і ремедіацію.
Висновок: практичні наступні кроки
Якщо запам’ятати одну річ: IOMMU дає безпеку DMA, а не безпеку скидання. Клас багів скидання GPU — це те, що відбувається, коли ми
плутаємо ці речі і будуємо автоматику, що припускає, ніби пристрої поводяться як безстанні периферійні пристрої.
Наступні кроки, які швидко приносять виграш:
- Інвентаризація топології: змаркуйте upstream-порти, спільні бриджі і IOMMU-групи для кожного GPU-вузла.
- Впровадьте сходи скидання: FLR → обережний bus reset (лише якщо ізольовано) → drain і reboot.
- Вимкніть runtime PM для passthrough-GPU, якщо бачите дивні D3cold/D3hot стани.
- Впровадьте карантин вузла: одна невдача скидання має видаляти вузол з планування до перезавантаження + тесту здоров’я.
- Змініть критерії закупівлі: вимагайте перевіреної поведінки скидання, контроль живлення слота якщо можливо, і платформи, спроєктовані для віртуалізації.
Ось так ви перетворюєте «баг скидання GPU» з повторюваного інциденту на відому обмеження з нудною, надійною відповіддю.
Нудно — це добре. Нудно означає, що ви отримаєте свої вихідні дні назад.