参数,缓冲区和子模块必须显式注册。 注册后,可以使用`parameters()`或`buffers()`之类的方法来检索整个(嵌套)模块层次结构中所有参数的容器。 类似地,使用`to(...)`之类的方法,例如 `to(torch::kCUDA)`将所有参数和缓冲区从 CPU 移到 CUDA 内存,在整个模块层次结构上工作。
#### 定义模块和注册参数](docs / modern-java-zh /
#### 定义模块和注册参数
为了将这些词写成代码,让我们考虑一下用 Python 界面编写的简单模块:
...
...
@@ -197,7 +197,7 @@ struct Net : torch::nn::Module {
就像在 Python 中一样,我们定义了一个名为`Net`的类(为简单起见,这里是`struct`而不是`class`),然后从模块基类派生它。 在构造函数内部,我们使用`torch::randn`创建张量,就像在 Python 中使用`torch.randn`一样。 一个有趣的区别是我们如何注册参数。 在 Python 中,我们用`torch.nn.Parameter`类包装了张量,而在 C ++中,我们不得不通过`register_parameter`方法传递张量。 这样做的原因是 Python API 可以检测到属性为`torch.nn.Parameter`类型并自动注册此类张量。 在 C ++中,反射非常受限制,因此提供了一种更传统(且不太神奇)的方法。
至此,我们知道了如何使用 C ++定义模块,注册参数,注册子模块,通过`parameters()`之类的方法遍历模块层次结构并最终运行模块的`forward()`方法。 尽管在 C ++ API 中还有很多方法,类和主题需要使用,但我将为您提供完整菜单的[文档](https://pytorch.org/cppdocs/api/namespace_torch__nn.html)。 我们将在稍后实现 DCGAN 模型和端到端训练管道的过程中,涉及更多概念。 在我们这样做之前,让我简要介绍一下 C ++前端为`torch::nn::Module`的子类提供的*所有权模型*。
...
...
@@ -465,7 +465,7 @@ struct Net : torch::nn::Module {
结论:您应该使用哪种所有权模型–哪种语义? C ++前端的 API 最能支持模块所有者提供的所有权模型。 这种机制的唯一缺点是在模块声明下方多了一行样板。 也就是说,最简单的模型仍然是 C ++模块简介中显示的值语义模型。 对于小的,简单的脚本,您也可以摆脱它。 但是,由于技术原因,您迟早会发现它并不总是受支持。 例如,序列化 API(`torch::save`和`torch::load`)仅支持模块支架(或普通`shared_ptr`)。 因此,建议使用模块持有人 API 和 C ++前端定义模块,此后我们将在本教程中使用此 API。
为了将实现真正提升到一个新的水平,我们可以使用自定义 CUDA 内核来手写前进和后退通道的一部分。 对于 LLTM,这具有特别有效的前景,因为按顺序有大量的逐点运算,这些运算都可以在单个 CUDA 内核中融合和并行化。 让我们看看如何编写这种 CUDA 内核,并使用此扩展机制将其与 PyTorch 集成。
## 在 C ++中使用 TorchScript 自定义运算符](docs / modern-java-zh /
## 在 C ++中使用 TorchScript 自定义运算符
TorchScript 的一项有用功能是能够将模型序列化到磁盘文件中。 该文件可以通过有线方式发送,存储在文件系统中,或者更重要的是,可以动态反序列化和执行,而无需保留原始源代码。 这在 Python 中是可能的,但在 C ++中也是可能的。 为此,PyTorch 为[提供了纯 C ++ API](https://pytorch.org/cppdocs/) ,用于反序列化以及执行 TorchScript 模型。 如果您还没有的话,请阅读[有关在 C ++](https://pytorch.org/tutorials/advanced/cpp_export.html) 中加载和运行序列化 TorchScript 模型的教程,接下来的几段将基于该教程构建。
...
...
@@ -621,19 +621,19 @@ $ ./example_app example.pt
成功! 您现在可以推断了。
## 结论](docs / modern-java-zh /
## 结论
本教程向您介绍了如何在 C ++中实现自定义 TorchScript 运算符,如何将其构建到共享库中,如何在 Python 中使用它来定义 TorchScript 模型以及如何将其加载到 C ++应用程序中以进行推理工作负载。 现在,您可以使用与第三方 C ++库进行接口的 C ++运算符扩展 TorchScript 模型,编写自定义的高性能 CUDA 内核,或实现任何其他需要 Python,TorchScript 和 C ++之间的界线才能平稳融合的用例。
本教程是[自定义运算符](torch_script_custom_ops.html)教程的后续教程,并介绍了我们为将 C ++类同时绑定到 TorchScript 和 Python 而构建的 API。 该 API 与 [pybind11](https://github.com/pybind/pybind11) 非常相似,如果您熟悉该系统,则大多数概念都将转移过来。
## 用 C ++实现和绑定类](docs / modern-java-zh /
## 用 C ++实现和绑定类
在本教程中,我们将定义一个简单的 C ++类,该类在成员变量中保持持久状态。
...
...
@@ -100,7 +100,7 @@ TORCH_LIBRARY(my_classes, m) {
```
## 使用 CMake 将示例构建为 C ++项目](docs / modern-java-zh /
## 使用 CMake 将示例构建为 C ++项目
现在,我们将使用 [CMake](https://cmake.org) 构建系统来构建上述 C ++代码。 首先,将到目前为止介绍的所有 C ++代码放入`class.cpp`文件中。 然后,编写一个简单的`CMakeLists.txt`文件并将其放在同一目录中。 `CMakeLists.txt`应该是这样的:
我们还可以在使用 libtorch 的 C ++进程中使用自定义注册的 C ++类。 举例来说,让我们定义一个简单的`nn.Module`,它实例化并调用 MyStackClass 类上的方法:
...
...
@@ -379,7 +379,7 @@ $ ./infer
难以置信!
## 将自定义类移入或移出 IValues](docs / modern-java-zh /
## 将自定义类移入或移出 IValues
也可能需要将自定义类从自定义 C ++类实例移入或移出`IValue``s, such as when you take or return ``IValue``s from TorchScript methods or you want to instantiate a custom class attribute in C++. For creating an ``IValue`:
## 为自定义 C ++类定义序列化/反序列化方法](docs / modern-java-zh /
## 为自定义 C ++类定义序列化/反序列化方法
如果您尝试将具有自定义绑定 C ++类的`ScriptModule`保存为属性,则会出现以下错误:
...
...
@@ -481,7 +481,7 @@ testing
```
## 定义接受或返回绑定 C ++类的自定义运算符](docs / modern-java-zh /
## 定义接受或返回绑定 C ++类的自定义运算符
定义自定义 C ++类后,您还可以将该类用作自变量或从自定义运算符返回(即自由函数)。 假设您具有以下免费功能:
...
...
@@ -522,7 +522,7 @@ class TryCustomOp(torch.nn.Module):
注册使用 C ++类作为参数的运算符时,要求已注册自定义类。 您可以通过确保自定义类注册和您的自由函数定义在同一`TORCH_LIBRARY`块中,并确保自定义类注册位于第一位来强制实施此操作。 将来,我们可能会放宽此要求,以便可以按任何顺序进行注册。
## 结论](docs / modern-java-zh /
## 结论
本教程向您介绍了如何向 TorchScript(以及扩展为 Python)公开 C ++类,如何注册其方法,如何从 Python 和 TorchScript 使用该类以及如何使用该类保存和加载代码以及运行该代码。 在独立的 C ++过程中。 现在,您可以使用与第三方 C ++库连接的 C ++类扩展 TorchScript 模型,或实现需要 Python,TorchScript 和 C ++之间的界线平滑融合的任何其他用例。
@@ -138,7 +138,7 @@ TORCH_LIBRARY_IMPL(myops, Autograd, m) {
```
## 超越 autograd](docs / modern-java-zh /
## 超越 autograd
从某种意义上说,调度员并没有做太多事情:它所做的只是实现一种美化的 if 语句,其方法如下:
...
...
@@ -169,7 +169,7 @@ public:
这是一些特定的调度键,您可能需要为其定义一个运算符。
### 自动播送](docs / modern-java-zh /
### 自动播送
Autocast 调度键实现对[自动混合精度(AMP)](https://pytorch.org/docs/stable/amp.html)的支持。 自动广播包装器内核通常会在运行 op 之前将传入的`float16`或`float32` CUDA 张量转换为某些首选精度。 例如,浮点 CUDA 张量上的积和卷积通常运行得更快,并且在`float16`中使用较少的内存,而不会影响收敛。 自动广播包装器仅在[启用自动广播的上下文](https://pytorch.org/docs/stable/amp.html#torch.cuda.amp.autocast)中有效。
...
...
@@ -239,6 +239,6 @@ TORCH_LIBRARY_IMPL(myops, Autocast, m) {