• 文档 >
  • 自动混合精度包 - torch.amp
快捷键

自动混合精度包 - torch.amp ¶

提供了混合精度的便利方法,其中一些操作使用 torch.float32float )数据类型,而其他操作使用低精度浮点数据类型( lower_precision_fp ): torch.float16half )或 torch.bfloat16 。一些操作,如线性层和卷积,在 lower_precision_fp 中运行得更快。其他操作,如归约,通常需要 float32 的动态范围。混合精度试图将每个操作匹配到适当的数据类型。

通常,“自动混合精度训练”使用 torch.float16 数据类型时,会同时使用 torch.autocasttorch.amp.GradScaler ,如自动混合精度示例和自动混合精度食谱中所示。然而, torch.autocasttorch.GradScaler 是模块化的,如果需要可以单独使用。如 torch.autocast 的 CPU 示例部分所示,“自动混合精度训练/推理”在 CPU 上使用 torch.bfloat16 数据类型时,仅使用 torch.autocast

警告

torch.cuda.amp.autocast(args...)torch.cpu.amp.autocast(args...) 将被弃用。请使用 torch.autocast("cuda", args...)torch.autocast("cpu", args...) 代替。 torch.cuda.amp.GradScaler(args...)torch.cpu.amp.GradScaler(args...) 将被弃用。请使用 torch.GradScaler("cuda", args...)torch.GradScaler("cpu", args...) 代替。

torch.autocasttorch.cpu.amp.autocast 在 1.10 版本中新增。

自动类型转换说明

torch.amp.autocast_mode.is_autocast_available(device_type)[source][source] 说明

返回一个布尔值,指示是否在 device_type 上可用自动类型转换。

参数:

device_type (str) – 要使用的设备类型。可能的值有:‘cuda’,‘cpu’,‘mtia’,‘xpu’等。类型与 torch.device 的类型属性相同。因此,您可以使用 Tensor.device.type 获取张量的设备类型。

返回类型:

bool

class torch.autocast(device_type, dtype=None, enabled=True, cache_enabled=None)[source][source]

autocast 的实例用作上下文管理器或装饰器,允许脚本中的某些区域以混合精度运行。

在这些区域中,操作以 autocast 选择的特定操作 dtype 运行,以提高性能同时保持精度。有关详细信息,请参阅 Autocast 操作参考。

当进入自动类型转换区域时,张量可以是任何类型。在使用自动类型转换时,您不应在您的模型或输入上调用 half()bfloat16()

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 torch.autocast(device_type="cuda"):
        output = model(input)
        loss = loss_fn(output, target)

    # Exits the context manager before backward()
    loss.backward()
    optimizer.step()

请参阅自动混合精度示例,了解在更复杂场景(例如梯度惩罚、多个模型/损失、自定义 autograd 函数)中的使用(包括梯度缩放)。

也可以用作装饰器,例如用于模型的 forward 方法:

class AutocastModel(nn.Module):
    ...
    @torch.autocast(device_type="cuda")
    def forward(self, input):
        ...

在自动转换区域产生的浮点张量可能为 float16 。返回到自动转换禁用区域后,使用它们与不同 dtypes 的浮点张量可能会导致类型不匹配错误。如果是这样,请将自动转换区域产生的张量转换回 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 torch.autocast(device_type="cuda"):
    # 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())

CPU 训练示例:

# 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()

CPU 推理示例:

# 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)

CPU 推理示例与 Jit Trace

class TestModel(nn.Module):
    def __init__(self, input_size, num_classes):
        super().__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))

