GPU для ваших проектов · оплата криптовалютой без KYC Как арендовать
Русский
Открыть консоль
Практическое руководство / KERNODECK

Переход на смешанную точность без потери численного контроля

Установите базовый уровень в обычной точности, включите autocast для прямого вычисления и потерь, затем сравните выходы, градиенты и качество на одних и тех же входах. При обучении в FP16 GradScaler помогает справляться с градиентами малой амплитуды; он не делает совместимой любую модель. BF16 имеет иное численное поведение. Сохраняйте явный критерий отката, прежде чем искать выигрыш в памяти или скорости.

6 мин чтения · Руководство для разработчиков

Начните с базового уровня, отвечающего потребности

Выберите короткий набор с обычными входами, граничными случаями и границами решения. Зафиксируйте модель, веса, предобработку и режим train или eval. Сравнение между двумя моделями или двумя батчами не позволяет отнести их различие к точности.

Записывайте выход, полезный для вашего приложения, а не только потерю. Для классификатора это могут быть оценки и решения; для регрессии — ошибка и крайние значения. Убедитесь уже на базовом уровне в наличии NaN или inf. Некорректный запуск FP32 не становится надёжной основой из-за большего числа битов.

Задайте допуск, минимальное качество и отсутствие нефинитных значений до испытания. PyTorch напоминает, что вычисления с плавающей запятой не гарантируют идентичных результатов между устройствами или путями выполнения.

Различать autocast, числовой формат и GradScaler

autocast выбирает тип некоторых операций в соответствии с их политикой вычислений. Он не преобразует всю программу в единый формат. При таком использовании избегайте ручного преобразования всей модели через half(). Актуальная документация рекомендует torch.autocast или torch.amp.autocast; старые интерфейсы torch.cuda.amp устарели.

GradScaler управляет масштабом потерь и градиентов во время обучения. Он не применяется как ускоритель инференса, в котором не выполняется backward. У FP16 числовой диапазон уже, чем у BF16; модель, рассчитанная на BF16, может переполниться в FP16. Поэтому повторное снижение масштаба не доказывает, что проблема решена.

Выбирайте формат исходя из ограничений модели и реально используемых операций, а затем проверьте поддержку целевой платформы. Коммерческое название карты или предпочтение по подготовке PyTorch не доказывает, что для вашего пользовательского оператора есть нужное ядро.

Прокрутите таблицу, чтобы увидеть все столбцы.
Решения по точности, которые нужно проверить на проекте
ВыборРольНеобходимая проверка
Эталон FP32Точка сравнения проектаКонечные выходные значения и ожидаемое качество
Autocast FP16Некоторые операции в пониженной точностиЧисловой диапазон и градиенты
Autocast BF16Другой компромисс между диапазоном и точностьюДоступные операторы и качество
GradScalerУправление масштабом градиентовФактически выполненные обновления

Расставьте этапы обучения в правильном порядке

Предложенный фрагмент предполагает, что модель и оптимизатор уже созданы, входные данные и целевые значения находятся на одном и том же GPU, а потери скалярны. Он не выполнялся и не является проверкой какого-либо предложения. Контекст autocast охватывает forward и потери; backward выполняется после его закрытия. Scaler создаётся один раз для сессии обучения, а не для каждого батча.

Чтобы просмотреть или ограничить градиенты, сначала снимите их масштабный множитель с помощью unscale_. Официальные примеры AMP уточняют, что это нужно делать один раз на каждый оптимизатор и после накопления градиентов, предназначенных для его обновления. Порог ограничения 1.0 ниже — иллюстративное значение, которое нужно выбрать для вашего проекта, а не универсальная рекомендация.

Здесь проверки прерывают диагностику, если потери, градиенты или общая норма не конечны. Эти чтения на CPU вносят помехи: не замеряйте время этого фрагмента. Накопление, несколько оптимизаторов и планировщик требуют собственного определения момента обновления.

Учебная последовательность AMP на GPU, не выполнявшаяся
import torch

# Предусловия: model, optimizer, loss_fn, inputs и targets существуют.
# Модель и входные данные находятся на одном устройстве CUDA/HIP.
dtype = torch.float16  # Выбор нужно проверить; BF16 — другая попытка.
scaler = torch.amp.GradScaler("cuda", enabled=(dtype == torch.float16))

# Разместите в вашем цикле, сохраняя scaler между батчами.
optimizer.zero_grad(set_to_none=True)
with torch.autocast(device_type="cuda", dtype=dtype):
    prediction = model(inputs)
    loss = loss_fn(prediction, targets)
if not bool(torch.isfinite(loss).item()):
    raise FloatingPointError("Потери не конечны: прервать диагностику")
scaler.scale(loss).backward()
scaler.unscale_(optimizer)
if any(p.grad is not None and
       not bool(torch.isfinite(p.grad).all().item())
       for p in model.parameters()):
    raise FloatingPointError("Градиент не конечен: прервать диагностику")
torch.nn.utils.clip_grad_norm_(
    model.parameters(), max_norm=1.0, error_if_nonfinite=True,
)
scaler.step(optimizer)
scaler.update()

