置顶:将pytorch clone到本地,查看initial commit,已经是麻雀虽小五脏俱全了,非常适合作为学习模板。

2017年12月7日01:24:15

 

2017-10-25 17:51

参考了知乎问题  如何有效地阅读PyTorch的源代码? 相关回答

按照构建顺序来阅读代码是很聪明的方法。

1,TH中最核心的是THStorage、THTensor,

THStorage实现了底层数据(其实就是一个数组),

THTensor实现了对底层数据的查看。

2,TH: 核心就THStorage与THTensor,辅助有 THGeneral、THHalf、THAllocator、THSize

 

2017-11-14 02:56

看了这么久,终于知道TH的头在哪里了。该有的预备知识也差不多都具备了,接下来准备一边继续深入

研究TH,一边记笔记。TH看懂了,THNN也是差不多立马能读懂的,再加上一个ATen或类似的东西,就可以

在C/C++层面构建神经网络了。

 

2017年11月15日01:35:54

pytorch的主要维护者之一的 Adam Paszke 有一篇 A quick tour of Torch internals 的文章。里头大概讲了下

TH的结构。TH用 C 模拟了泛型编程。今天抽丝剥茧,写了一个只包含2个文件的极度简单的演示程序:

main.cpp

#include <iostream>

#define CONCAT_2_EXPAND(x,y) x ## y
#define show_(name) CONCAT_2_EXPAND(show_, name)
// 上面两句合并成一句: #define show_(name) show_##name 都会出错!

#include "generic.h"

//real = int 类型, int 先用 real 来代表自己
#define real int
#line 1 GENERIC_FILE 
#include GENERIC_FILE

#undef real // int 用完 real 后必须 undef 掉 real,因为 double 还要用 real

//real = double 类型
#define real double
#line 1 GENERIC_FILE 
#include GENERIC_FILE

int main(){
    show_int(6);
    show_double(3.14);

    system("pause");
    return 0;
}

  

generic.h

#ifndef GENERIC_FILE
#define GENERIC_FILE "generic.h"
#else

#include <iostream>
using namespace std;

void show_(real)(real number){
    cout << "real = " << number << endl;
}

#endif

 

注释:

#line number "string"

它通知预处理器从下一行的行号被重新设定为 number 所代表的数字。如果给出了可选部分"string",预处理器就把它作为当前文件的名字。这条指令将修改__LINE__符号的值,如果加上可选部分,还将修改__FILE__符号的值。

 

两个文件的功能是显示 int 和 double 两种不同类型的数。已经实现了泛型编程。

#define、#undef、#line 1 GENERIC_FILE 三者的组合运用真是绝妙的用法。

预编译完后代码膨胀成包含 show_int() 和 show_double() 两个函数的文件了。其实在 C和指针 这本书的 17.5.4节也提到过用C模拟泛型编程的一些技巧。可以参看。用C实现泛型,使用者需要遵循一定的命名规则。

 

2017年11月18日20:09:10

将函数的泛型实现从 generic.h 中分离到单独的 generic.c 文件中去了,代码在这:generic_in_c

文件结构及编译过程比较巧妙。

TH在make过程中可以看到如下信息:

 

Scanning dependencies of target TH
[ 5%] Building C object CMakeFiles/TH.dir/THGeneral.c.o
[ 10%] Building C object CMakeFiles/TH.dir/THHalf.c.o
[ 15%] Building C object CMakeFiles/TH.dir/THAllocator.c.o
[ 20%] Building C object CMakeFiles/TH.dir/THSize.c.o
[ 25%] Building C object CMakeFiles/TH.dir/THStorage.c.o
[ 30%] Building C object CMakeFiles/TH.dir/THTensor.c.o
[ 35%] Building C object CMakeFiles/TH.dir/THBlas.c.o
[ 40%] Building C object CMakeFiles/TH.dir/THLapack.c.o
[ 45%] Building C object CMakeFiles/TH.dir/THLogAdd.c.o
[ 50%] Building C object CMakeFiles/TH.dir/THRandom.c.o
[ 55%] Building C object CMakeFiles/TH.dir/THFile.c.o
[ 60%] Building C object CMakeFiles/TH.dir/THDiskFile.c.o
[ 65%] Building C object CMakeFiles/TH.dir/THMemoryFile.c.o
[ 70%] Building C object CMakeFiles/TH.dir/THAtomic.c.o
[ 75%] Building C object CMakeFiles/TH.dir/THVector.c.o
[ 80%] Building C object CMakeFiles/TH.dir/generic/simd/convolve.c.o
[ 85%] Building C object CMakeFiles/TH.dir/generic/simd/convolve5x5_sse.c.o
[ 90%] Building C object CMakeFiles/TH.dir/vector/AVX.c.o
[ 95%] Building C object CMakeFiles/TH.dir/generic/simd/convolve5x5_avx.c.o
[100%] Linking C shared library libTH.so
[100%] Built target TH

 

逆着这个顺序来,一边删除功能一边编译可以了解TH的结构。

THStorage应该是TH最基本的功能了。是先实现storage,再实现tensor及相关功能,再实现file功能。

lapack、blas、simd等从cmakelists来看都是可选的。

storage和allocator紧密关联。THGeneral.c中大部分是实现内存管理的东西。

查看预编译后的代码可以看到总共有8种类型的storage: inttypes 5种 + floattypes 2种 + half类型

预编译展开 TH.h 可以看到所有的函数声明。