# mypy: 允许未类型化定义
导入
集合
导入 functools
导入
警告
来自
打字
导入
任何,
可选
导入
火炬
来自
torch 的类型
导入 _dtype
尝试:
导入 numpy as np
HAS_NUMPY = 真实
除了
模块未找到错误:
HAS_NUMPY = 假
np = 无
# 类型:忽略[赋值]
全部 = [
autocast 装饰器,
"自动转换",
是否支持 autocast,
"custom_fwd",
"custom_bwd",
]
[文档]def is_autocast_available(device_type: str) -> bool:
r"""
返回一个布尔值,指示是否在 :attr:`device_type` 上可用自动类型转换。
Args:
device_type(str): 要使用的设备类型。可能的值有:'cuda'、'cpu'、'mtia'、'xpu' 等。
类型与 :class:`torch.device` 的 `type` 属性相同。
因此,您可以使用 `Tensor.device.type` 获取张量的设备类型。
"""
返回是否支持自动铸造成就可用(device_type)
def autocast_decorator(自动铸件实例,
函数):
@functools.包装(
函数)
def 装饰自动铸件(*
参数, **kwargs):
替换为
自动铸件实例:
返回
函数(*
参数, **kwargs)
装饰自动铸件.
支持脚本 =
在脚本模式下不支持 @autocast() 装饰器
# 类型:忽略[已定义]
返回
装饰_autocast
[文档]
类
自动播:
r""
class:`autocast` 的实例作为上下文管理器或装饰器
允许您的脚本中的某些区域以混合精度运行。
在这些区域,操作以由 autocast 选择的操作特定数据类型运行
以提高性能的同时保持精度。
有关详细信息,请参阅::ref:`Autocast 操作参考`。
当进入自动类型转换区域时,张量可以是任何类型。
在使用自动类型转换时,不应在您的模型或输入上调用 `half()` 或 `bfloat16()`。
`:class:`autocast` 应仅包装您网络的正向传递(传递),包括损失
计算过程。在自动类型转换下不建议进行反向传递。
后向操作运行与 autocast 用于对应前向操作相同的类型。
CUDA 设备示例:
默认精度下创建模型和优化器
model = Net().cuda()
优化器 = optim.SGD(model.parameters(), ...)
for input, target in data:
optimizer.zero_grad()
# 启用前向传递(模型 + 损失)的自动类型转换
with torch.autocast(device_type="cuda"):
output = 模型(input)
loss = 损失函数(output, target)
# 在 backward() 之前退出上下文管理器
loss.backward()
optimizer.step()
请参阅:ref:`自动混合精度示例`了解用法(包括梯度缩放)
在更复杂的情况下(例如,梯度惩罚、多个模型/损失、自定义自动微分函数)。
class:`autocast` 也可以用作装饰器,例如,在您的模型的 ``forward`` 方法上使用:
class AutocastModel(nn.Module):
...
@torch.autocast(device_type="cuda")
def forward(self, input):
...
在启用自动铸造的区域产生的浮点张量可能是 ``float16``。
返回到禁用自动铸造的区域后,使用它们进行浮点操作
不同数据类型的张量可能会导致类型不匹配错误。如果是这样,请将自动转换区域产生的张量(或多个张量)转换回 `float32`(或所需的其它数据类型)。
如果自动转换区域的张量已经是 `float32` 类型,则转换操作不会执行,也不会产生额外的开销。
如果自动转换区域的张量已经是 `float32`,则转换操作不会执行,
也不会产生额外的开销。
CUDA 示例::
# 创建一些默认数据类型(此处假设为 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 在 autocast 的操作列表中,应运行在 float16 格式。
输入是 float32,但操作在 float16 上运行并产生 float16 输出。
无需手动转换。
e_float16 = torch.mm(a_float32, b_float32)
同样处理混合输入类型。
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 训练示例::
默认精度下创建模型和优化器
创建 Net 模型
优化器 = optim.SGD(model.parameters(), ...)
for 循环遍历 epochs
for input, target in data:
optimizer.zero_grad()
# 运行带有自动转换的前向传递。
with torch.autocast(device_type="cpu", dtype=torch.bfloat16):
output = 模型(input)
loss = 损失函数(output, target)
loss.backward()
optimizer.step()
CPU 推理示例::
创建默认精度模型
model = Net().eval()
with torch.autocast(device_type="cpu", dtype=torch.bfloat16):
for input in data:
# 运行带有自动转换的前向传递。
output = 模型(input)
使用 Jit Trace 的 CPU 推理示例:
class TestModel(nn.Module):
def __init__(self, 输入大小, 类别数):
super().__init__()
self.fc1 = nn.Linear(输入大小, 类别数)
def forward(self, x):
return self.fc1(x)
输入大小 = 2
num_classes = 2
model = TestModel(input_size, num_classes).eval()
# 目前建议禁用 Jit Autocast Pass,
# 因为问题: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)
模型运行
for _ in range(3):
model(torch.randn(1, 输入大小))
在自动转换区域中出现的类型不匹配错误是一个错误;如果您观察到这种情况,
请提交一个问题。
``autocast(enabled=False)`` 子区域可以嵌套在启用 autocast 的区域中。
局部禁用 autocast 可能很有用,例如,如果您想强制子区域
在特定的 ``dtype`` 中运行。禁用 autocast 可以让您拥有显式的控制权,
执行类型。在子区域中,来自周边区域的输入在使用前应转换为 ``dtype``
应在使用前将输入转换为 ``dtype`` 类型::
# 创建一些默认数据类型(此处假设为 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):
# 调用 e_float16.float() 确保执行为 float32
# (因为 e_float16 是在 autocasted 区域创建的,所以有必要)
f_float32 = torch.mm(c_float32, e_float16.float())
在重新进入自动类型转换开启区域时,无需手动转换。
无论输入类型如何,torch.mm 再次以 float16 运行并产生 float16 输出。
g_float16 = torch.mm(d_float32, f_float32)
自动铸态是线程局部的。如果你想在新的线程中启用它,请使用上下文管理器或装饰器
必须在那个线程中调用。这影响::class:`torch.nn.DataParallel`和
`:class:`torch.nn.parallel.DistributedDataParallel` 在每个进程使用超过一个 GPU 时
(参见::ref:`使用多个 GPU》)
参数:
device_type(str, required): 使用设备类型。可能的值有:'cuda', 'cpu', 'mtia', 'xpu', 和 'hpu'。
类型与 :class:`torch.device` 的 `type` 属性相同。
因此,您可以使用 `Tensor.device.type` 获取张量的设备类型。
enabled(bool, optional): 是否在该区域启用自动类型转换。
默认:``True``
dtype(torch_dtype, optional): 自动类型转换中操作的数值类型。它使用默认值
(对于 CUDA 为 ``torch.float16``,对于 CPU 为 ``torch.bfloat16``),由
`torch.get_autocast_dtype`,如果 `dtype` 为 `None`。
默认:`None`
cache_enabled(bool, 可选): 在 autocast 内部的权重缓存是否启用。
默认:``True``
"""
def __init__(
self,
设备类型: str,
数据类型:
可选[
数据类型] =
无,
启用:
布尔值 = True,
cache_enabled: 可选[bool] =
无,
):
如果
不 isinstance(
设备类型, str):
抛出
值错误(
f预期 `device_type` 为 `str` 类型,实际得到:`{
类型(
设备类型)}
)
如果 dtype
是
无:
dtype = PyTorch.
获取自动类型转换(
设备类型)
如果
PyTorch._jit_internal.
是否正在脚本化():
self.启用 =
启用
self.设备 =
设备类型
self.快速数据类型 = dtype
断言 dtype
是
不
无
返回
self.设备 =
设备类型
如果
不
自动广播是否可用(self.
设备):
抛出
运行时错误(
f"用户指定了一个不支持的自动转换设备类型"{self.
设备}
)
self.自定义后端名称 =
PyTorch._C._get_privateuse1_backend_name()
self.快速数据类型 =
PyTorch.
获取自动类型转换(self.
设备)
如果 self.
设备 == self.
自定义后端名称:
必要的函数 = [
"获取支持自动放大(AMP)的数据类型",
]
消息 = f
尝试使用 AMP 与`{self.
自定义后端名称}
后端,但后端还没有“
消息 +=
注册了一个模块或该模块缺少一些必要的功能。后端应该注册
消息 +=
一个由 `torch._register_device_module` 定义的模块,并且该模块必须具有以下函数:
输入文本翻译为简体中文为:
\n"
消息 +=
`get_amp_supported_dtype() -> List[torch.dtype]`. 翻译为:`获取支持自动混合精度的数据类型() -> torch.dtype 列表`.
输入文本翻译为简体中文为:
\n"
断言
有属性(
PyTorch, self.
自定义后端名称),
消息
self.自定义设备模块 = getattr(
PyTorch, self.
自定义后端名称)
for 函数
在
必要的函数:
断言
有属性(self.
自定义设备模块,
函数), (
消息 + f
但是函数 `{
函数}
缺少。
输入文本翻译为简体中文为:
\n"
)
self.缓存已启用 =
PyTorch.is_autocast_cache_enabled()
如果 (
启用
和
PyTorch.cuda.
转换.
常见.
AMP 绝对不可用()
和 self.
设备 == "cuda"
):
警告.
警告(
"用户提供的设备类型为'cuda',但 CUDA 不可用。禁用"
)
启用 =
假
如果 dtype
是
不
无:
self.快速数据类型 = dtype
如果
缓存已启用
是
不
无:
self.缓存已启用 = cache_enabled
如果 self.
设备 == "cpu":
支持的数据类型 = [
PyTorch.bfloat16,
PyTorch.float16]
如果 self.
快速数据类型
不
在
支持的数据类型
和
启用:
错误信息 =
在 CPU 自动类型转换中,但目标数据类型不受支持。禁用自动转换。
输入文本翻译为简体中文为:\n"
错误信息 +=
CPU 自动类型转换仅支持数据类型为
错误信息 += (
“,”.
连接(str(
数据类型) for dtype
在
支持的数据类型) +
"目前。"
)
警告.
警告(
错误信息)
启用 =
假
如果...否则 self.
设备 ==
翻译:
支持的数据类型 = [
PyTorch.bfloat16,
PyTorch.float16]
如果 self.
快速数据类型
不
在
支持的数据类型:
错误信息 =
"在 MTIA autocast 中,但目标数据类型不受支持。禁用 autocast。
输入文本翻译为简体中文为:\n"
错误信息 +=
"MTIA Autocast 目前仅支持 torch.bfloat16 和 torch.float16 数据类型。"
警告.
警告(
错误信息)
启用 =
假
如果...否则 self.
设备 ==
XPU:
支持的数据类型 = [
PyTorch.bfloat16,
PyTorch.float16]
如果 self.
快速数据类型
不
在
支持的数据类型:
错误信息 =
"在 XPU autocast 中,但目标数据类型不受支持。禁用 autocast。
输入文本翻译为简体中文为:\n"
错误信息 +=
"XPU Autocast 目前仅支持 torch.bfloat16 和 torch.float16 数据类型。"
警告.
警告(
错误信息)
启用 =
假
如果...否则 self.
设备 ==
知识产权:
支持的数据类型 = [
PyTorch.bfloat16,
PyTorch.float16]
如果 self.
快速数据类型
不
在
支持的数据类型:
错误信息 =
在 IPU autocast 中,但目标数据类型不受支持。禁用 autocast。
输入文本翻译为简体中文为:\n"
错误信息 +=
目前 IPU Autocast 仅支持 torch.bfloat16 和 torch.float16 数据类型。
警告.
警告(
错误信息)
启用 =
假
如果...否则 self.
设备 ==
hpu:
支持的数据类型 = [
PyTorch.bfloat16,
PyTorch.float16]
如果 self.
快速数据类型
不
在
支持的数据类型:
错误信息 =
"在 HPU autocast 中,但目标数据类型不受支持。禁用 autocast。
输入文本翻译为简体中文为:\n"
错误信息 +=
"HPU Autocast 目前仅支持 torch.bfloat16 和 torch.float16 数据类型。"
警告.
警告(
错误信息)
启用 =
假
如果...否则 self.
设备 == self.
自定义后端名称:
支持的数据类型 = self.
自定义设备模块.
获取支持的放大数据类型()
如果 self.
快速数据类型
不
在
支持的数据类型:
错误信息 = f
在{self.
自定义后端名称}
autocast 中,但目标数据类型不受支持。
错误信息 += f
禁用自动转换。
输入文本翻译为简体中文为:\n {self.
自定义后端名称}
自动转换仅支持以下数据类型 "
错误信息 += (
“,”.
连接(str(
数据类型) for dtype
在
支持的数据类型) +
"目前。"
)
警告.
警告(
错误信息)
启用 =
假
如果...否则 self.
设备 ==
cuda:
如果 (
启用
和 self.
快速数据类型 ==
PyTorch.bfloat16
和
不
PyTorch.cuda.
支持 BF16()
):
抛出
运行时错误(
"当前 CUDA 设备不支持 bfloat16 数据类型。请将数据类型切换为 float16。"
)
如果...否则 self.
设备 ==
国会议员:
支持的数据类型 = [
PyTorch.bfloat16,
PyTorch.float16]
如果 self.
快速数据类型
不
在
支持的数据类型:
错误信息 = (
在 MPS autocast 中,但目标数据类型不受支持。禁用 autocast。
输入文本翻译为简体中文为:\n"
"MPS Autocast 目前仅支持 torch.bfloat16 和 torch.float16 数据类型。"
)
警告.
警告(
错误信息)
启用 =
假
如果...否则 self.
快速数据类型 ==
PyTorch.bfloat16:
如果
不
PyTorch.
后端.
会员.
macOS 或更高版本(14, 0):
错误信息 = (
在 MPS autocast 中,但目标数据类型 torch.bfloat16 不受支持
在低于 14 的 macOS 版本上。禁用 autocast。
)
警告.
警告(
错误信息)
启用 =
假
如果...否则 self.
设备 == "xla":
支持的数据类型 = [
PyTorch.float16,
PyTorch.bfloat16]
如果 self.
快速数据类型
不
在
支持的数据类型:
错误信息 =
在 XLA autocast 中,但目标数据类型不受支持。禁用 autocast。
输入文本翻译为简体中文为:\n"
错误信息 += (
"XLA Autocast 目前仅支持 torch.bfloat16 数据类型。"
)
警告.
警告(
错误信息)
启用 =
假
self.启用 =
启用
def __进入__(self):
如果
PyTorch._jit_internal.
是否正在脚本化():
断言 self.
快速数据类型
是
不
无
返回 self
self.之前缓存启用 =
PyTorch.is_autocast_cache_enabled()
self.上一个 =
PyTorch.
是否启用自动转换(self.
设备)
self.之前快速数据类型 =
PyTorch.
获取自动类型转换(self.
设备)
PyTorch.
设置自动转换启用(self.
设备, self.
启用)
PyTorch.
设置自动类型转换(self.
设备, self.
快速数据类型) # type: ignore[arg-type]
PyTorch.
自动转换增加嵌套层级()
PyTorch.set_autocast_cache_enabled(self.
_缓存启用)
仅派发到 PreDispatchTorchFunctionMode 以避免暴露此
# API 至其他功能模式。我们仅暴露给 PreDispatchTorchFunctionMode
# 用于在 torch.export.export 中保留 autocast
如果
PyTorch._C.
火炬功能模式是否启用():
栈 =
PyTorch.
覆盖.
_获取当前功能模式栈()
for 模式
在
栈:
如果 isinstance(
模式,
PyTorch.fx.
试验性的.
代理张量.
预分发火炬函数模式,
):
args = (
self.设备,
self.快速数据类型,
self.启用,
self._缓存启用,
)
返回
模式.__torch_function__(
PyTorch.
转换.
_自动播放入口, (),
参数)
def __退出__(self,
异常类型:
任何,
异常值:
任何,
异常堆栈:
任何):
# 类型:忽略[重写]
如果
PyTorch._jit_internal.
是否正在脚本化():
返回
# 当我们退出到任何自动转换实例之外的外部嵌套级别时,删除缓存。
如果
PyTorch.autocast_decrement_nesting() == 0:
PyTorch.
清除自动类型转换缓存()
PyTorch.
设置自动转换启用(self.
设备, self.
上一页)
PyTorch.
设置自动类型转换(self.
设备, self.prev_fastdtype)
PyTorch.set_autocast_cache_enabled(self.prev_cache_enabled)
仅派发到 PreDispatchTorchFunctionMode 以避免暴露此
# API 至其他功能模式。我们仅暴露给 PreDispatchTorchFunctionMode
# 用于在 torch.export.export 中保留 autocast
如果
PyTorch._C.
火炬功能模式是否启用():
栈 =
PyTorch.
覆盖.
_获取当前功能模式栈()
for 模式
在
栈:
如果 isinstance(
模式,
PyTorch.fx.
试验性的.
代理张量.
预分发火炬函数模式,
):
返回
模式.__torch_function__(
PyTorch.
转换.
_自动播出版本退出, (), ())
返回
假
def __调用__(self,
函数):
如果
PyTorch._jit_internal.
是否正在脚本化():
返回
函数
返回 autocast_decorator(self,
函数)
# 这些函数不打算供公共使用。
# 它们是我们预分发跟踪期间追踪到图中的函数。
当遇到自动类型转换上下文管理器时。
def _自动播放入口(*vals):
对于预调度跟踪,如果激活了 TorchFunction 模式,我们希望将其跟踪到图中。
如果
PyTorch._C.
火炬功能模式是否启用():
返回
PyTorch.
覆盖.handle_torch_function(
PyTorch.
转换.
_自动播放入口,
[] *vals
)
模式 =
PyTorch.
转换.
自动播(*vals)
模式.
__进入__()
返回
模式
def _自动播出版本退出(
模式):
如果
PyTorch._C.
火炬功能模式是否启用():
返回
PyTorch.
覆盖.handle_torch_function(
PyTorch.
转换.
_自动播出版本退出,
[]
模式)
模式.
__退出__(
无,
无,
无)
# 将张量和张量容器进行转换。对于字符串和 np.ndarrays 的特殊情况,可以直通,可能错误地检测为“可迭代对象”。
# 可能被错误地检测为“可迭代对象”。
def _类型转换(value,
设备类型: str,
数据类型:
数据类型):
如果 isinstance(value,
PyTorch.
张量):
是否符合资格 = (
value.is_floating_point()
和 value.
设备.
类型 ==
设备类型
和 (value.dtype
是
不
PyTorch.float64)
)
返回 value.
到(
数据类型)
如果
是否符合资格
否则
值
如果...否则 isinstance(value, (str,
字节)):
返回
值
如果...否则 HAS_NUMPY
和 isinstance(value,
numpy.
纳维数组):
返回
值
如果...否则 isinstance(value,
集合.abc.
映射):
返回 {
_类型转换(k,
设备类型,
数据类型):
_类型转换(v,
设备类型,
数据类型)
for k, v 在 value.
项目()
}
如果...否则 isinstance(value,
集合.abc.
迭代器):
可迭代的 = (
_类型转换(v,
设备类型,
数据类型) for v
在 value)
如果 isinstance(value, (
列表,
元组)):
返回
类型(value)(
可迭代对象)
否则:
返回
可迭代的
否则:
返回
值
[文档]def
自定义前向(
前端=
无,
*,
设备类型: str,
输入设备:
可选[
数据类型] =
无,
):
""
为自定义自动微分函数的 `forward` 方法创建一个辅助装饰器。
自动微分函数是 :class:`torch.autograd.Function` 的子类。
更多详情请参阅 :ref:`示例页面`。
参数:
device_type(str): 要使用的设备类型。'cuda'、'cpu'、'mtia'、'xpu' 等等。
类型与 :class:`torch.device` 的 `type` 属性相同。
因此,您可以使用 `Tensor.device.type` 获取张量的设备类型。
cast_inputs (:class:`torch.dtype` 或 None, 可选, 默认=None): 如果不是 ``None``,
当在自动类型转换启用的区域中运行 `forward` 时,
将浮点张量转换为目标数据类型(非浮点张量不受影响),
然后以自动类型转换禁用状态执行 `forward`。
如果为 `None`,则 `forward` 的内部操作以当前自动类型转换状态执行。
.. 注意::
如果装饰的 `forward` 在自动铸造成能区域外被调用,
func:`custom_fwd` 是一个空操作,`cast_inputs` 没有作用。
"""
如果
不 isinstance(
设备类型, str):
抛出
值错误(
f预期 `device_type` 为 `str` 类型,实际得到:`{
类型(
设备类型)}
)
如果 fwd
是
无:
返回 functools.
偏函数(
自定义前向,
设备类型=
设备类型,
输入设备=
设置输入
)
@functools.包装(
前端)
def 装饰前向(*
参数, **kwargs):
参数[0]._dtype =
PyTorch.
获取自动类型转换(
设备类型)
如果
设置输入
是
无:
参数[0]._fwd_used_autocast =
PyTorch.
是否启用自动转换(
设备类型)
返回
前端(*
参数, **kwargs)
否则:
自动上下文 =
PyTorch.
是否启用自动转换(
设备类型)
参数[0]._fwd_used_autocast =
假
如果 autocast_context:
替换为
自动播(
设备类型=
设备类型,
启用=False):
返回
前端(
*_类型转换(
参数,
设备类型,
输入设备),
**_类型转换(kwargs,
设备类型,
输入设备),
)
否则:
返回
前端(*
参数, **kwargs)
返回
装饰前向
# 自动微分确保传入的梯度与前向输出类型相同。允许在 custom_bwd 上使用单独的
# cast_inputs 参数,如果它不匹配则可能导致错误
# cast_inputs 供给 custom_fwd 使用
[文档]def custom_bwd(bwd=None, *, device_type: str):
"""创建自定义自动微分函数的向后方法的辅助装饰器。
自动微分函数是 :class:`torch.autograd.Function` 的子类。
确保使用与 ``forward`` 相同的 autocast 状态执行 ``backward``。
查看更多详情,请参阅::ref:`示例页面`.
Args:
device_type(str): 要使用的设备类型。'cuda'、'cpu'、'mtia'、'xpu'等。
类型与 :class:`torch.device` 的 `type` 属性相同。
因此,您可以使用 `Tensor.device.type` 获取张量的设备类型。
"""
如果 device_type 不是字符串类型:
raise ValueError(
期望 `device_type` 为 `str` 类型,实际得到:`{type(device_type)}`
)
如果 bwd 为 None:
返回 functools.partial(custom_bwd, device_type=device_type)
@functools.wraps(bwd)
def decorate_bwd(*args, **kwargs):
with autocast(
device_type=device_type,
enabled=args[0]._fwd_used_autocast
dtype=args[0]._dtype
):
return bwd(*args, **kwargs)
返回装饰_bwd