Пакет автоматической смешанной точности - torch.amp
torch.amp предоставляет удобные методы для смешанной точности, где некоторые операции используют тип данных torch.float32 (float) и другие операции используют тип данных с плавающей точкой меньшей точности (lower_precision_fp): torch.float16 (half) или torch.bfloat16. Некоторые операции, такие как линейные слои и свертки, намного быстрее в lower_precision_fp. Другие операции, такие как сокращения, часто требуют динамического диапазона float32. Смешанная точность пытается сопоставить каждую операцию с её соответствующим типом данных.
Обычно «обучение со смешанной точностью» с типом данных torch.float16 использует torch.autocast и torch.cuda.amp.GradScaler вместе, как показано в примерах CUDA автоматической смешанной точности и рецепте CUDA автоматической смешанной точности. Однако torch.autocast и torch.cuda.amp.GradScaler являются модульными и могут использоваться по отдельности, если необходимо. Как показано в разделе примера CPU для torch.autocast, «обучение/вывод со смешанной точностью» на CPU с типом данных torch.bfloat16 использует только torch.autocast.
Для CUDA и CPU также предоставлены отдельные API:
-
torch.autocast("cuda", args...)эквивалентноtorch.cuda.amp.autocast(args...). -
torch.autocast("cpu", args...)эквивалентноtorch.cpu.amp.autocast(args...). Для CPU в настоящее время поддерживается только тип данных с плавающей точкой меньшей точностиtorch.bfloat16.
Автоматическое переключение типов данных
-
class torch.autocast(device_type, dtype=None, enabled=True, cache_enabled=None)[source] -
Экземпляры
autocastслужат контекстными менеджерами или декораторами, которые позволяют определённым частям вашего скрипта выполняться в смешанной точности.В этих областях операции выполняются в типе данных, специфичном для операции и выбранном по умолчанию для повышения производительности при сохранении точности. Подробности см. в Справочнике по операциям Autocast.
При входе в область с включённой автоматической смешанной точностью тензоры могут быть любого типа. Не следует вызывать
half()илиbfloat16()для вашей модели(ей) или входных данных при использовании автоматического переключения типов.autocastдолжен охватывать только прямой(е) проход(ы) вашей сети, включая вычисление(я) потерь. Обратные проходы под управлением autocast не рекомендуются. Обратные операции выполняются в том же типе, что и соответствующие прямые операции, используемые autocast.Пример для устройств CUDA:
# Creates model and optimizer in default precision model = Net().cuda() optimizer = optim.SGD(model.parameters(), ...) for input, target in data: optimizer.zero_grad() # Enables autocasting for the forward pass (model + loss) with autocast(): output = model(input) loss = loss_fn(output, target) # Exits the context manager before backward() loss.backward() optimizer.step()См. примеры автоматической смешанной точности CUDA (вместе с масштабированием градиента) для использования в более сложных сценариях (например, штраф за градиент, несколько моделей/функций потерь, пользовательские функции autograd) на странице примеров.
autocastтакже может использоваться как декоратор, например, для методаforwardвашей модели:class AutocastModel(nn.Module): ... @autocast() def forward(self, input): ...Числовые тензоры, полученные в области с включённой автоматической смешанной точностью, могут быть
float16. После возвращения в область без автоматического переключения типов их использование с числовыми тензорами других типов может привести к ошибкам несоответствия типов. В таком случае преобразуйте полученные тензоры из области автокаста обратно вfloat32(или в другой тип, если необходимо). Если тензор из области автокаста ужеfloat32, преобразование является пустой операцией и не несёт дополнительной нагрузки. Пример для CUDA:# Creates some tensors in default dtype (here assumed to be float32) a_float32 = torch.rand((8, 8), device="cuda") b_float32 = torch.rand((8, 8), device="cuda") c_float32 = torch.rand((8, 8), device="cuda") d_float32 = torch.rand((8, 8), device="cuda") with autocast(): # torch.mm is on autocast's list of ops that should run in float16. # Inputs are float32, but the op runs in float16 and produces float16 output. # No manual casts are required. e_float16 = torch.mm(a_float32, b_float32) # Also handles mixed input types f_float16 = torch.mm(d_float32, e_float16) # After exiting autocast, calls f_float16.float() to use with d_float32 g_float32 = torch.mm(d_float32, f_float16.float())Пример обучения на процессоре:
# Creates model and optimizer in default precision model = Net() optimizer = optim.SGD(model.parameters(), ...) for epoch in epochs: for input, target in data: optimizer.zero_grad() # Runs the forward pass with autocasting. with torch.autocast(device_type="cpu", dtype=torch.bfloat16): output = model(input) loss = loss_fn(output, target) loss.backward() optimizer.step()Пример вывода на процессоре:
# Creates model in default precision model = Net().eval() with torch.autocast(device_type="cpu", dtype=torch.bfloat16): for input in data: # Runs the forward pass with autocasting. output = model(input)Пример вывода на процессоре с использованием Jit Trace:
class TestModel(nn.Module): def __init__(self, input_size, num_classes): super(TestModel, self).__init__() self.fc1 = nn.Linear(input_size, num_classes) def forward(self, x): return self.fc1(x) input_size = 2 num_classes = 2 model = TestModel(input_size, num_classes).eval() # For now, we suggest to disable the Jit Autocast Pass, # As the issue: https://github.com/pytorch/pytorch/issues/75956 torch._C._jit_set_autocast_mode(False) with torch.cpu.amp.autocast(cache_enabled=False): model = torch.jit.trace(model, torch.randn(1, input_size)) model = torch.jit.freeze(model) # Models Run for _ in range(3): model(torch.randn(1, input_size))Ошибки несоответствия типов в области с включённой автоматической смешанной точностью являются ошибкой; если вы наблюдаете это, пожалуйста, отправьте сообщение об ошибке.
autocast(enabled=False)подрегионы могут быть вложены в области с включённой автоматической смешанной точностью. Местное отключение автоматического переключения типов может быть полезно, например, если вы хотите принудительно выполнить подрегион в определённомdtype. Отключение автоматического переключения типов даёт вам явный контроль над типом выполнения. В подрегионе входные данные из окружающей области должны быть преобразованы вdtypeперед использованием:# Creates some tensors in default dtype (here assumed to be float32) a_float32 = torch.rand((8, 8), device="cuda") b_float32 = torch.rand((8, 8), device="cuda") c_float32 = torch.rand((8, 8), device="cuda") d_float32 = torch.rand((8, 8), device="cuda") with autocast(): e_float16 = torch.mm(a_float32, b_float32) with autocast(enabled=False): # Calls e_float16.float() to ensure float32 execution # (necessary because e_float16 was created in an autocasted region) f_float32 = torch.mm(c_float32, e_float16.float()) # No manual casts are required when re-entering the autocast-enabled region. # torch.mm again runs in float16 and produces float16 output, regardless of input types. g_float16 = torch.mm(d_float32, f_float32)Состояние автокаста является локальным для потока. Если вы хотите включить его в новом потоке, контекстный менеджер или декоратор должны вызываться в этом потоке. Это влияет на
torch.nn.DataParallelиtorch.nn.parallel.DistributedDataParallelпри использовании более чем одного графического процессора на процесс (см. работу с несколькими графическими процессорами).- Параметры:
-
- device_type (str, обязательно) – Использовать ли устройство ‘cuda’ или ‘cpu’
-
enabled (bool, необязательно) – Автоматический выбор типа данных должен быть включен в данной области. По умолчанию:
True - dtype (torch_dtype, необязательно) – Использовать ли torch.float16 или torch.bfloat16.
-
cache_enabled (bool, необязательно) – Включить ли кеширование весов внутри autocast. По умолчанию:
True
-
class torch.cuda.amp.autocast(enabled=True, dtype=torch.float16, cache_enabled=True)[source] -
См.
torch.autocast.torch.cuda.amp.autocast(args...)эквивалентноtorch.autocast("cuda", args...)
-
torch.cuda.amp.custom_fwd(fwd=None, *, cast_inputs=None)[source] -
Вспомогательный декоратор для методов
forwardпользовательских функций автоградиента (подклассыtorch.autograd.Function). Дополнительные сведения см. на странице примера.- Параметры:
-
cast_inputs (
torch.dtypeили None, необязательно, по умолчанию=None) – Если неNone, при выполненииforwardв области с включённой автоматической смешанной точностью преобразование входных числовых тензоров CUDA в целевой тип (нечисловые тензоры не затрагиваются), затем выполнениеforwardс отключённой автоматической смешанной точностью. ЕслиNone, внутренние операцииforwardвыполняются с текущим состоянием autocast.
Примечание
Если вызываемый декоратором
forwardметод вызывается вне области с включённой автоматической смешанной точностью,custom_fwdявляется пустой операцией, иcast_inputsне оказывает никакого влияния.
-
torch.cuda.amp.custom_bwd(bwd)[source] -
Вспомогательный декоратор для методов обратного распространения пользовательских функций автоградиента (подклассы
torch.autograd.Function). Гарантирует, чтоbackwardвыполняется с тем же состоянием autocast, что иforward. Дополнительные сведения см. на странице примера.
-
class torch.cpu.amp.autocast(enabled=True, dtype=torch.bfloat16, cache_enabled=True)[source] -
См.
torch.autocast.torch.cpu.amp.autocast(args...)эквивалентноtorch.autocast("cpu", args...)
Масштабирование градиентов
Если прямой проход для конкретной операции имеет float16 входные данные, обратный проход для этой операции произведёт float16 градиенты. Значения градиентов с небольшой величиной могут быть не представимы в float16. Эти значения обнулятся («потеря значащих разрядов»), поэтому обновление соответствующих параметров будет утеряно.
Для предотвращения потери значащих разрядов, «масштабирование градиентов» умножает потерю(и) сети на масштабный множитель и вызывает обратный проход по масштабированной(ым) потерям. Градиенты, текущие назад по сети, затем масштабируются на тот же множитель. Другими словами, значения градиентов имеют большую величину, поэтому они не обнуляются.
Градиент каждого параметра (.grad атрибут) должен быть не масштабирован перед обновлением оптимизатором параметров, чтобы множитель масштабирования не мешал скорости обучения.
-
class torch.cuda.amp.GradScaler(init_scale=65536.0, growth_factor=2.0, backoff_factor=0.5, growth_interval=2000, enabled=True)[source] -
-
get_backoff_factor()[source] -
Возвращает Python-число с коэффициентом отката масштабирования.
-
get_growth_factor()[source] -
Возвращает Python-число с коэффициентом роста масштабирования.
-
get_growth_interval()[source] -
Возвращает Python-целое число с интервалом роста.
-
get_scale()[source] -
Возвращает Python-число с текущим масштабом или 1.0, если масштабирование отключено.
Предупреждение
get_scale()влечёт синхронизацию CPU-GPU.
-
is_enabled()[source] -
Возвращает булево значение, указывающее, включен ли этот экземпляр.
-
load_state_dict(state_dict)[source] -
Загружает состояние масштабирования. Если этот экземпляр отключён,
load_state_dict()— это бездействие.- Параметры:
-
state_dict (dict) — состояние масштабирования. Должно быть объектом, возвращаемым из вызова
state_dict().
-
scale(outputs)[source] -
Умножает («масштабирует») тензор или список тензоров на множитель масштабирования.
Возвращает масштабированные результаты. Если этот экземпляр
GradScalerне включен, результаты возвращаются без изменений.- Параметры:
-
outputs (Tensor или итерируемый список тензоров) — результаты, подлежащие масштабированию.
-
set_backoff_factor(new_factor)[source] -
- Параметры:
-
new_scale (float) — значение, используемое в качестве нового коэффициента отката масштабирования.
-
set_growth_factor(new_factor)[source] -
- Параметры:
-
new_scale (float) — значение, используемое в качестве нового коэффициента роста масштабирования.
-
set_growth_interval(new_interval)[source] -
- Параметры:
-
new_interval (int) — значение, используемое в качестве нового интервала роста.
-
state_dict()[source] -
Возвращает состояние масштабирования в виде
dict. Содержит пять элементов:-
"scale"— Python-число, содержащее текущий масштаб -
"growth_factor"— Python-число, содержащее текущий коэффициент роста -
"backoff_factor"— Python-число, содержащее текущий коэффициент отката -
"growth_interval"— Python-целое число, содержащее текущий интервал роста -
"_growth_tracker"— Python-целое число, содержащее количество недавних последовательных не пропущенных шагов.
Если этот экземпляр не включён, возвращает пустой словарь.
Примечание
Если вы хотите сохранить состояние масштабирования после определённой итерации,
state_dict()следует вызвать послеupdate(). -
-
step(optimizer, *args, **kwargs)[source] -
step()выполняет следующие две операции:- Внутренне вызывает
unscale_(optimizer)(еслиunscale_()не был явно вызван дляoptimizerранее в итерации). В рамкахunscale_()проверяются градиенты на наличие inf/NaN. - Если не обнаружены градиенты inf/NaN, вызывается
optimizer.step()с использованием не масштабированных градиентов. В противном случае,optimizer.step()пропускается, чтобы избежать повреждения параметров.
*argsи**kwargsпередаются вoptimizer.step().Возвращает результат вызова
optimizer.step(*args, **kwargs).- Параметры:
-
- optimizer (torch.optim.Optimizer) — оптимизатор, применяющий градиенты.
- args — любые аргументы.
- kwargs — любые ключевые аргументы.
Предупреждение
Использование замкнутых функций (closure) в настоящее время не поддерживается.
- Внутренне вызывает
-
-
unscale_(optimizer)[source] -
Делит («растягивает») тензоры градиентов оптимизатора на коэффициент масштабирования.
unscale_()является необязательным, обеспечивая случаи, когда вам нужно изменить или проверить градиенты между проходом(ами) обратного распространения иstep(). Еслиunscale_()не вызывается явно, градиенты будут автоматически растягиваться во времяstep().Простой пример, использующий
unscale_()для включения обрезки нерастянутых градиентов:... scaler.scale(loss).backward() scaler.unscale_(optimizer) torch.nn.utils.clip_grad_norm_(model.parameters(), max_norm) scaler.step(optimizer) scaler.update()
- Параметры:
-
optimizer (torch.optim.Optimizer) – Оптимизатор, которому принадлежат градиенты, подлежащие растяжению.
Примечание
unscale_()не требует синхронизации CPU-GPU.Предупреждение
unscale_()следует вызывать только один раз на один оптимизатор на вызовstep()и только после того, как все градиенты для назначенных параметров данного оптимизатора были накоплены. Вызовunscale_()дважды для данного оптимизатора между каждым вызовомstep()приводит к ошибке RuntimeError.Предупреждение
unscale_()может растянуть разреженные градиенты вне места, заменяя атрибут.grad.
-
update(new_scale=None)[source] -
Обновляет коэффициент масштабирования.
Если какие-либо шаги оптимизатора были пропущены, масштаб умножается на
backoff_factorдля уменьшения. Еслиgrowth_intervalнепропущенных итераций произошли последовательно, масштаб умножается наgrowth_factorдля увеличения.Передача
new_scaleзадаёт новое значение масштаба вручную. (new_scaleне используется напрямую, он используется для заполнения внутреннего тензора масштаба GradScaler. Таким образом, еслиnew_scaleбыл тензором, последующие изменения этого тензора in-place не будут далее влиять на масштаб, используемый GradScaler внутри.)- Параметры:
-
new_scale (float or
torch.cuda.FloatTensor, optional, default=None) – Новый коэффициент масштабирования.
Предупреждение
update()следует вызывать только в конце итерации, после того, какscaler.step(optimizer)был вызван для всех оптимизаторов, используемых в этой итерации.
-
Справочник по операциям Autocast
Применимость операций
Операции, выполняемые в float64 или с типами данных, не являющимися числами с плавающей точкой, не подходят и будут выполняться в этих типах независимо от того, включена ли автоподстройка типов.
Подходят только операции без изменения места хранения результатов и методы объекта Tensor. В регионах, где включена автоподстройка типов, разрешены варианты операций с изменением места хранения и вызовы, которые явно передают out=... объект Tensor, но они не будут проходить автоподстройку. Например, в регионах с включенной автоподстройкой типов a.addmm(b, c) может быть выполнена автоподстройка, но a.addmm_(b, c) и a.addmm(b, c, out=d) не могут. Для лучшей производительности и стабильности в регионах с включенной автоподстройкой типов предпочтительнее использовать операции без изменения места хранения результатов.
Операции, вызываемые с явным аргументом dtype=..., не подходят, и их вывод будет соответствовать аргументу dtype.
Поведение операций CUDA при автоподстройке типов
В следующих списках описано поведение подходящих операций в регионах с включенной автоподстройкой типов. Эти операции всегда проходят автоподстройку, независимо от того, вызваны ли они в рамках модуля torch.nn.Module, как функция или как метод объекта torch.Tensor. Если функции доступны в нескольких пространствах имен, они будут проходить автоподстройку независимо от пространства имён.
Операции, не перечисленные ниже, не проходят автоподстройку. Они выполняются в типе, определённом их входными данными. Однако автоподстройка может всё ещё изменить тип, в котором выполняются не перечисленные операции, если они находятся ниже по потоку от операций с автоподстройкой.
Если операция не указана в списке, мы предполагаем, что она численно устойчива в float16. Если вы считаете, что не перечисленная операция численно неустойчива в float16, пожалуйста, откройте вопрос.
CUDA-операции, которые могут перейти к float16
__matmul__, addbmm, addmm, addmv, addr, baddbmm, bmm, chain_matmul, multi_dot, conv1d, conv2d, conv3d, conv_transpose1d, conv_transpose2d, conv_transpose3d, GRUCell, linear, LSTMCell, matmul, mm, mv, prelu, RNNCell
CUDA-операции, которые могут перейти к float32
__pow__, __rdiv__, __rpow__, __rtruediv__, acos, asin, binary_cross_entropy_with_logits, cosh, cosine_embedding_loss, cdist, cosine_similarity, cross_entropy, cumprod, cumsum, dist, erfinv, exp, expm1, group_norm, hinge_embedding_loss, kl_div, l1_loss, layer_norm, log, log_softmax, log10, log1p, log2, margin_ranking_loss, mse_loss, multilabel_margin_loss, multi_margin_loss, nll_loss, norm, normalize, pdist, poisson_nll_loss, pow, prod, reciprocal, rsqrt, sinh, smooth_l1_loss, soft_margin_loss, softmax, softmin, softplus, sum, renorm, tan, triplet_margin_loss
CUDA-операции, которые повышают до самого широкого типа входных данных
Эти операции не требуют определённого типа данных для стабильности, но принимают несколько входных данных и требуют, чтобы типы входных данных совпадали. Если все входные данные имеют тип float16, операция выполняется в float16. Если любой из входных данных имеет тип float32, автоподстройка преобразует все входные данные в float32 и выполняет операцию в float32.
addcdiv, addcmul, atan2, bilinear, cross, dot, grid_sample, index_put, scatter_add, tensordot
Некоторые операции, не перечисленные здесь (например, бинарные операции, такие как add), по умолчанию повышают входные данные без вмешательства автоподстройки. Если входные данные представляют собой смесь float16 и float32, эти операции выполняются в float32 и производят float32 выходные данные, независимо от того, включена ли автоподстройка.
Предпочитать binary_cross_entropy_with_logits вместо binary_cross_entropy
Обратные проходы функции torch.nn.functional.binary_cross_entropy() (и torch.nn.BCELoss, которая её оборачивает) могут создавать градиенты, которые не могут быть представлены в float16. В регионах с включённой автоподстройкой типов входные данные могут быть float16, что означает, что обратный градиент должен быть представим в float16 (автоподстройка float16 входных данных вперёд в float32 не помогает, потому что это преобразование должно быть обращено в обратном проходе). Поэтому, binary_cross_entropy и BCELoss вызывают ошибку в регионах с включённой автоподстройкой.
Многие модели используют слой сигмоиды непосредственно перед слоем бинарной кросс-энтропии. В этом случае объедините два слоя с помощью torch.nn.functional.binary_cross_entropy_with_logits() или torch.nn.BCEWithLogitsLoss. binary_cross_entropy_with_logits и BCEWithLogits безопасны для автоподстройки.
Поведение операций на CPU с автоподстановкой типов
В следующих списках описано поведение допустимых операций в областях, где включена автоподстановка типов. Эти операции всегда проходят через автоподстановку, независимо от того, вызваны ли они как часть torch.nn.Module, функции или метода torch.Tensor. Если функции доступны в нескольких именованных пространствах, они проходят через автоподстановку независимо от пространства имён.
Операции, не указанные ниже, не проходят через автоподстановку. Они выполняются с типом, определённым их входными данными. Однако автоподстановка может всё ещё изменить тип, в котором выполняются неперечисленные операции, если они являются следствием операций с автоподстановкой.
Если операция не указана в списке, мы предполагаем, что она числовой устойчива в bfloat16. Если вы считаете, что неперечисленная операция неустойчива числово в bfloat16, пожалуйста, создайте проблему.
Операции на CPU, которые могут автоматически подставить тип на bfloat16
conv1d, conv2d, conv3d, bmm, mm, baddbmm, addmm, addbmm, linear, matmul, _convolution
Операции на CPU, которые могут автоматически подставить тип на float32
conv_transpose1d, conv_transpose2d, conv_transpose3d, avg_pool3d, binary_cross_entropy, grid_sampler, grid_sampler_2d, _grid_sampler_2d_cpu_fallback, grid_sampler_3d, polar, quantile, nanquantile, stft, cdist, trace, view_as_complex, cholesky, cholesky_inverse, cholesky_solve, inverse, lu_solve, orgqr, inverse, ormqr, pinverse, max_pool3d, max_unpool2d, max_unpool3d, adaptive_avg_pool3d, reflection_pad1d, reflection_pad2d, replication_pad1d, replication_pad2d, replication_pad3d, mse_loss, ctc_loss, kl_div, multilabel_margin_loss, fft_fft, fft_ifft, fft_fft2, fft_ifft2, fft_fftn, fft_ifftn, fft_rfft, fft_irfft, fft_rfft2, fft_irfft2, fft_rfftn, fft_irfftn, fft_hfft, fft_ihfft, linalg_matrix_norm, linalg_cond, linalg_matrix_rank, linalg_solve, linalg_cholesky, linalg_svdvals, linalg_eigvals, linalg_eigvalsh, linalg_inv, linalg_householder_product, linalg_tensorinv, linalg_tensorsolve, fake_quantize_per_tensor_affine, eig, geqrf, lstsq, _lu_with_info, qr, solve, svd, symeig, triangular_solve, fractional_max_pool2d, fractional_max_pool3d, adaptive_max_pool3d, multilabel_margin_loss_forward, linalg_qr, linalg_cholesky_ex, linalg_svd, linalg_eig, linalg_eigh, linalg_lstsq, linalg_inv_ex
Операции на CPU, которые повышают тип до типа с наибольшей точностью
Эти операции не требуют конкретного типа данных для устойчивости, но принимают несколько входных данных и требуют соответствия типов входных данных. Если все входные данные являются bfloat16, операция выполняется в bfloat16. Если какой-либо из входных данных является float32, автоподстановка преобразует все входные данные в float32 и выполняет операцию в float32.
cat, stack, index_copy
Некоторые операции, не указанные здесь (например, бинарные операции, такие как add), изначально повышают точность входных данных без вмешательства автоподстановки. Если входные данные представляют собой смесь bfloat16 и float32, эти операции выполняются в float32 и генерируют выходные данные float32 независимо от того, включена ли автоподстановка.
© 2024, PyTorch Contributors
PyTorch has a BSD-style license, as found in the LICENSE file.
https://pytorch.org/docs/1.13/amp.html