torch._C

作者: stupidXY | 来源:发表于2020-11-29 21:05 被阅读0次

    PyTorch为实现前端的易用性与灵活性,使用了user-friendly的动态语言Python作为首选前端,但对比Python语言与C++性能的性能,前者与后者的差是数量级的。部分的原因如下:

    1、Python支持动态类型,Python引入了很多抽象,需要在执行时判断数据类型,带来很大的开销,C++的数据类型在编译期就已经确定。

    2、Python是种解解释型语言,C++是种编译型语言,解释型语言的代码由特定的解释器边解释边执行,很难在整体的角度对代码进行优化,编译型语言先编译后执行,编译器可对代码先进行优化。

    3、GIL带来的伪多线程问题,所以Python大力发展协程和异步语法

    因此,在BACK-END这种对性能有严格要求的场景,不宜用Python作为开发语言。PyTorch选择大量地使用C++/C进行扩展。torch._C就是使用的C++/C写的Python扩展。

    总体框架

    一般来说, 当在FRONT-END进行python函数调用时,可以追踪到toch._C开头的函数调用,然后从torch._C模块中调用对应的C++代码,这些C++代码最终可追溯到ATen和C10中的C++ API的调用。因此一定程度上torch._C模块作为C++后端和Python前端的交互模块。

    对于torch._C模块的实现,其代码位于torh/csrc目录中,该目录中的代码构成torch._C的实现细节。

    torch/csrc目录中的代码如何形成torch._C模块,并且让该模块中的函数等内容能在Python被调用?这得从PyTroch的编译系统说起。PyTorch使用Setuptools编译toch._C模块, 它的核心是setup.py文件,该文件包含编译项目所需要的所有信息,它最重要的setup()函数作为主要切入点,setup()指定MetaData(e.g. name, description, version, author, author_mail等)和package内容。

    其中ext_modules指定扩展模块,torch._C就是通过这样指定的。

    通过指定ext_modules,Setuptools处理torch._C的编译过程。

    关键细节

    ext_modules被指定为extensions,extensions(与torch._C相关的实现)如下所示:

    其中libraies = main_libraries指定的torch._C的来源,main_libraries定义如下

    stub.c如下所示

    PyMODEINIT_FUNC为链接说明,关键在于initModule()函数,该函数位于torch/csrc/Module.cpp中,如下:

    initModule

    以上图中691为例,函数通过THPUtils_addPyMethodDefs( )

    THPUtils_addPyMethodDefs

    添加到methods(static std::vector<PyMethodDef> methods)中,在获取一些方法的定义之后,则可根据这些方法创建torchmodle。

    ,然后通过TH***_init()进行一些对象的初始化,以THPGenerator_init(PyObject *module)为例:

    THPGenerator_init

    通过PyModule_AddObject()添加到torchmodule中, 并增加PyTypeObject THPGeneratorType的引用计数。

    对于以下的这些对象的初始化:

    THDoubleStorage_init()

    ,在pytorch源码工程中搜索不到它们的具体定义,那这些函数是如何生成的呢?

    我们看到torch/csrc/Storage.h

    torch/csrc/Storage.h

    上图中第6行#define THPStorage_(NAME) TH_CONCAT_4(THP,Real,Storage_,NAME)中的TH_CONCAT_4的宏定义在aten/src/TH/THGeneral.h.in中

    THGeneral.h.in部分

    也就是说THPStorage_(NAME)   被替换成   TH_CONCAT_4(THP, Real, Storage_, NAME)   被替换成 TH_CONCAT_4_EXPAND(THP, Real, Storage_, NAME)  被替换成  TH_CONCAT_4_EXPAND(THP, Real, Storage_, NAME)  被替换成 THP##Real##Storage_##NAME, 如果Real可以具体为Double、Float...,NAME可以为init..., 这样就可以构造出THDoubleStorage_init()图中这些函数。

    再看torch/csrc/generic/Storage.h和TH/THGenerateAllTypes.h

    torch/csrc/generic/Storage.h  

    在上图中看到了THPStorage_(init)从而可被替换成THP##Real##Storage_##init

    TH/THGenerateAllTypes.h   TH/THGenerateFloats.h TH/THGenerateFloat.h

    在上图中看到了#define Real Float,从而THP##Real##Storage_##init可被替换成THPStorage_(init)从而可被替换成THPFloatStorage_init(),对于THPDoubleStorage_init()等函数也是一样。

    涉用技术

    SetupTools

    THPDoubleStorage_init()、THPFloatStorage_init()等所有类型的相应函数生成(如图TH/THGeneataFloat.h中用宏先将Real替换成Float,再includeTH_GENERIC_FILE生成THPFloatStorage_init(),再将Real进行undef;在torch/csrc/Storage.h中对所有类型的相应文件进行上述操作,即可生成所有类型的相应函数)。

    相关文章

      网友评论

          本文标题:torch._C

          本文链接:https://www.haomeiwen.com/subject/rlyobktx.html