在自动类型转换启用的区域内类型不匹配错误是一个 bug;如果您观察到这种情况,请提交一个问题。

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 torch.autocast(device_type="cuda"):
    e_float16 = torch.mm(a_float32, b_float32)
    with torch.autocast(device_type="cuda", 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.DataParalleltorch.nn.parallel.DistributedDataParallel 当与每个进程中的多个 GPU 一起使用时(参见使用多个 GPU)。

参数:
  • device_type (str, required) – 要使用的设备类型。可能的值有:‘cuda’,‘cpu’,‘mtia’,‘xpu’,和‘hpu’。类型与 torch.device 的类型属性相同。因此,您可以使用 Tensor.device.type 获取张量的设备类型。

  • enabled (bool, optional) – 是否在该区域启用自动转换。默认: True

  • dtype (torch_dtype, optional) – 自动转换中运行的 ops 的数据类型。如果 dtypeNone ,则使用默认值(CUDA 为 torch.float16 ,CPU 为 torch.bfloat16 ),由 get_autocast_dtype() 给出。默认: None

  • cache_enabled (bool, 可选) – 是否启用 autocast 内部的权重缓存。默认: True

torch.amp.custom_fwd(fwd=None, *, device_type, cast_inputs=None)[source][source]

创建一个用于自定义 autograd 函数的 forward 方法的辅助装饰器。

Autograd 函数是 torch.autograd.Function 的子类。请参阅示例页面以获取更多详细信息。

参数:
  • device_type (str) – 要使用的设备类型。‘cuda’,‘cpu’,‘mtia’,‘xpu’等。类型与 torch.device 的 type 属性相同。因此,您可以使用 Tensor.device.type 获取张量的设备类型。

  • cast_inputs ( torch.dtype 或 None, 可选,默认=None) – 如果不是 None ,当 forward 在启用自动转换的区域运行时,将传入的浮点张量转换为目标数据类型(非浮点张量不受影响),然后禁用自动转换执行 forward 。如果 Noneforward 的内部操作以当前自动转换状态执行。

备注

如果装饰的 forward 在启用自动转换的区域外被调用, custom_fwd 是一个空操作, cast_inputs 没有效果。

torch.amp.custom_bwd(bwd=None, *, device_type)[source][source]

创建自定义自动微分函数反向方法的辅助装饰器。

自动微分函数是 torch.autograd.Function 的子类。确保 backward 在与 forward 相同的 autocast 状态下执行。请参阅示例页面以获取更多详细信息。

参数:

device_type (str) – 要使用的设备类型。‘cuda’,‘cpu’,‘mtia’,‘xpu’等。类型与 torch.device 的类型属性相同。因此,您可以使用 Tensor.device.type 获取张量的设备类型。

class torch.cuda.amp.autocast(enabled=True, dtype=torch.float16, cache_enabled=True)[source][source]

torch.autocast

torch.cuda.amp.autocast(args...) 已弃用。请使用 torch.amp.autocast("cuda", args...) 代替。

torch.cuda.amp.custom_fwd(fwd=None, *, cast_inputs=None)[source][source]

torch.cuda.amp.custom_fwd(args...) 已弃用。请使用 torch.amp.custom_fwd(args..., device_type='cuda') 代替。

torch.cuda.amp.custom_bwd(bwd)[source][source]

torch.cuda.amp.custom_bwd(args...) 已弃用。请使用 torch.amp.custom_bwd(args..., device_type='cuda') 代替。

class torch.cpu.amp.autocast(启用=True, 数据类型=torch.bfloat16, 缓存启用=True)[source][source] ¶

请参阅 torch.autocasttorch.cpu.amp.autocast(args...) 已弃用。请使用 torch.amp.autocast("cpu", args...) 代替。

梯度缩放

如果特定操作的 forward 过程有 float16 个输入,则该操作的 backward 过程将产生 float16 个梯度。梯度值可能无法在 float16 中表示,其值将清零(下溢),因此相应参数的更新将丢失。

为了防止下溢,“梯度缩放”会将网络的损失乘以一个缩放因子,并对缩放后的损失进行反向传播。然后,通过网络反向流动的梯度也会按相同的因子进行缩放。换句话说,梯度值具有更大的幅度,因此不会冲刷到零。

在优化器更新参数之前,每个参数的梯度( .grad 属性)应该进行未缩放处理,以确保缩放因子不会干扰学习率。

备注

AMP/fp16 可能不适用于每个模型!例如,大多数 bf16 预训练模型无法在 fp16 数值范围内运行,该范围最大为 65504,这会导致梯度上溢而不是下溢。在这种情况下,缩放因子可能会小于 1,作为将梯度转换为 fp16 动态范围内可表示的数字的尝试。虽然人们可能期望缩放因子始终大于 1,但我们的 GradScaler 并不保证这一点以保持性能。如果在运行 AMP/fp16 时遇到损失或梯度中的 NaN,请验证您的模型是否兼容。

class torch.cuda.amp.GradScaler(init_scale=65536.0, growth_factor=2.0, backoff_factor=0.5, growth_interval=2000, enabled=True)[source][source]

请使用 torch.amp.GradScaler("cuda", args...) 代替。 torch.cuda.amp.GradScaler(args...) 已弃用。

class torch.cpu.amp.GradScaler(init_scale=65536.0, growth_factor=2.0, backoff_factor=0.5, growth_interval=2000, enabled=True)[source][source]

请使用 torch.amp.GradScaler("cpu", args...) 代替。 torch.cpu.amp.GradScaler(args...) 已弃用。

自动转换操作参考 ¶

沉浸式翻译

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 中是数值不稳定的,请提交一个问题。

支持自动转换为 float16 的 CUDA 操作

__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

支持自动转换为 float32 的 CUDA 操作

__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 )在无需自动类型转换干预的情况下会提升输入。如果输入是 float16float32 的混合,这些操作将在 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_entropyBCELoss 在启用自动类型转换的区域将引发错误。

许多模型在二元交叉熵层之前使用 Sigmoid 层。在这种情况下,可以使用 torch.nn.functional.binary_cross_entropy_with_logits()torch.nn.BCEWithLogitsLoss 将两个层合并。 binary_cross_entropy_with_logitsBCEWithLogits 可以安全地进行自动类型转换。

