自动混合精度包 - torch.amp

torch.amp 提供了混合精度计算的便捷方法,在这种模式下,某些操作使用 torch.float32 (float) 数据类型,而其他操作则使用较低精度的数据类型(如 torch.float16 (half) 或 torch.bfloat16)。例如,线性层和卷积在低精度数据类型中运行速度更快。然而,归约等运算符通常需要 torch.float32 的动态范围。混合精度计算会根据每个操作的特点选择合适的数据类型。

通常,使用数据类型为torch.float16的“自动混合精度训练”会同时使用torch.autocasttorch.amp.GradScaler,如在自动混合精度示例自动混合精度实用技巧中所示。然而,torch.autocasttorch.amp.GradScaler 是模块化的,并且可以根据需要单独使用。如torch.autocast中的CPU示例部分所示,使用数据类型为torch.bfloat16的“自动混合精度训练/推理”在CPU上仅使用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)[源代码]

返回一个布尔值,指示 device_type 设备上是否支持自动类型转换(autocast)。

参数

device_type (str) – 设备类型。可能的值包括:‘cuda’, ‘cpu’, ‘xpu’ 等等。该类型与 torch.devicetype 属性相同,因此你可以通过 Tensor.device.type 获取张量的设备类型。

返回类型

bool

classtorch.autocast(device_type, dtype=None, enabled=True, cache_enabled=None)[源代码]

实例化的 autocast 用作上下文管理器或装饰器,使你的脚本中的一些区域可以以混合精度运行。

在这些区域中,操作会使用自动类型转换选定的特定数据类型来运行,从而提升性能并保持准确性。详细信息请参阅自动类型转换操作参考

当进入启用了autocast的区域时,张量可以是任何类型。在使用autocasting的情况下,你不应该调用half()bfloat16()方法来处理你的模型或输入数据。

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

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

参见自动混合精度示例,了解在更复杂场景(如梯度惩罚、多个模型和损失函数以及自定义autograd函数)中使用自动混合精度和梯度缩放的方法。

autocast 还可以用作装饰器,例如在你的模型的 forward 方法上:

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

在启用了autocast的区域内生成的浮点张量可能是float16类型。返回到禁用autocast的区域后,使用不同数据类型的浮点张量可能会导致类型不匹配错误。如果出现这种情况,请将autocast区域内生成的张量重新转换为float32(或所需的其他数据类型)。如果来自autocast区域的张量已经是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)

基于Jit Trace的CPU推理示例:

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) 子区域可以嵌套在启用 autocast 的区域内。局部禁用 autocast 可以让你强制子区域以特定的 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)

autocast 状态是线程本地的。如果你想在新线程中启用它,需要在线程中调用上下文管理器或装饰器。这会影响 torch.nn.DataParalleltorch.nn.parallel.DistributedDataParallel,当每个进程使用多个 GPU 时(参见与多 GPU 协同工作)。

参数
  • device_type (str, required) – 设备类型。可能的值为:‘cuda’, ‘cpu’, ‘xpu’ 和 ‘hpu’。该类型与torch.devicetype 属性相同,因此你可以通过 Tensor.device.type 获取张量的设备类型。

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

  • dtype (torch_dtype, optional) – 数据类型,用于autocast中运行的操作。如果dtypeNone,则使用默认值(对于CUDA为torch.float16,对于CPU为torch.bfloat16),由get_autocast_dtype() 提供。 默认: None

  • cache_enabled (bool, optional) – 是否启用autocast功能中的权重缓存。默认值: True

torch.amp.custom_fwd(fwd=None, *, device_type, cast_inputs=None)[源代码]

为自定义自动微分函数的forward方法创建一个辅助装饰器。

Autograd 函数是 torch.autograd.Function 的子类。更多详情请参见示例页面

参数
  • device_type (str) – 设备类型,如 ‘cuda’, ‘cpu’, ‘xpu’ 等。该类型与 torch.devicetype 属性相同。因此,你可以通过 Tensor.device.type 获取张量的设备类型。

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

注意

如果装饰过的forward在未启用autocast的区域中被调用,custom_fwd将不做任何操作,并且cast_inputs也不会产生影响。

torch.amp.custom_bwd(bwd=None, *, device_type)[源代码]

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

Autograd 函数是 torch.autograd.Function 的子类。它确保 backward 方法在与 forward 相同的 autocast 状态下执行。更多详情请参阅 示例页面

参数

device_type (str) – 设备类型,如 ‘cuda’, ‘cpu’, ‘xpu’ 等。该类型与 torch.devicetype 属性相同。因此,你可以通过 Tensor.device.type 获取张量的设备类型。

torch.cuda.amp.autocast(enabled=True, dtype=torch.float16, cache_enabled=True)[源代码]

参见 torch.autocast

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

torch.cuda.amp.custom_fwd(fwd=None, *, cast_inputs=None)[源代码]

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

torch.cuda.amp.custom_bwd(bwd)[源代码]

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

torch.cpu.amp.autocast(enabled=True, dtype=torch.bfloat16, cache_enabled=True)[源代码]

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

梯度缩放

如果某个操作的前向传递使用了float16输入,那么该操作的反向传递将产生float16梯度。对于幅度较小的梯度值,float16可能无法准确表示它们。这些小幅度的梯度值会被舍入为零(“下溢”),导致相应参数的更新丢失。

