导入
内置函数
导入
复制
导入 dataclasses
导入
检查
导入
操作系统
导入
系统
导入
打字
导入
警告
导入 zipfile
from collections.abc 导入
迭代器
from 枚举
导入
自动,
枚举
from 打字
导入
任何,
可调用,
可选,
类型检查,
联合
导入
火炬
导入 torch.utils._pytree as pytree
from torch.fx._兼容性
导入
兼容性
from torch.fx.passes.infra.pass_base 导入 PassResult
from torch.fx.passes.infra.pass_manager 导入 PassManager
from torch 的类型
导入 FileLike
from torch.utils._pytree 导入 (
Flatten 函数,
从可序列化上下文函数,
到可序列化上下文函数,
Unflatten 函数,
)
如果
类型检查:
# 在类型检查期间导入以下模块以启用代码智能功能,
不应无条件导入,因为它们导入 sympy,导入 sympy 非常慢
from torch._ops 导入
运算符重载
from torch.fx.experimental.symbolic_shapes 导入
严格的最小最大约束
全部 = [
"约束",
"维度",
"导出向后签名",
"导出图签名",
"已导出程序",
"自定义分解表",
模块调用条目,
模块调用签名,
默认分解,
维度,
"导出",
导出用于训练,
导出用于推理,
加载,
注册数据类,
保存,
反扁平化,
平坦参数适配器,
非扁平化模块,
]
确保导出特定自定义操作被加载
导入 torch.export.custom_ops
from .decomp_utils 导入 CustomDecompTable
from .动态形状
导入
约束,
维,
维数,
形状集合
from .导出程序
导入 (
默认分解,
导出程序,
模块调用条目,
模块调用签名,
)
from .图签名
导入
导出反向签名,
导出图签名
from .unflatten 导入
平坦参数适配器, unflatten,
未扁平化模块
PassType = 可调用[[
PyTorch.fx.GraphModule
]
可选[PassResult]]
定义
导出用于训练(
模块:
PyTorch.
神经网络.
模块,
参数:
元组[
任何, ...
]
关键字参数:
可选[
字典[str,
任何]] =
无,
*,
动态形状:
可选[
联盟[
字典[str,
任何
]
元组[
任何
]
列表[
任何]]] =
无,
严格的:
布尔值 = True,
保留模块调用签名:
元组[str, ...] = (),
) -> 导出程序:
""
`:func:`export_for_training`函数接受任何 nn.Module 及其示例输入,并生成表示该函数中 Tensor 计算的跟踪图`
仅以离线(AOT)方式跟踪该函数的 Tensor 计算,随后可以用不同的输入或序列化执行。
跟踪图(1)在所有 ATen 运算符集中生成标准化运算符。
跟踪图(1)在所有 ATen 运算符集中生成标准化运算符。
(以及任何用户指定的自定义操作符),(2)已消除所有 Python 控制
流程和数据结构(有例外),以及(3)记录集合
形状约束,以展示这种归一化和控制流消除
适用于未来输入。此 API 旨在用于 PT2 量化训练用例
将很快成为 torch.export.export 的默认 IR。要了解更多信息,请继续阅读。
此变更背后的动机,请参阅
https://dev-discuss.pytorch.org/t/why-pytorch-does-not-need-a-new-standardized-operator-set/2206
使用此 API 和:func:`run_decompositions()`,您应该能够获取推理 IR
您的自定义分解行为。
**稳定性保证**
请参阅 :func:`export()` 的文档字符串以获取更多详细信息。
参数:
模块:我们将追踪此模块的前向方法。
参数:示例位置参数输入。
可选的示例关键字输入。
动态形状:
一个可选参数,其类型应该是:
1) 从 ``f`` 的参数名称到其动态形状规范的字典,
2) 一个指定原始顺序中每个输入动态形状的元组。
如果你在关键字参数中指定动态性,你需要按照原始函数签名中定义的顺序传递它们。
张量参数的动态形状可以指定为以下两种形式之一。
动态形状的指定可以是以下两种形式之一。
(1) 一个从动态维度索引到:func:`Dim`类型的字典,其中它是
无需在此字典中包含静态维度索引,但如果有,
它们应映射为 None;或(2)一个:func:`Dim`类型或 None 的元组/列表
这里的 :func:`Dim` 类型对应于动态维度,静态维度
None 表示为空。字典或张量/列表的元组/列表类型的参数通过映射或包含指定序列的序列递归指定。
严格模式:当启用(默认)时,导出函数将通过 TorchDynamo 跟踪程序,以确保生成的图的正确性。否则,
严格:当启用(默认)时,导出函数将通过 TorchDynamo 跟踪程序,以确保生成的图的正确性。否则,
严格:当启用(默认)时,导出函数将通过 TorchDynamo 跟踪程序,以确保生成的图的正确性。否则,
导出的程序将不会验证嵌入到图中的隐含假设,
可能会导致原始模型和导出模型之间的行为差异。这在
用户需要绕过 tracer 中的错误,或者简单地希望逐步
在他们的模型中启用安全性时很有用。请注意,这不会
要不同,并且模型将以相同的方式序列化,无论传递什么值
这里传递的。
警告:此选项为实验性,请自行承担风险使用。
返回值:
包含已追踪的可调用的 :class:`ExportedProgram`。
**可接受的输入/输出类型**
可接受的输入(对于 `args` 和 `kwargs`)和输出类型包括:
- 基本类型,例如 `torch.Tensor`、`int`、`float`、`bool` 和 `str`。
- 数据类,但必须在调用 :func:`register_dataclass` 之后注册。
- (嵌套) 包含 `dict`、`list`、`tuple`、`namedtuple` 和 `OrderedDict` 等所有上述类型的 `data structures`。
``OrderedDict`` 包含所有上述类型。
"""
from ._trace 导入 _export_for_training
如果 not isinstance(
模块,
PyTorch.
神经网络.
模块):
抛出
值错误(
f预期 `mod` 是 `torch.nn.Module` 的实例,却得到了{
类型(
模块)}
。
)
如果 isinstance(
模块,
PyTorch.
算子.
脚本模块):
抛出
值错误(
"导出 ScriptModule 不受支持。"
"也许尝试将你的 ScriptModule 转换为 ExportedProgram。"
"请使用 `TS2EPConverter(mod, args, kwargs).convert()` 来代替。"
)
返回
导出用于训练(
模块,
参数,
关键字参数,
动态形状,
严格的=
严格的,
保留模块调用签名=
保留模块调用签名,
)
定义
导出用于推理(
模块:
PyTorch.
神经网络.
模块,
参数:
元组[
任何, ...
]
关键字参数:
可选[
字典[str,
任何]] =
无,
*,
动态形状:
可选[
联盟[
字典[str,
任何
]
元组[
任何
]
列表[
任何]]] =
无,
严格的:
布尔值 = True,
保留模块调用签名:
元组[str, ...] = (),
解构表:
可选[
字典[
"运算符重载",
可选[
可调用]]] =
无,
) -> 导出程序:
""
`:func:`export_for_inference` 接受任何 nn.Module 和示例输入,并生成表示推理过程的追踪图
仅函数在即时编译(AOT)方式下的张量计算
可以随后用不同的输入或序列化执行。
追踪图(1)产生 ATen 运算符集中的归一化运算符
(以及任何用户指定的自定义操作符)可通过 decomp_table 进行自定义
(2) 已消除所有 Python 控制流和数据结构(存在某些例外),
并且(3)记录了显示这种归一化和控制流消除对后续输入有效的形状约束集合。
此 API 为方便使用,因为它结合了 :func:`export_for_training` 和
func:`run_decompositions`。
**稳定性保证**
请参阅 :func:`export()` 的文档字符串以获取更多详细信息。
参数:
模块:我们将追踪此模块的前向方法。
参数:示例位置参数输入。
可选的示例关键字输入。
动态形状:
一个可选参数,其类型应该是:
1) 从 ``f`` 的参数名称到其动态形状规范的字典,
2) 一个指定原始顺序中每个输入动态形状的元组。
如果你在关键字参数中指定动态性,你需要按照原始函数签名中定义的顺序传递它们。
张量参数的动态形状可以指定为以下两种形式之一。
动态形状的指定可以是以下两种形式之一。
(1) 一个从动态维度索引到:func:`Dim`类型的字典,其中它是
无需在此字典中包含静态维度索引,但如果有,
它们应映射为 None;或(2)一个:func:`Dim`类型或 None 的元组/列表
这里的 :func:`Dim` 类型对应于动态维度,静态维度
None 表示为空。字典或张量/列表的元组/列表类型的参数通过映射或包含指定序列的序列递归指定。
严格模式:当启用(默认)时,导出函数将通过 TorchDynamo 跟踪程序,以确保生成的图的正确性。否则,
严格:当启用(默认)时,导出函数将通过 TorchDynamo 跟踪程序,以确保生成的图的正确性。否则,
严格:当启用(默认)时,导出函数将通过 TorchDynamo 跟踪程序,以确保生成的图的正确性。否则,
导出的程序将不会验证嵌入到图中的隐含假设,
可能会导致原始模型和导出模型之间的行为差异。这在
用户需要绕过 tracer 中的错误,或者简单地希望逐步
在他们的模型中启用安全性时很有用。请注意,这不会
要不同,并且模型将以相同的方式序列化,无论传递什么值
在此处传递。
警告:此选项为实验性,请自行承担风险使用。
decomp_table: 请参阅 :func:`run_decompositions` 获取更多详细信息。
返回值:
包含追踪的可调用对象的 :class:`ExportedProgram`。
**可接受的输入/输出类型**
可接受的输入(对于 `args` 和 `kwargs`)和输出类型包括:
- 基本类型,例如 `torch.Tensor`、`int`、`float`、`bool` 和 `str`。
数据类,但它们必须先通过调用 :func:`register_dataclass` 进行注册。
- (嵌套) 由 `dict`、`list`、`tuple`、`namedtuple` 等组成的结构。
包含所有上述类型的 `OrderedDict`。
"""
ep_for_training = 导出用于训练(
模块,
参数,
关键字参数,
动态形状=
动态形状,
严格的=
严格的,
保留模块调用签名=
保留模块调用签名,
)
返回
训练用 ep.
运行分解(
分解表=
解构表)
[文档]
定义
导出(
模块:
PyTorch.
神经网络.
模块,
参数:
元组[
任何, ...
]
关键字参数:
可选[
字典[str,
任何]] =
无,
*,
动态形状:
可选[
并集[
字典[str,
任何
]
元组[
任何
]
列表[
任何]]] =
无,
严格的:
布尔值 = True,
保留模块调用签名:
元组[str, ...] = (),
) -> 导出程序:
""
`:func:`export` 接收任何 nn.Module 及示例输入,并生成表示的已跟踪图
仅函数在即时编译(AOT)方式下的张量计算
可以随后用不同的输入或序列化执行。
追踪图(1)产生功能 ATen 运算符集中的归一化运算符
(以及任何用户指定的自定义操作符),(2)已消除所有 Python 控制
流程和数据结构(有例外),以及(3)记录集合
形状约束,以展示这种归一化和控制流消除
适用于未来输入的音效。
**安全性保证**
在追踪过程中,:func:`export()` 会记录用户程序和底层 PyTorch 运算符内核所做的形状相关假设。
这些假设由用户程序和底层 PyTorch 运算符内核做出。
输出:class:`ExportedProgram`仅在以下假设成立时才被认为是有效的。
这些假设必须为真。
跟踪对输入张量的形状(而非值)做出假设。
这些假设必须在:func:`export`的图捕获时进行验证。
要成功。具体来说:
- 对输入张量的静态形状的假设会自动验证,无需额外努力。
- 对输入张量的动态形状的假设需要明确指定
通过使用 :func:`Dim` API 构建动态维度,并通过关联
通过`dynamic_shapes`参数传递示例输入。
如果任何假设无法验证,将引发致命错误。当这种情况发生时,
错误信息将包括对所需规范的建议修复
为了验证假设。例如::func:`export` 可能表明
对动态维度“dim0_x”的定义进行以下修复,例如出现在输入“x”的形状中,之前定义为“Dim("dim0_x")”:
与输入“x”关联的形状,之前定义为“Dim("dim0_x")”:
dim = Dim("dim0_x", max=5)
此示例意味着生成的代码需要输入“x”的第 0 维小于
必须大于或等于 5 才有效。您可以检查建议的修复以动态维度定义,然后直接将它们复制到您的代码中,无需进行任何更改。
定义,然后直接复制到您的代码中,无需更改。
``dynamic_shapes`` 参数到您的 :func:`export` 调用。
参数:
模块:我们将追踪此模块的前向方法。
args: 示例位置参数输入。
kwargs: 可选的示例关键字输入。
dynamic_shapes:
An optional argument where the type should either be: 可选参数,其类型应为:
1) 一个字典,从函数 `f` 的参数名到它们的动态形状规格
2) 一个元组,指定了原始顺序中每个输入的动态形状规格
如果你在指定关键字参数的动态性,你需要按照原始函数签名中定义的顺序传递它们
在定义动态性时,如果指定了关键字参数,则需要按照原始函数签名中定义的顺序传递
张量参数的动态形状可以指定为以下两种情况之一
(1)一个从动态维度索引到:func:`Dim`类型的字典,其中不需要在此字典中包含静态维度索引,但如果包含,则应映射到 None;或者(2)一个:func:`Dim`类型或 None 的元组/列表,
它不是必须的,但如果有,它们应该映射到 None;
或者(2)一个:func:`Dim`类型或 None 的元组/列表,
动态维度与静态维度相对应的 :func:`Dim` 类型,静态维度用 None 表示。
字典或张量/元组/列表的参数可以通过映射或包含的规格序列递归指定。
严格模式:当启用时(默认),导出函数将通过程序进行跟踪。
严格:当启用(默认)时,导出函数将跟踪程序。
TorchDynamo 将确保生成的图的正确性。否则,导出的程序将无法验证图内嵌入的隐含假设,可能会导致原始模型和导出模型的行为差异。这在用户需要绕过 tracer 中的错误,或者只想逐步进行时很有用。
导出的程序将无法验证图内嵌入的隐含假设,可能会导致原始模型和导出模型的行为差异。这在用户需要绕过 tracer 中的错误,或者只想逐步进行时很有用。
这在用户需要绕过 tracer 中的错误,或者只想逐步进行时很有用。
这在用户需要绕过 tracer 中的错误,或者只想逐步进行时很有用。
在他们的模型中启用安全性。请注意,这不会影响最终的 IR 规范
要不同,并且无论传递什么值,模型都将以相同的方式进行序列化
在此处传递。
警告:此选项为实验性,请自行承担风险使用。
返回值:
包含追踪的可调用对象的 :class:`ExportedProgram`。
**可接受的输入/输出类型**
可接受的输入(对于 `args` 和 `kwargs`)和输出类型包括:
- 基本类型,例如 `torch.Tensor`、`int`、`float`、`bool` 和 `str`。
数据类,但它们必须先通过调用 :func:`register_dataclass` 进行注册。
- (嵌套) 由 `dict`、`list`、`tuple`、`namedtuple` 等组成的结构。
包含所有上述类型的 `OrderedDict`。
"""
from ._trace 导入
导出
如果 not isinstance(
模块,
PyTorch.
神经网络.
模块):
抛出
值错误(
f预期 `mod` 是 `torch.nn.Module` 的实例,却得到了{
类型(mod)}
。
)
如果 isinstance(mod,
PyTorch.
算子.
脚本模块):
抛出
值错误(
"导出 ScriptModule 不受支持。"
"也许尝试将你的 ScriptModule 转换为 ExportedProgram。"
"请使用 `TS2EPConverter(mod, args, kwargs).convert()` 来代替。"
)
返回 _export(
模块,
参数,
关键字参数,
动态形状,
严格的=
严格,
保留模块调用签名=
保留模块调用签名,
预处理=True,
)
默认 pickle 协议 = 2
[文档]
定义
保存(
ep: 导出程序,
f: 文件类,
*,
额外文件:
可选[
字典[str,
任何]] =
无,
opset_version: 可选[
字典[str, int]] =
无,
pickle 协议:
整型 =
默认 pickle 协议,
) -> 无:
""
..警告:
正在积极开发中,保存的文件可能在 PyTorch 的新版本中不可用
。
将一个 :class:`ExportedProgram` 保存到文件对象中。然后可以使用 Python API :func:`torch.export.load ` 加载。
使用 Python API :func:`torch.export.load ` 加载。
参数:
ep (ExportedProgram):要保存的已导出程序。
f (str | os.PathLike[str] | IO[bytes]) 一个文件对象(必须
实现写入和刷新(或包含文件名的字符串)。
extra_files(可选[Dict[str, Any]]):从文件名到内容的映射。
将作为 f 的一部分存储。
opset_version(可选[Dict[str, int]]):操作集名称的映射。
到这个 opset 的版本
可以指定 pickle_protocol 来覆盖默认协议
示例::
导入 torch
导入 io
class MyModule(torch.nn.Module):
def forward(self, x):
return x + 10
ep = torch.export.export(MyModule(), (torch.randn(5),))
保存到文件
torch.export.save(ep, 'exported_program.pt2')
保存到 io.BytesIO 缓冲区
buffer = io.BytesIO()
torch.export.save(ep, buffer)
以额外文件保存
extra_files = {'foo.txt': b'bar'.decode('utf-8')}
torch.export.save(ep, 'exported_program.pt2', extra_files=extra_files)
"""
如果 not isinstance(ep,
导出程序):
抛出
类型错误(
f"The 'ep' parameter must be an instance of 'ExportedProgram', got '"{
类型(ep).__name__}
'而不是。"'
)
from torch._export.serde.schema 导入 SCHEMA_VERSION
from torch._export.serde 序列化
导入
序列化,
序列化工件
工件:
序列化工件 =
序列化(ep,
opset 版本,
pickle 协议)
如果 isinstance(f, (str, os.PathLike)):
f = os.文件系统路径(f)
替换为
压缩包.ZipFile(f,
w) as zipf:
将每个字段在 SerializedArtifact 中保存到文件。
断言 isinstance(
艺术品.
导出的程序,
字节)
zipf.写入字符串("serialized_exported_program.json",
艺术品.
导出程序)
zipf.写字符串(
"序列化状态字典.pt",
艺术品.
状态字典)
Zipf 定律.
写字符串("serialized_constants.pt",
工件.
常量)
Zipf 定律.
写字符串(
"序列化示例输入.pt",
艺术品.
示例输入)
齐夫.
写字符串(
版本,
“。”.
连接(
地图(str,
SCHEMA 版本)))
添加额外文件(如果提供)
如果
额外文件:
对于
额外文件名,
内容
进入
额外文件.
项目():
编码内容 =
内容.
编码(
utf-8)
zipf.写入字符串(f
"额外文件/"{
额外文件名}",
编码内容)
[文档]
定义
加载(
f: 文件类,
*,
额外文件:
可选[
字典[str,
任何]] =
无,
预期 OpSet 版本:
可选[
字典[str, int]] =
无,
) -> 导出程序:
""
..警告:
正在积极开发中,保存的文件可能在 PyTorch 的新版本中不可用
的 PyTorch。
加载之前使用 :class:`ExportedProgram` 保存的
`torch.export.save `.
参数:
f (str | os.PathLike[str] | IO[bytes]): 一个文件对象(必须
实现 write 和 flush)或包含文件名的字符串。
extra_files (Optional[Dict[str, Any]]): 给定的额外文件名字典
此地图将被加载,其内容将被存储
在提供的地图中。
expected_opset_version(可选[Dict[str, int]]):一个包含操作集名称到预期操作集版本的映射
的映射
返回值:
一个 :class:`ExportedProgram` 对象
示例::
导入 torch
导入 io
从文件中加载 ExportedProgram
ep = torch.export.load('exported_program.pt2')
# 从 io.BytesIO 对象加载 ExportedProgram
with open('exported_program.pt2', 'rb') as f:
buffer = io.BytesIO(f.read())
buffer.seek(0)
ep = torch.export.load(buffer)
# 加载时附带额外文件。
extra_files = {'foo.txt': ''} # 值将被数据替换
ep = torch.export.load('exported_program.pt2', extra_files=extra_files)
打印(extra_files['foo.txt'])
打印(ep(torch.randn(5)))
"""
如果 isinstance(f, (str, os.PathLike)):
f = os.文件系统路径(f)
额外文件 =
额外文件
或者 {}
替换为
压缩包.ZipFile(f, "r") as zipf:
检查版本
版本 = zipf.
阅读(
版本).
解码().
分割(
“。”)
from torch._export.serde.schema 导入 SCHEMA_VERSION
断言 len(
版本) == len(SCHEMA_VERSION)
如果
版本[0] != str(SCHEMA_VERSION[0
)]
抛出 RuntimeError(
f"序列化版本"{
版本}
与我们的当前版本不匹配
f"模式版本"{SCHEMA_VERSION}
。
)
from torch._export.serde 序列化
导入
反序列化,
序列化工件
# 从 zip 文件中加载 serialized_ep 和 serialized_state_dict
序列化导出程序:
可选[
字节] =
无。
序列化状态字典:
可选[
字节] =
无。
序列化常量:
可选[
字节] =
无。
序列化示例输入:
可选[
字节] =
无。
对于
文件信息
进入
Zipf 定律.
信息列表():
文件内容 =
Zipf 定律.
阅读(
文件信息.
文件名)
如果
文件信息.
文件名 == "serialized_exported_program.json":
序列化导出程序 =
文件内容
elif 文件信息.
文件名 ==
"序列化状态字典.json":
警告.
警告(
"此版本文件已过时")
序列化状态字典 =
文件内容
elif 文件信息.
文件名 ==
serialized_constants.json:
警告.
警告(
此版本文件已过时)
serialized_constants = 文件内容
elif 文件信息.
文件名 ==
"序列化状态字典.pt":
序列化状态字典 =
文件内容
elif 文件信息.
文件名 == "serialized_constants.pt":
序列化常量 =
文件内容
elif 文件信息.
文件名 ==
"序列化示例输入.pt":
序列化示例输入 =
文件内容
elif 文件信息.
文件名.
以...开头(
额外文件):
文件名 =
文件信息.
文件名.
分割(
根目录, 1
)]1]
额外文件[
文件名] =
文件内容.
解码(
utf-8)
断言
序列化导出程序
是 not
无。
断言
序列化状态字典
是 not
无。
断言
序列化常量
是 not
无。
断言
序列化示例输入
是 not
无。
工件:
序列化工件 =
序列化工件(
序列化导出程序,
序列化状态字典,
序列化常量,
序列化示例输入,
)
反序列化导出程序
ep = 反序列化(
工件,
预期 opset 版本)
返回 ep
[文档]def register_dataclass(
cls: 类型[type[Any]],
*,
serialized_type_name: 可选[str] = None,
)
-> None:
"""
将数据类注册为 :func:`torch.export.export` 的有效输入/输出类型。
Args:
cls:要注册的数据类类型
serialized_type_name:数据类的序列化名称。如果您想序列化包含此数据类的 pytree TreeSpec,则此字段是必需的
required if you want to serialize the pytree TreeSpec containing this dataclass.
dataclass。
示例::
导入 torch
从 dataclasses 导入 dataclass
@dataclass
class InputDataClass:
feature: torch.Tensor
bias: int
@dataclass
class OutputDataClass:
res: torch.Tensor
torch.export.register_dataclass(InputDataClass)
torch.export.register_dataclass(OutputDataClass)
class Mod(torch.nn.Module):
def forward(self, x: InputDataClass) -> OutputDataClass:
res = x.feature + x.bias
return OutputDataClass(res=res)
ep = torch.export.export(Mod(), (InputDataClass(torch.ones(2, 2), 1), ))
print(ep)
"""
from torch._export.utils import register_dataclass_as_pytree_node
return register_dataclass_as_pytree_node(
cls, serialized_type_name=serialized_type_name
)