自动混合精度包 - torch.cuda.amp¶
并提供混合精度的便捷方法,
其中,某些操作使用 () 数据类型,而其他操作
使用 ()。一些运算,如线性层和卷积、
在 中要快得多。其他操作(如缩减)通常需要动态
的范围。混合精度尝试将每个运算与其适当的数据类型匹配。
torch
torch.float32
float
torch.float16
half
float16
float32
通常,“自动混合精度训练”使用 and
一起使用,如 Automatic Mixed Precision 示例和 Automatic Mixed Precision 配方所示。
但是,
并且
是模块化的,如果需要,可以单独使用。
自动投射¶
-
class (device_type, enabled=True, **kwargs)[来源]
torch.
autocast
¶ 的
实例充当上下文管理器或装饰器,这些 允许脚本的区域以混合精度运行。
在这些区域中,运算在 autocast 选择的特定于运算的 dtype 中运行 提高性能,同时保持准确性。 有关详细信息,请参阅 Autocast Op Reference (自动转换操作参考)。
当进入启用自动转换的区域时,Tensor 可以是任何类型。 使用自动转换时,不应对模型或输入调用 或。
half()
bfloat16()
应仅包装网络的 forward pass,包括 loss 计算。不建议在 autocast 下向后传递。 Backward 操作以与 autocast 用于相应 forward 操作的相同类型运行。
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()
有关用法(以及梯度缩放)的信息,请参阅自动混合精度示例 在更复杂的场景中(例如,梯度惩罚、多个模型/损失、自定义 Autograd 函数)。
class AutocastModel(nn.Module): ... @autocast() def forward(self, input): ...
在启用自动转换的区域中生成的浮点 Tensor 可能是 。 返回到禁用自动转换的区域后,将它们与 floating-point 一起使用 不同 dtype 的张量可能会导致类型不匹配错误。如果是这样,则强制转换 Tensor 在 autocast 区域中生成,返回到(或根据需要返回其他 dtype)。 如果来自自动转换区域的 Tensor 已经是 ,则强制转换是无操作, 并且不会产生额外的开销。 CUDA 示例:
float16
float32
float32
# 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())
CPU 示例:
# Creates some tensors in default dtype (here assumed to be float32) a_float32 = torch.rand((8, 8), device="cpu") b_float32 = torch.rand((8, 8), device="cpu") c_float32 = torch.rand((8, 8), device="cpu") d_float32 = torch.rand((8, 8), device="cpu") with autocast(dtype=torch.bfloat16, device_type="cpu"): # torch.mm is on autocast's list of ops that should run in bfloat16. # Inputs are float32, but the op runs in bfloat16 and produces bfloat16 output. # No manual casts are required. e_bfloat16 = torch.mm(a_float32, b_float32) # Also handles mixed input types f_bfloat16 = torch.mm(d_float32, e_bfloat16) # After exiting autocast, calls f_float16.float() to use with d_float32 g_float32 = torch.mm(d_float32, f_bfloat16.float())
启用自动转换的区域中的类型不匹配错误是一个错误;如果这是你观察到的, 请提交 issue。
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)
autocast 状态是线程本地的。如果你想在新线程中启用它,上下文管理器或装饰器 必须在该线程中调用。这会影响
每个
进程与多个 GPU 一起使用时 (请参阅使用多个 GPU)。
-
类(enabled=True, dtype=torch.float16, cache_enabled=True)[来源]
torch.cuda.amp.
autocast
¶ 请参阅
。 等效于
torch.cuda.amp.autocast(args...)
torch.autocast("cuda", args...)
-
torch.cuda.amp.
custom_fwd
(fwd=None, **kwargs)[来源]¶ 自定义 autograd 函数(的
子类)方法的辅助装饰器 。有关更多详细信息,请参阅示例页面。
forward
- 参数
cast_inputs ( 或 None, optional, default=None) – 如果不是 , 在启用了自动广播的区域运行时,将转换传入的 浮点 CUDA 张量添加到目标 dtype 中(非浮点张量不受影响), 然后在禁用自动转换的情况下执行。 如果 , 的内部操作以当前自动转换状态执行。
torch.dtype
None
forward
forward
None
forward
梯度缩放¶
如果特定运算的正向传递有输入,则
该运算将产生梯度。
具有较小量级的梯度值可能无法在 中表示。
这些值将刷新为零(“下溢”),因此相应参数的更新将丢失。float16
float16
float16
为了防止下溢,“梯度缩放”将网络的损失乘以比例因子,并且 对缩放的损失调用向后传递。通过网络向后流动的梯度是 然后按相同的因子进行缩放。换句话说,梯度值具有更大的幅度, 因此,它们不会刷新为零。
每个参数的 gradient ( attribute) 应在优化器之前取消缩放
更新参数,以便 Scale Factor 不会干扰学习率。.grad
-
类 (init_scale=65536.0, growth_factor=2.0, backoff_factor=0.5, growth_interval=2000, 已启用=真)[来源]
torch.cuda.amp.
GradScaler
¶ -
-
state_dict
()[来源]¶ -
"scale"
- 包含当前刻度的 Python 浮点数"growth_factor"
- 包含当前增长因子的 Python 浮点数"backoff_factor"
- 包含当前回退因子的 Python 浮点数"growth_interval"
- 包含当前增长区间的 Python int"_growth_tracker"
- 一个 Python int,其中包含最近连续未跳过的步骤数。
如果未启用此实例,则返回空 dict。
-
step
(优化器, *args, **kwargs)[来源]¶ -
内部调用 (除非
在迭代的早期明确调用)。作为 的一部分,
将检查 infs/NaN 的梯度。
unscale_(optimizer)
optimizer
如果未找到 inf/NaN 梯度,则使用未缩放的 梯度。否则,将跳过以避免损坏参数。
optimizer.step()
optimizer.step()
*args
并转发到 。**kwargs
optimizer.step()
返回 的返回值 。
optimizer.step(*args, **kwargs)
- 参数
optimizer (torch.optim.Optimizer) – 应用梯度的优化器。
args – 任何参数。
kwargs – 任何关键字参数。
警告
目前不支持使用 Closure。
-
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) – 拥有要未缩放的梯度的优化器。
警告
每个优化器每次
调用只应调用一次, 并且仅在该优化器的 assign parameters 的所有梯度都已累积之后。 在每次调用之间为给定优化器调用
两次会触发 RuntimeError。
-
update
(new_scale=无)[来源]¶ 更新比例因子。
如果跳过了任何优化器步骤,则 scale 乘以以将其减少。如果未跳过的迭代连续发生,则 将 scale 乘以增加它。
backoff_factor
growth_interval
growth_factor
传递 (Passpass) 将手动设置新的缩放值。( 不是 直接使用,用于填充 GradScaler 的内部 scale 张量。因此,如果是一个张量,则以后对该张量的就地更改将不会进一步 影响 GradScaler 内部使用的比例。
new_scale
new_scale
new_scale
- 参数
new_scale (float or , optional, default=None) – 新比例因子。
torch.cuda.FloatTensor
-
Autocast Op 参考¶
Op 资格¶
只有 CUDA 操作才有资格进行自动转换。
在 dtype 中运行或非浮点 dtype 的运算不符合条件,并且将
无论是否启用了 Autocast,都以这些类型运行。float64
只有 out-of-place operations 和 Tensor 方法才符合条件。
显式提供 Tensor 的就地变体和调用
允许在启用自动转换的区域中使用,但不会进行自动转换。
例如,在启用了自动转换的区域可以自动转换,
但是不能。
为了获得最佳性能和稳定性,请在启用了 autocast 的情况下首选 off-of-place operations
地区。out=...
a.addmm(b, c)
a.addmm_(b, c)
a.addmm(b, c, out=d)
使用显式参数调用的操作不符合条件,
并将生成尊重参数的输出。dtype=...
dtype
特定于 Op 的行为¶
以下列表描述了启用自动转换的区域中符合条件的操作的行为。
这些操作始终会进行自动转换,无论它们是作为 ,
作为函数或
方法。如果函数在多个命名空间中公开,则
无论命名空间如何,它们都会进行自动转换。
下面未列出的 Ops 不会进行自动转换。它们在 由他们的输入定义。但是,自动转换可能仍会更改类型 如果未列出的操作位于自动转换操作的下游,则运行其中的未列出操作。
如果一个运算未列出,我们假设它在 中的数值稳定。
如果您认为未列出的操作在 中数值不稳定 ,
请提交 issue。float16
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
可以自动转换为
¶
__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
提升到最广泛输入类型的运算¶
这些 operations 不需要特定的 dtype 来实现稳定性,而是接受多个输入
并要求 inputs 的 dtypes 匹配。如果所有输入都是 ,则运算在 中运行。如果任何输入为 ,
autocast 将所有输入强制转换为 并在 中运行运算。float16
float16
float32
float32
float32
addcdiv
, , , , , , , , ,addcmul
atan2
bilinear
cross
dot
grid_sample
index_put
scatter_add
tensordot
此处未列出的一些操作(例如,像这样的二进制操作)原生会提升
inputs 的 intent 请求。如果输入是 和 的混合,则这些运算会运行并生成输出
无论是否启用了 Autocast。add
float16
float32
float32
float32
优先
选择
¶
(和 ) 的向后传递 (包装它)
可以生成在 中无法表示的渐变。在启用了自动广播的区域中,正向输入
可能是 ,这意味着向后渐变必须在 (自动转换 forward inputs to 没有帮助,因为该转换必须在 backward 中反转)。
因此,并在启用自动转换的区域中引发错误。
float16
float16
float16
float16
float32
binary_cross_entropy
BCELoss
许多模型在二进制交叉熵层之前使用 sigmoid 层。
在这种情况下,请使用 或 合并
两个图层。 并且可以安全地自动施法。
binary_cross_entropy_with_logits
BCEWithLogits