为了防止下溢,“梯度缩放”会将网络的损失乘以一个比例因子,并在缩放后的损失上执行反向传递。在网络中反向流动的梯度会被相同的因子缩放。换句话说,梯度值具有更大的幅度,因此不会变为零。

在优化器更新参数之前,应将每个参数的梯度(.grad 属性)进行去缩放处理,以防止缩放因子影响学习率。

注意

AMP/fp16 并不适用于所有模型!例如,大多数 bf16 预训练的模型无法在 fp16 的数值范围内(最大值为 65504)正常运行,并会导致梯度溢出而不是下溢。在这种情况下,缩放因子可能会降低到小于 1,以尝试将梯度调整到可以在 fp16 动态范围内表示的数值。虽然人们通常期望缩放因子始终大于 1,但我们的 GradScaler 不会为此做出保证,以保持性能。如果你在使用 AMP/fp16 运行时遇到损失或梯度中的 NaN 值,请验证你的模型是否兼容。

torch.cuda.amp.GradScaler(init_scale=65536.0, growth_factor=2.0, backoff_factor=0.5, growth_interval=2000, enabled=True) [源代码](<_modules/torch/cuda/amp/grad_scaler.html#GradScaler)

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

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

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

自动类型转换操作参考

操作资格

运行在 float64 或非浮点数数据类型的操作不受自动转换的影响,无论是否启用自动转换功能,这些操作都会使用相应数据类型执行。

只有非原地操作和Tensor方法才有资格进行自动类型转换。在启用了自动类型转换的区域中,虽然允许使用显式提供out=... 参数的原地变体和其他调用,但这些不会通过自动类型转换处理。例如,在一个启用自动类型转换的区域内,a.addmm(b, c) 可以进行自动类型转换,但是 a.addmm_(b, c)a.addmm(b, c, out=d) 不能。为了获得最佳性能和稳定性,在启用了自动类型转换的区域内,建议优先使用非原地操作。

带有显式 dtype=... 参数的 Ops 不符合条件,其输出会遵循该 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,autocast会将所有输入转换为float32并以float32运行操作。

addcdiv, addcmul, atan2, bilinear, cross, dot, grid_sample, index_put, scatter_add, tensordot

此处未列出的一些操作(例如二元操作如add)会自动提升输入类型而无需autocasting的干预。如果输入是float16float32的混合,则这些操作将以float32运行,并生成float32输出,无论autocast是否启用。

建议使用binary_cross_entropy_with_logits代替binary_cross_entropy

torch.nn.functional.binary_cross_entropy()(及其包装类torch.nn.BCELoss)的反向传播可能会产生无法用float16表示的梯度。在autocast启用的区域中,前向输入可能是float16类型,这意味着反向传播计算出的梯度也必须可以用float16来表示(将float16类型的前向输入自动转换为float32没有帮助,因为在反向传播过程中需要将其恢复)。因此,在autocast启用的区域中,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 操作

这些操作不需要特定的数据类型来保证稳定性,但需要多个输入,并且要求这些输入的数据类型必须一致。如果所有输入都是float16,则操作将以float16运行。如果有任何一个输入是float32,autocast会将所有输入转换为float32并以float32运行操作。

bilinear, cross, grid_sample, index_put, scatter_add, tensordot

此处未列出的一些操作(例如二元操作如add)会自动提升输入类型而无需autocasting的干预。如果输入是float16float32的混合,则这些操作将以float32运行,并生成float32输出,无论autocast是否启用。

CPU 操作行为

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

以下未列出的操作不会进行自动类型转换。它们会根据输入定义的类型来运行。但是,如果这些操作位于已经进行了自动类型转换的操作下游,则自动类型转换仍然可能会改变这些未列出操作的运行类型。

如果某个操作未列出,我们假设它在bfloat16中是数值稳定的。如果你认为某个未列出的操作在bfloat16中是数值不稳定的,请提交一个问题。需要注意的是,float16bfloat16使用相同的列表。

可以自动转换为 的CPU操作

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操作

avg_pool2d, avg_pool3d, adaptive_avg_pool2d, adaptive_avg_pool3d, batch_norm, channel_shuffle, cosine_similarity, cross_entropy, embedding, gelu, glu, group_norm, instance_norm, layer_norm, local_response_norm, log_softmax, max_pool2d_with_indices, max_unpool2d, mse_loss, multi_head_attention_forward, nll_loss, one_hot, pad, pointwise_conv2d, prelu, relu6, roi_align, selu, softmax, softmin, softplus, softsign, threshold It seems like you might have been looking for a list of PyTorch or similar deep learning framework operations. However, the provided list appears to be a mix of functions and does not match the initial request. If you need a specific set of operations or if there's another context in which these are needed, please clarify your requirements so I can provide more accurate assistance.

将 CPU 操作提升至最宽输入类型的操作

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

cat, stack, index_copy

此处未列出的一些操作(例如二元操作如add)会自动提升输入类型而无需autocasting的干预。如果输入是bfloat16float32的混合体,这些操作将以float32运行,并生成float32输出,无论autocast是否启用。

本页目录