XPU 操作特定行为(实验性)¶

以下列表描述了在自动转换启用区域中符合条件的操作的行为。这些操作无论作为 torch.nn.Module 的一部分、作为一个函数还是作为一个 torch.Tensor 方法被调用,都会始终通过自动转换。如果函数在多个命名空间中公开,它们无论在哪个命名空间都会通过自动转换。

未列出的操作不会通过自动转换。它们将在由它们的输入定义的类型中运行。然而,如果未列出的操作在自动转换操作之后,自动转换仍可能改变它们运行的类型。

如果一个操作未列出,我们假设它在 float16 中是数值稳定的。如果您认为一个未列出的操作在 float16 中是数值不稳定的,请提交一个问题。

支持自动转换为 float16 的 XPU 操作

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, RNNCell

支持自动转换为 float32 的 XPU 操作

__pow__, __rdiv__, __rpow__, __rtruediv__, binary_cross_entropy_with_logits, cosine_embedding_loss, cosine_similarity, cumsum, dist, exp, group_norm, hinge_embedding_loss, kl_div, l1_loss, layer_norm, log, log_softmax, margin_ranking_loss, nll_loss, normalize, poisson_nll_loss, pow, reciprocal, rsqrt, soft_margin_loss, softmax, softmin, sum, triplet_margin_loss

将提升到最宽输入类型的 XPU 操作

这些操作不需要特定的 dtype 以保证稳定性,但需要多个输入,并且要求输入的 dtype 匹配。如果所有输入都是 float16 ,则操作在 float16 下运行。如果任何输入是 float32 ,则自动转换将所有输入转换为 float32 ,并在 float32 下运行操作。

bilinear, cross, grid_sample, index_put, scatter_add, tensordot

一些未在此列出的操作(例如,二进制操作 add )会原生提升输入,无需自动类型转换的干预。如果输入是 float16float32 的混合,这些操作将在 float32 中运行并产生 float32 输出,无论自动类型转换是否启用。

CPU 操作特定行为

以下列表描述了在自动类型转换启用区域中符合条件的操作的行为。这些操作无论作为 torch.nn.Module 的一部分、作为函数还是作为 torch.Tensor 方法被调用,都会始终通过自动类型转换。如果函数在多个命名空间中公开,无论命名空间如何,都会通过自动类型转换。

未列出的操作不会通过自动类型转换。它们将在由其输入定义的类型中运行。然而,如果未列出的操作是自动类型转换操作的下级,自动类型转换仍可能更改它们运行的类型。

如果一个操作未列出,我们假设它在 bfloat16 中数值稳定。如果您认为一个未列出的操作在 bfloat16 中数值不稳定,请提交问题。 float16 共享了 bfloat16 的列表。

可以自动转换到 bfloat16 的 CPU 操作 bfloat16

conv1d, conv2d, conv3d, bmm, mm, linalg_vecdot, baddbmm, addmm, addbmm, linear, matmul, _convolution, conv_tbc, mkldnn_rnn_layer, conv_transpose1d, conv_transpose2d, conv_transpose3d, prelu, scaled_dot_product_attention, _native_multi_head_attention

可以自动转换到 float32 的 CPU 操作 float32

avg_pool3d, binary_cross_entropy, grid_sampler, grid_sampler_2d, _grid_sampler_2d_cpu_fallback, grid_sampler_3d, polar, prod, 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, cosine_embedding_loss, nll_loss, nll_loss2d, hinge_embedding_loss, poisson_nll_loss, cross_entropy_loss, l1_loss, huber_loss, margin_ranking_loss, soft_margin_loss, triplet_margin_loss, multi_margin_loss, ctc_loss, kl_div, multilabel_margin_loss, binary_cross_entropy_with_logits, 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_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, geqrf, _lu_with_info, qr, svd, 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 操作@0#

这些操作不需要特定的数据类型以保证稳定性,但需要多个输入,并且要求输入的数据类型匹配。如果所有输入都是 bfloat16 ,则操作在 bfloat16 下运行。如果任何输入是 float32 ,则 autocast 将所有输入转换为 float32 ,并在 float32 下运行该操作。

cat, stack, index_copy

列表中未列出的某些操作(例如,二进制操作 add )会原生提升输入,无需 autocast 干预。如果输入是 bfloat16float32 的混合,则这些操作在 float32 下运行,并产生 float32 输出,无论 autocast 是否启用。


© 版权所有 PyTorch 贡献者。

使用 Sphinx 构建,主题由 Read the Docs 提供。

文档

访问 PyTorch 的全面开发者文档

查看文档

教程

获取初学者和高级开发者的深入教程

查看教程

资源

查找开发资源并获得您的疑问解答

查看资源