自动混合精度软件包 - torch.amp¶
为混合精度提供便捷的方法,
其中,某些操作使用 () 数据类型,而其他操作
使用低精度浮点数据类型 ():() 或 .一些运算,如线性层和卷积、
在 中要快得多。其他操作(如缩减)通常需要动态
的范围。混合精度尝试将每个运算与其适当的数据类型匹配。
torch.float32
float
lower_precision_fp
torch.float16
half
torch.bfloat16
lower_precision_fp
float32
通常,“自动混合精度训练”的数据类型为 uses 和
together,如 CUDA Automatic Mixed Precision 示例和 CUDA Automatic Mixed Precision 配方所示。
但是,
并且
是模块化的,如果需要,可以单独使用。
如 CPU 示例部分所示
,在 CPU 上使用 “自动混合精度训练/推理”
数据类型仅使用
.
torch.float16
torch.bfloat16
对于 CUDA 和 CPU,API 也单独提供:
torch.autocast("cuda", args...)
等效于 。torch.cuda.amp.autocast(args...)
torch.autocast("cpu", args...)
等效于 。对于 CPU,目前仅支持较低精度的浮点数据类型 of。torch.cpu.amp.autocast(args...)
torch.bfloat16
自动投射¶
- 类 Torch 的 Torch 类autocast(device_type, dtype=None, enabled=True, cache_enabled=None)[来源]¶
的
实例充当上下文管理器或装饰器,这些 允许脚本的区域以混合精度运行。
在这些区域中,运算在 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()
有关用法(以及梯度缩放),请参阅 CUDA 自动混合精度示例 在更复杂的场景中(例如,梯度惩罚、多个模型/损失、自定义 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 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 跟踪的 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))
启用自动转换的区域中的类型不匹配错误是一个错误;如果这是你观察到的, 请提交 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)。
- 类 torch.cuda.amp。autocast(enabled=True, dtype=torch.float16, cache_enabled=True)[来源]¶
请参阅
。 等效于
torch.cuda.amp.autocast(args...)
torch.autocast("cuda", args...)
- torch.cuda.amp。custom_fwd(fwd=无, *, cast_inputs=无)[来源]¶
自定义 autograd 函数(的
子类)方法的辅助装饰器 。有关更多详细信息,请参阅示例页面。
forward
梯度缩放¶
如果特定运算的正向传递有输入,则
该运算将产生梯度。
具有较小量级的梯度值可能无法在 中表示。
这些值将刷新为零(“下溢”),因此相应参数的更新将丢失。float16
float16
float16
为了防止下溢,“梯度缩放”将网络的损失乘以比例因子,并且 对缩放的损失调用向后传递。通过网络向后流动的梯度是 然后按相同的因子进行缩放。换句话说,梯度值具有更大的幅度, 因此,它们不会刷新为零。
每个参数的 gradient ( attribute) 应在优化器之前取消缩放
更新参数,以便 Scale Factor 不会干扰学习率。.grad
- 类 torch.cuda.amp。GradScaler(init_scale=65536.0, growth_factor=2.0, backoff_factor=0.5, growth_interval=2000, enabled=True)[来源]¶
-
- state_dict()[来源]¶
-
"scale"
- 包含当前刻度的 Python 浮点数"growth_factor"
- 包含当前增长因子的 Python 浮点数"backoff_factor"
- 包含当前回退因子的 Python 浮点数"growth_interval"
- 包含当前增长区间的 Python int"_growth_tracker"
- 一个 Python int,其中包含最近连续未跳过的步骤数。
如果未启用此实例,则返回空 dict。
- step(optimizer, *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=None)[来源]¶
更新比例因子。
如果跳过了任何优化器步骤,则 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 资格¶
在 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
CUDA 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
提升到最宽输入类型的 CUDA Ops¶
这些 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
特定于 CPU 操作的行为¶
以下列表描述了启用自动转换的区域中符合条件的操作的行为。
这些操作始终会进行自动转换,无论它们是作为 ,
作为函数或
方法。如果函数在多个命名空间中公开,则
无论命名空间如何,它们都会进行自动转换。
下面未列出的 Ops 不会进行自动转换。它们在 由他们的输入定义。但是,自动转换可能仍会更改类型 如果未列出的操作位于自动转换操作的下游,则运行其中的未列出操作。
如果一个运算未列出,我们假设它在 中的数值稳定。
如果您认为未列出的操作在 中数值不稳定 ,
请提交 issue。bfloat16
bfloat16
可自动转换为
¶
conv1d
, , , , , , , , , ,conv2d
conv3d
bmm
mm
baddbmm
addmm
addbmm
linear
matmul
_convolution
可自动转换为
¶
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
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
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 Ops¶
这些 operations 不需要特定的 dtype 来实现稳定性,而是接受多个输入
并要求 inputs 的 dtypes 匹配。如果所有输入都是 ,则运算在 中运行。如果任何输入为 ,
autocast 将所有输入强制转换为 并在 中运行运算。bfloat16
bfloat16
float32
float32
float32
cat
, ,stack
index_copy
此处未列出的一些操作(例如,像这样的二进制操作)原生会提升
inputs 的 intent 请求。如果输入是 和 的混合,则这些运算会运行并生成输出
无论是否启用了 Autocast。add
bfloat16
float32
float32
float32