GPU для досліджень ML · Оплата криптою без KYC
IteraGPU
Навчання · Пам'ять та оптимізація

Зменшити мікробатч, не втрачаючи обліку оновлень.

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

01 /

Відокремити мікробатч, зворотний прохід і оновлення

Мікробатч — це група прикладів, оброблена одним прямим проходом на одній репліці. Зворотний прохід обчислює його внесок у градієнти. Оновлення оптимізатора використовує наявні градієнти, щоб змінити параметри. За накопичення кілька прямих/зворотних проходів передують цьому оновленню; параметри залишаються незмінними протягом групи.

У PyTorch градієнти накопичуються в призначених для цього тензорах. Тому обнулення градієнтів після кожного мікробатчу скасувало б бажане накопичення. І навпаки, забути обнулити їх між двома групами означало б, що приклади з попереднього оновлення теж зробили свій внесок.

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

Технічні джерела: PyTorch — накопичення та обнулення градієнтів

02 /

Обчислити ефективний батч, не рахуючи GPU двічі

Позначимо m — кількість прикладів на мікробатч і на репліку, A — кількість накопичених мікробатчів, D — кількість реплік паралелізму даних. Якщо ці розміри сталі, а приклади розподілені правильно, кількість прикладів, що роблять внесок в одне глобальне оновлення, дорівнює m × A × D.

Коефіцієнт D не обов'язково позначає всі карти в машині. GPU, які спільно використовують ту саму модель через тензорний або конвеєрний паралелізм, не стають від цього окремими репліками даних. Записуйте фактично налаштовані групи, а не просто комерційну кількість батчу.

Арифметичний приклад: два приклади на мікробатч, вісім накопичень і дві репліки дають 32 приклади на одне глобальне оновлення. Кожна репліка обробляє шістнадцять прикладів у цій групі. Таблиця порівнює кількості; вона не ранжує їхню пам'ять чи швидкість.

Ефективний батч у прикладах = мікробатч на репліку m × накопичення A × репліки даних D
Ілюстративні кількості, без вимірювання продуктивності; повні мікробатчі та розподілені приклади.
mADПрикладів на глобальне оновлення
28232
116232
44232
28116

Технічні джерела: PyTorch — ефективний батч і накопичення у змішаній точності · PyTorch — поведінка реплік DistributedDataParallel

03 /

Нормалізувати втрати за фактично оціненими елементами

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

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

Теоретичний приклад: один мікробатч містить 512 токенів під наглядом із середньою втратою 2; інший містить 1 536 із середньою 4. Зважене середнє дорівнює (512 × 2 + 1 536 × 4) ÷ 2 048 = 3,5. Незважене середнє дорівнює 3 і надмірно зважує малу групу. Ці значення лише ілюструють обчислення.

Технічні джерела: Hugging Face Accelerate — накопичення з прикладами різного розміру

04 /

Організувати повну групу накопичення

Спочатку підготуйте межі групи та її знаменник. Для кожного мікробатча обчисліть вихід, нормалізовану втрату та зворотний прохід без проміжного оновлення. Звільняйте виходи, які більше не потрібні; зберігання втрат, прив'язаних до їхнього графа, у списку може продовжити час життя виділень.

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

У змішаній точності з GradScaler масштабний коефіцієнт залишається сталим під час накопичення. Фактичне перемасштабування та можливе відсікання відбуваються після внесків; оновлення scaler йде за спробою кроку. Перевірки на нескінченні значення можуть перешкодити зміні параметрів.

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

Технічні джерела: PyTorch — графи autograd і тензори, збережені для backward · PyTorch — накопичення, unscale, відсікання та GradScaler

05 /

У мульти-GPU перевіряйте редукцію та розподіл прикладів

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

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

Не переносьте це правило на всі розподілені системи. Sharding станів, pipeline, хуки комунікації та фреймворки можуть змінювати фактичні операції. Почніть із конфігурації, яку підтримує ваш інструмент, а потім перевірте повну групу на кожній репліці.

Технічні джерела: PyTorch — редукція градієнтів і межі дії no_sync у DDP

06 /

Чому той самий ефективний батч не гарантує того самого досвіду

Рівність m × A × D — це підрахунок. Щоб відтворити градієнт великого батчу, потрібні зокрема коректно зважені внески, однаковий стан параметрів упродовж групи та операції, сумісні з таким розкладом. Чисельну близькість перевіряють з відповідним допуском; її не виводять лише з добутку.

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

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

Технічні джерела: PyTorch — статистики BatchNorm1d · PyTorch — межі відтворюваності

07 /

Контролювати пам'ять і вирішувати, що далі

Інструментуйте групу, що охоплює зворотні проходи та перше оновлення, а потім наступні групи. Успіх на forward не підтверджує градієнти чи стани, створені оптимізатором. Лічильники повинні зберігати свій периметр за device. Досьє про пам'ять дає метод зчитування базових рівнів і піків.

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

Перед кампанією перевірте одне оновлення на невеликому контрольованому наборі: ті самі приклади, зважена втрата, скінченні градієнти, межа групи та кількість кроків. Потім оцініть якість за обраним протоколом. Малий MLP для інференсу з досьє для завантаження не виконує цього рецепта навчання; він не замінює цю перевірку.

Ваша підсумкова картка об'єднує m, A, D, контрольовані токени, точність, нормалізацію, обробку останньої групи та спостережені піки. Потім поверніться до вибору конфігурації та бюджету експериментів, відокремлюючи підготовку, спроби та реально прийняті результати.

  • Аномально мала втрата: шукайте подвійне ділення на акумуляцію.
  • Результат змінюється залежно від розбиття: перевірте ігноровані токени та середнє від середніх.
  • Акумуляція без ефекту: перевірте zero_grad і optimizer.step.
  • Зростання пам'яті: шукайте посилання, збережені між мікробатчами.
  • Зсув розкладу: розрізняйте зворотні проходи та оновлення.

Технічні джерела: Hugging Face — пам'яттєві піки навчання

Практичні питання

Чи множить акумуляція шістнадцяти мікробатчів пам'ять у шістнадцять разів?

Не обов'язково: внески обробляються послідовно. Градієнти зберігаються, тоді як непотрібні активації можуть бути звільнені. Пік залежить, однак, від моделі, збережених посилань і станів оптимізатора; вимірюйте повну групу.

Чи завжди два GPU подвоюють ефективний батч?

Лише якщо ці GPU беруть участь як дві репліки даних з оголошеним мікробатчем. Карти, що спільно використовують одну модель, не становлять автоматично двох реплік. Перевірте розподілені групи та оброблені приклади.

Чи можу я поділити всі втрати на кількість акумуляцій?

Це просте правило відповідає мікробатчам однакової ваги, без нормалізації, вже керованої фреймворком. За змінної кількості контрольованих токенів або неповної останньої групи використовуйте реальний знаменник цільової функції.