Вибір питання перед відкриттям траси
Траса краще відповідає на конкретне питання: чи обчислення чекає на дані, чи копія повторюється, чи маленький оператор викликається занадто часто? Визначте вхід, вихід і межі вашого кроку. Для тренування уточніть, чи він містить backward, оновлення оптимізатора та читання батчу. Для інференсу відокремте завантаження моделі та запит.
Тримайте короткий сценарій, правильність якого ви знаєте. Занотуйте форми, батч, точність, режим моделі, можливу компіляцію та джерело даних. Спрощений вхід може допомогти ізолювати поведінку, але він уже не обов’язково відображає повне навантаження. Зазначте цю різницю у звіті.
Зафіксуйте підсумкову одиницю: мілісекунди на крок або оброблені приклади за секунду. Суми подій не замінюють фактично витраченого часу. Порівнюйте інтервали з однаковими межами читання та передавання.
Розрізнення часу CPU, роботи GPU та очікування
CPU готує та запускає операції; GPU може виконувати їх пізніше. Тому інтервал Python може містити запуск, очікування або і те, і те. Документація PyTorch щодо CUDA зазначає, що точні вимірювання повинні враховувати цю асинхронність, зокрема через синхронізацію або відповідні події для відповідних меж.
Для цільового вимірювання тривалості GPU можуть підійти події CUDA. Для наскрізної затримки дочекайтеся завершення роботи, що входить у цю затримку, і виміряйте весь запит. Не змішуйте ці дві одиниці. Синхронізація, додана між кожною операцією, може усунути реальне перекриття та змінити програму, яку ви намагаєтеся зрозуміти.
У профілювальнику власний час оператора та час із підопераціями також відповідають на різні питання. Подивіться на хронологію, перш ніж підсумовувати рядки таблиці. Одночасні або вкладені активності не є частинами витраченого часу, що не перетинаються.
Виділення фази запуску та активного інтервалу
Перший прохід може містити ініціалізацію, завантаження або компіляцію. Вирішіть, чи ваше питання стосується цього запуску, чи вже стабілізованої фази. Збережіть обидва спостереження, якщо вони важливі для використання, замість того щоб стирати початкову вартість усередненням, поданим як загальне.
Функція schedule дозволяє розрізнити очікування, підготовку збору та активний інтервал. Прогрів профілювальника не є доказом того, що ваша модель досягла стабільного режиму. Перевіряйте також форми, які трапляються, та стан кешів. Застосунок із змінними входами може натрапляти на нові шляхи після кількох ітерацій.
Навчальний план, запропонований нижче, очікує один крок, готує один і захоплює два. Чотирьох кроків достатньо, щоб пояснити механізм, але не щоб встановити розподіл продуктивності. У справжній кампанії виберіть обґрунтований інтервал і повторіть вимірювання поза профілювальником після аналізу.
Пропонований приклад: чотири кроки з чіткими межами
Наведений фрагмент не виконувався. Він припускає, що model, optimizer, loss_fn, loader і device існують, що модель розміщена на device, а завантажувач надає щонайменше чотири batch-і пар x, y. Він виконує оновлення: використовуйте для цього призначений експериментальний стан, а не сесію, ваги якої потрібно зберегти.
Мітки розділяють читання CPU, передавання та навчання. Ітератор створюється перед вікном, що виключає частину його запуску з периметра. Файл вибирається новий, щоб не перезаписати наявний слід. Приклад відмовляється від збору даних GPU, якщо він недоступний, замість того щоб непомітно подати слід CPU як аналіз GPU.
Сигнал step() просуває розклад після кожного кроку. Офіційний рецепт описує цей зв'язок між ітераціями та збором даних. На стеку ROCm пристрій PyTorch усе ще називається cuda; доступність збору даних прискорювача залежить від збірки та її інструментів. Перевірте, які активності фактично присутні в результаті.
from pathlib import Path
import torch
from torch.profiler import (
profile, schedule, record_function,
ProfilerActivity, supported_activities,
)
trace = Path("trace-etape.json")
if trace.exists():
raise FileExistsError("Choisissez un nouveau nom de trace")
activities = [ProfilerActivity.CPU]
if device.type == "cuda":
if ProfilerActivity.CUDA not in supported_activities():
raise RuntimeError("Collecte GPU indisponible dans ce build")
activities.append(ProfilerActivity.CUDA)
iterator = iter(loader)
model.train()
with profile(
activities=activities,
schedule=schedule(wait=1, warmup=1, active=2, repeat=1),
record_shapes=False, profile_memory=False, with_stack=False,
on_trace_ready=lambda p: p.export_chrome_trace(str(trace)),
) as prof:
for _ in range(4):
with record_function("lecture_batch_cpu"):
x, y = next(iterator)
with record_function("transfert"):
x, y = x.to(device), y.to(device)
with record_function("entrainement"):
optimizer.zero_grad(set_to_none=True)
loss = loss_fn(model(x), y)
loss.backward()
optimizer.step()
prof.step()
print(prof.key_averages().table(
sort_by="self_cpu_time_total", row_limit=8,
))Перетворення спостереження на перевірювану гіпотезу
Почніть з активного вікна та переконайтеся, що очікувані мітки з'являються. Далі вивчіть проміжки між активностями, копіювання та повтори. Тривале очікування в lecture_batch_cpu вказує на конвеєр вхідних даних; воно не вимірює сховище безпосередньо. Часте копіювання спонукає перевірити розміщення тензорів, не доводячи, що воно зайве.
Сформулюйте одну гіпотезу, а потім запропонуйте контрольовану зміну. Наприклад, якщо константа перестворюється й передається на кожному кроці, перевірте, чи може час її життя охоплювати кілька кроків без зміни результату. Якщо якийсь оператор виглядає домінантним, вивчіть його форми та кількість викликів, перш ніж шукати йому заміну.
Наведені нижче рядки — це можливі прочитання, а не висновки, зроблені з виконаного трасування. Жодна тривалість чи прискорення не заявляється. Корисний висновок — це наступний експеримент, який може підтвердити або спростувати запропоновану причину.
Прокрутіть таблицю, щоб побачити всі стовпці.| Можливе спостереження | Гіпотеза | Наступна перевірка |
|---|---|---|
| GPU без активності під час читання | Конвеєр вхідних даних не встигає | Той самий розрахунок із уже підготовленим batch |
| Повторювані копії константи | Невідповідне розміщення або час життя | Перемістити один раз, перевірити вихідні дані |
| Багато дрібних запусків | Фрагментована робота | Розглянути групування та загальну вартість |
| Один тривалий оператор | Визначальна форма або алгоритм | Порівняти той самий оператор та його вхідні дані |
Обмеження вартості та обсягу інформації від інструментування
Почніть із короткого збору даних і небагатьох опцій. Увімкніть форми, стеки чи пам'ять лише тоді, коли це потрібно для якогось питання. API PyTorch зазначає, що ця інформація додає витрат; збір форм може навіть утримувати посилання на тензори. Тому детальний профіль може змінити тривалість або використання пам'яті програми.
Трасування може містити назви операторів, форми та, залежно від налаштувань, шляхи до коду. Перегляньте його перед поширенням. Мітка зони має описувати крок, не вміщуючи email, токен, приватний шлях чи вміст вхідних даних. Виберіть читач трасування, що відповідає вашому середовищу, і тримайте збір даних під своїм контролем.
Якщо очікувані події GPU відсутні, не заповнюйте їхній час нулями. Зазначте, що їх не спостерігали, і перевірте підтримку збору даних. Відсутність події в інструменті не є доказом відсутності обчислень.
Перевірка оптимізації поза профілювальником
Почніть із того самого відповідного стану й порівняйте правильність до та після зміни. Для навчання додатковий крок змінює ваги; два послідовно запущені знімки не обов'язково є еквівалентним порівнянням. Збережіть код, параметри та початкову точку, щоб могти пояснити різницю.
Потім виміряйте сценарій без детального збору даних, з тим самим прогрівом і кількома проходами. Наведіть обсяг, сирі значення та їхній розкид. Локальне покращення може зникнути в повному циклі або погіршити якість: і те, і те має залишатися в рішенні.
Зрештою використайте спостереження, щоб уточнити ресурси, які справді потрібні. Трасування з вашої робочої станції не впорядковує пропозиції Kernodeck і не доводить ані процесор хоста, ані мережу орендованого сервера. Порівняння GPU вимагає зіставного навантаження, умов і результатів на відповідних ресурсах.