本港台开奖现场直播 j2开奖直播报码现场
当前位置: 新闻频道 > IT新闻 >

报码:PyTorch内部机制解析:如何通过PyTorch实现Tensor(2)

时间:2017-08-07 09:07来源:报码现场 作者:118开奖 点击:
tp_new 函数可以创建对象。它负责创建(而不是初始化)该类型的对象,相当于 Python 中的__new()__方法。C 实现是一个静态方法,该方法传递实例化的类型

tp_new 函数可以创建对象。它负责创建(而不是初始化)该类型的对象,相当于 Python 中的__new()__方法。C 实现是一个静态方法,该方法传递实例化的类型和任意参数,并返回一个新创建的对象。

static PyObject * THPTensor_(pynew)(PyTypeObject *type, PyObject *args, PyObject *kwargs){ HANDLE_TH_ERRORS Py_ssize_t num_args = args ? PyTuple_Size(args) : 0; THPTensorPtr self = (THPTensor *)type->tp_alloc(type, 0);// more code below

我们的新函数的第一件事就是为 THPTensor 分配内存。然后,它会根据传递给该函数的参数进行一系列的初始化。例如,当从另一个 THPTensor y 创建 THPTensor x 时,我们将新创建的 THPTensor 的 cdata 字段值设置为以 y 的底层 TH Tensor 作为参数并调用 THTensor_(newWithTensor)返回的结果。这一过程中有内存大小、存储、NumPy 数组和序列的类似的构造函数。

注意,我们只使用了 tp_new 函数,而不是同时使用 tp_new 和 tp_init(对应于 Python 中的 __init()__函数)。

Tensor.cpp 中定义的另一个重要的部分是索引的工作原理。PyTorch Tensors 支持 Python 的映射协议。这样我们可以做如下事情:

x = torch.Tensor(10).fill_(1)y = x[3] // y == 1x[4] = 2// etc.

注意,此索引可以拓展到多维 Tensor。

我们可以通过定义 https://docs.python.org/3.7/c-api/typeobj.html#c.PyMappingMethods 里描述的三种映射方法来使用[]符号。

最重要的方法是 THPTensor_(getValue)和 THPTensor_(setValue),它们解释了如何对 Tensor 进行索引,并返回一个新的 Tensor / Scalar(标量),或更新现有 Tensor 的值。阅读这些实现代码,以更好地了解 PyTorch 是如何支持基本张量索引的。

通用构建(第一部分)

我们可以花费大量时间探索 THPTensor 的各个方面,以及它如何与一个新定义 Python 对象相关联。但是我们仍然需要明白 THPTensor_(init)()函数是如何转换成我们在模块初始化中使用的 THPIntTensor_init()函数。我们该如何使用定义「通用」Tensor 的 Tensor.cpp 文件,并使用它来生成所有类型序列的 Python 对象?换句话说,Tensor.cpp 里遍布着如下代码:

return THPTensor_(New)(THTensor_(new)(LIBRARY_STATE_NOARGS));

这说明了我们需要使类型特定的两种情况:

我们的输出代码将调用 THP <Type> Tensor_New(...)代替调用 THPTensor_(New)

我们的输出代码将调用 TH <Type> Tensor_new(...)代替调用 THTensor_(new)

换句话说,对于所有支持的 Tensor 类型,我们需要「生成」已经完成上述替换的源代码。这是 PyTorch 的「构建」过程的一部分。PyTorch 依赖于配置工具(https://setuptools.readthedocs.io/en/latest/)来构建软件包,我们在顶层目录中定义一个 setup.py 文件来自定义构建过程。

使用配置工具构建扩展模块的一个组件是列出编译中涉及的源文件。但是,我们的 csrc/generic/Tensor.cpp 文件未列出!那么这个文件中的代码最终是如何成为最终产品的一部分呢?

回想前文所述,我们从以上的 generic 目录中调用 THPTensor *函数(如 init)。如果我们来看一下这个目录,会发现一个定义了的 Tensor.cpp 文件。此文件的最后一行很重要:

//generic_include TH torch/csrc/generic/Tensor.cpp

请注意,虽然这个 Tensor.cpp 文件被 setup.py 文件引用,但它被包装在一个叫 Python helper 的名为 split_types 的函数里。这个函数需要输入一个文件,并在该文件内容中寻找「//generic_include」字符串。如果能匹配该字符串,直播,它将会为每个张量类型生成一个具有以下变动的输出文件,:

1. 输出文件重命名为 Tensor<Type>.cpp

2. 输出文件小幅修改如下:

// Before://generic_include TH torch/csrc/generic/Tensor.cpp// After:#define TH_GENERIC_FILE "torch/src/generic/Tensor.cpp"#include "TH/THGenerate<Type>Type.h"

引入第二行的头文件有些许弊端,例如,引入了一些额外的上下文中定义的 Tensor.cpp 源代码。让我们看看其中一个头文件:

#ifndef TH_GENERIC_FILE#error "You must define TH_GENERIC_FILE before including THGenerateFloatType.h"#endif#define real float#define accreal double#define TH_CONVERT_REAL_TO_ACCREAL(_val) (accreal)(_val)#define TH_CONVERT_ACCREAL_TO_REAL(_val) (real)(_val)#define Real Float#define THInf FLT_MAX#define TH_REAL_IS_FLOAT#line 1 TH_GENERIC_FILE#include TH_GENERIC_FILE#undef accreal#undef real#undef Real#undef THInf#undef TH_REAL_IS_FLOAT#undef TH_CONVERT_REAL_TO_ACCREAL#undef TH_CONVERT_ACCREAL_TO_REAL#ifndef THGenerateManyTypes#undef TH_GENERIC_FILE#endif

(责任编辑:本港台直播)
顶一下
(0)
0%
踩一下
(0)
0%
------分隔线----------------------------
栏目列表
推荐内容