Разобранный пример: два близких решения не взаимозаменяемы

Предположим, есть сервис, который выбирает класс с максимальным счётом. На учебном входе эталон даёт два очень близких счёта: 1,0000 и 1,0003. Другой численный путь мог бы изменить их порядок или создать равенство. Эти числа иллюстрируют границу принятия решения; это не измеренные выходные значения FP16 или BF16.

Правильная проверка состоит из двух уровней. Сравните счёты с явными допусками, затем сравните решение и правило, применяемое к равенствам. Малое различие по абсолютной величине может изменить выбранное действие. И наоборот, заметное численное различие может остаться без последствий для задачи, порог которой находится далеко от наблюдаемых счётов.

Фиксируйте идентификаторы, эталонные выходы, испытание AMP и влияние на решение. Установите правило приёмки до чтения результатов. Не расширяйте допуск, чтобы скрыть неудобный случай; выходы разных масштабов могут требовать различных критериев.

Прокрутите таблицу, чтобы увидеть все столбцы.
Учебная карточка сравнения, дополняемая измерениями
КритерийСсылкаИспытание AMPРешение
Конечные выходыПроверитьПроверитьОтклонять необъяснимые неконечные значения
Числовое расхождениеСохранённые значенияРасхождение к вычислениюДопуск, заданный до испытания
Прикладное решениеКласс или действиеКласс или действиеИзучить изменения
Качество на фиксированном набореИзмеритьИзмеритьСоблюдать порог проекта

Интерпретировать NaN и пропущенные обновления

Когда появляются неконечные значения, ищите первый шаг, который их порождает: вход, промежуточный выход, потерю или градиент. Воспроизведите тот же случай на эталоне, затем локально отключите autocast вокруг подозрительной операции, контролируя также тип её входов. Перезапуск всего обучения в FP32 может служить сравнением, но не локализует проблему автоматически.

Скалер может пропустить обновление, когда градиенты содержат inf или NaN. Поэтому цикл, который продолжается, не обязательно выполнил столько же обновлений, сколько итераций. Фиксируйте это поведение при диагностике. Не продвигайте вслепую политику обучения, предположительно следующую за фактическими обновлениями.

Конечная потеря не гарантирует конечных градиентов. И наоборот, единичный инцидент не достаточен, чтобы объявить обучение непригодным: изучите его частоту, прогресс и качество. Рецепт AMP даёт метод для раздельной изоляции autocast и скалирования, когда один из них подозрителен.

Подготовить воспроизводимый откат

Перед испытанием сохраните эталонную конфигурацию, веса, состояние оптимизатора и согласованный checkpoint. Если в вашем обучении используется скалер, его состояние также входит в возобновление. Задокументируйте dtype и возможные области, оставленные в FP32. Возобновление с другой политикой — это экспериментальное изменение, которое нужно идентифицировать, а не неявно эквивалентное продолжение.

Возвращайтесь к предыдущей конфигурации, если выходы становятся неконечными, если качество выходит за установленный критерий или если обновления перестают продвигаться пригодным образом. Сохраните случай, который мотивировал этот возврат. После изменения повторите сравнение на том же наборе, прежде чем увеличивать длительность.

Упражнение Kernodeck по checkpoints проверяет возобновление на CPU без AMP. Переиспользуйте его метод сравнения, добавив состояния, фактически потребляемые вашим циклом.

Измерять выигрыш только после числовой валидации

После валидации измерьте память и время без подробной диагностики. Сохраните формы, batch, модель и качество. Чтения скаляров, синхронизации и профилировщики могут изменять длительности; уберите интрузивные контроли из финального измерения.

На ROCm имя устройства PyTorch остаётся cuda, и соответствующие интерфейсы переиспользуются. Это не гарантирует ни те же ядра, ни идентичные результаты по сравнению с NVIDIA. Проверьте backend и операторы проекта на целевой платформе. Данное руководство не заявляет ни фиксированного снижения памяти, ни кратного увеличения скорости, ни совместимости подготовки Kernodeck.

Ваши вопросы

Означает ли AMP, что все тензоры переходят в FP16?

Нет. autocast применяет политику по операциям. Некоторые операции остаются в другой точности. Ручное преобразование всей модели в half() не эквивалентно использованию autocast и может изменить условия стабильности.

Всегда ли BF16 выгодно заменяет FP16?

Нет. Оба формата имеют разные компромиссы, и их поддержка зависит от операций и окружения. Сравните качество и стоимость на вашей нагрузке; более широкий диапазон BF16 сам по себе не гарантирует требуемой точности.

Нужен ли GradScaler для инференса?

Скалер участвует в обучении с градиентами, а не в инференсе без backward. Для последнего вместо этого контролируйте выходы и качество под autocast, сохраняя ожидаемый режим оценки.

Достаточно ли конечной потери, чтобы принять AMP?

Нет. Проверьте также градиенты, обновления, качество и решения приложения. Небольшое числовое различие может стать решающим вблизи порога; обучение, которое продолжается, тоже может пропустить некоторые обновления.