我们希望能够在 THP 张量等价类上调用所有的 TH 张量的方法。然而,为所有 TH 方法编写封装性价比极低。我们需要一个更好的方式来满足这一需求。 PyTorch cwrap PyTorch 实现自己的 cwrap 工具来包装用于 Python 后端的 TH Tensor 方法。我们使用自定义 YAML 格式( ())来定义包含一系列 C 方法声明的.cwrapfile 文件。cwrap 工具获取此文件,并以与 THPTensor Python 对象和 Python C 扩展方法调用相兼容的格式输出包含打包方法的.cpp 源文件。此工具不仅用于生成包含 TH 的代码,还包含 CuDNN。它是一款设计为可扩展的工具。 用于就地 addmv_功能的示例 YAML「声明」如下: [[ name: addmv_ cname: addmv return: self arguments: - THTensor* self - arg: real beta default: AS_REAL(1) - THTensor* self - arg: real alpha default: AS_REAL(1) - THTensor* mat - THTensor* vec]] cwrap 工具的架构非常简单。它先读入一个文件,然后使用一系列插件进行处理。有关可以更改代码的插件的文档,请参阅 tools/cwrap/plugins/__init__.py。 源代码在一系列的编译通过时生成。首先,YAML「声明」被解析和处理。然后,通过参数检查和提取后源代码逐个生成,定义方法头,调用底层库(如 TH)。最后,cwrap 工具允许一次处理整个文件。addmv_的结果输出可以在这里找到: https://gist.github.com/killeent/c00de46c2a896335a52552604cc4d74b. 为了与 CPython 后端进行交互,该工具生成一个 PyMethodDefs 数组,可以存储或附加到 THPTensor 的 tp_methods 字段。 在包装 Tensor 方法的具体情况下,构建过程首先从 TensorMethods.cwrap 生成输出源文件。该源文件就是通用 Tensor 源文件中的 #include 后面的文件。所有这些都发生在预处理器执行之前。结果,所有生成的方法包装器都执行与上述 THPTensor 代码相同的运作过程。因此,单个通用声明和定义也适用于其它类型。 合而为一 到目前为止,我们已经展示了如何扩展 Python 解释器来创建一个新的扩展模块,如何定义我们新的 THPTensor 类型,以及如何为所有与 TH 连接的类型的 Tensor 生成源代码。简单来说,我们将染指汇编。 Setuptool 允许我们定义一个用于编译的扩展模块。整个 torch._C 扩展模块文件是通过收集所有源文件、头文件、库等,并创建一个 setuptool 扩展来编译的。然后,由 setuptool 处理构建扩展模块本身。我将在随后的一篇博文中探讨更多的构建过程。 总而言之,让我们回顾一下我们的四个问题: PyTorch 如何通过扩展 Python 解释器来定义可以从 Python 代码中调用的 Tensor 类型? 它使用 CPython 的框架来扩展 Python 解释器并定义新的类型,同时尤其关注为所有类型生成代码。 PyTorch 如何封装实际定义 Tensor 属性和方法的 C 的类库? 它通过定义一个由 TH Tensor 支持的新型 THPTensor。再通过 CPython 后端的各种语法规则,函数调用信息就会转发到这个张量。 PyTorch 的 C 类包装器如何生成 Tensor 方法的代码? 它需要我们提供自定义的 YAML 格式的代码,并通过使用多个插件通过一系列处理步骤来为每个方法生成源代码。 PyTorch 的编译系统如何编译这些组件并生成可运行的应用程序? 它需要一堆源/头文件、库和编译指令来构建使用 Setuptool 的扩展模块。 本博文只是 PyTorch 构建系统的部分概述。还有更多的细节,但我希望这是对 Tensor 类的多数组件的通用介绍。 资源: https://docs.python.org/3.7/extending/index.html 对于理解如何编写 Python 的 C / C++扩展模块极具价值。 原文链接:https://gist.github.com/killeent/4675635b40b61a45cac2f95a285ce3c0 (责任编辑:本港台直播) |