按照构建顺序来阅读代码是很聪明的方法。
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 可以看到所有的函数声明。