Spec-Zone.ru › PyTorch 1

Пакет автоматической смешанной точности - 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.
  • Автоматическое преобразование типов
  • Масштабирование градиента
  • Справочник по операциям автоматического преобразования типов

    • Пригодность операций
    • Поведение операций CUDA

      • Операции CUDA, которые могут автоматически преобразовываться в float16
      • Операции CUDA, которые могут автоматически преобразовываться в float32
      • Операции CUDA, которые повышают до самого широкого типа входных данных
      • Предпочитать binary_cross_entropy_with_logits вместо binary_cross_entropy
    • Поведение операций CPU

      • Операции CPU, которые могут автоматически преобразовываться в bfloat16
      • Операции CPU, которые могут автоматически преобразовываться в float32
      • Операции CPU, которые повышают до самого широкого типа входных данных

Автоматическое переключение типов данных

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() выполняет следующие две операции:

  1. Внутренне вызывает unscale_(optimizer) (если unscale_() не был явно вызван для optimizer ранее в итерации). В рамках unscale_() проверяются градиенты на наличие inf/NaN.
  2. Если не обнаружены градиенты 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

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API