记录一下tensorflow源码、安装好的tensorflow与eigen库的关系

都说tensorflow底层矩阵相关的操作是由eigen库来实现的,一直都没搞明白到底tensorflow是怎么调用库中函数的。
所以最近研究了一下它们之间的关系,使用的是tensorflow2.0

首先,为了搞清楚tensorflow是如何使用eigen进行矩阵分割和调度的,对tensorflow2.0的源码中的threadpool.cc进行了研究,该文件除了包含tensorflow/core/…中的一些头文件之外,还包含了

include "third_party/eigen3/unsupported/Eigen/CXX11/Tensor"

这一句话,包含了一个没有后缀的 名为Tensor的文件

打开源码中的该文件(CXX11/Tensor)康一康,内容为

#include "unsupported/Eigen/CXX11/Tensor"

#ifdef _WIN32
#ifndef SLEEP_FUNC_HEADER_GUARD
#define SLEEP_FUNC_HEADER_GUARD
inline void sleep(unsigned int seconds) { Sleep(1000*seconds); }
#endif

// On Windows, Eigen will include Windows.h, which defines various
// macros that conflict with TensorFlow symbols. Undefine them here to
// prevent clashes.
#undef DeleteFile
#undef ERROR
#undef LoadLibrary
#endif  // _WIN32

发现该文件又include了自身,所以一直有所困惑。

实际上,该文件include的 #include "unsupported/Eigen/CXX11/Tensor"这句话并不是包含该文件(15行代码的这个文件)本身,而是包含的eigen库中对应位置的Tensor文件。
找到下载的eigen3.3.9目录,在以下位置找到实际上包含的Tensor文件
G:\cpp_files\eigen-3.3.9\eigen-3.3.9\unsupported\Eigen\CXX11\Tensor
该文件一共有154行代码(C++),其中包括了eigen库中多个执行实际功能的.h文件
位置在:
G:\cpp_files\eigen-3.3.9\eigen-3.3.9\unsupported\Eigen\CXX11\src\Tensor\“xxx”.h

所以可以看出,tensorflow在编译的时候是自动下载eigen库,并且因为已经提前知道eigen库的目录结构,所以在源码文件编写时也是直接include未来需要用到的eigen库的文件,比如一直研究的threadpool.cc中的函数逻辑,就需要eigen中的很多.h文件,所以使用了include "third_party/eigen3/unsupported/Eigen/CXX11/Tensor"这句话。

另外,像上述提到的Tensor这样的没有后缀名的文件在eigen库中有很多,为什么有了可以执行实际功能的.h文件之后还需要新建这样的总结性文件呢,应该是为了让他人便于include,因为这样只需要include一个(没有后缀的module)文件,而如果不这么做可能需要include几十个.h(执行实际功能的文件)

由于tensorflow编译时才下载eigen库的代码,所以研究其逻辑实现的时候需要同时结合tensorflow2.0的源码和下载好的eigen库的代码。

另外,在研究已经编译好的tensorflow2.0的core目录时,即
G:\software\anaconda\envs\tf2.0\Lib\site-packages\tensorflow_core\……
发现其中的include目录下,即
G:\software\anaconda\envs\tf2.0\Lib\site-packages\tensorflow_core\include\……
内部的文件夹:Eigen、unsupported与直接下载下来的eigen库的完全相同
对比

除此之外,其中的文件夹:thrid_party\eigen3,与tensorflow2.0源码中的eigen3文件夹(目录为:G:\cpp_files\tensorflow2.0\tensorflow\third_party\eigen3)的内容完全一致
对比
打开编译后的eigen3中的某个文件,比如
G:\software\anaconda\envs\tf2.0\Lib\sitepackages\tensorflow_core\include\third_party\eigen3\unsupported\Eigen\CXX11\Tensor
即文章开头说到的那个源码中没有后缀名的Tensor文件,其内容为:

#include "unsupported/Eigen/CXX11/Tensor"

#ifdef _WIN32
#ifndef SLEEP_FUNC_HEADER_GUARD
#define SLEEP_FUNC_HEADER_GUARD
inline void sleep(unsigned int seconds) { Sleep(1000*seconds); }
#endif

// On Windows, Eigen will include Windows.h, which defines various
// macros that conflict with TensorFlow symbols. Undefine them here to
// prevent clashes.
#undef DeleteFile
#undef ERROR
#undef LoadLibrary
#endif  // _WIN32

可以看出,内容没有改变,与源码中相同,说明该文件(以及该文件夹中的所有编译不需要的文件)在编译之后都保留了下来。
观察该文件的第一行代码,#include “unsupported/Eigen/CXX11/Tensor”,使用的是“”型的include方式,意思是在当前工作目录去include某个文件(与<>型include不同),因为它include的是
G:\software\anaconda\envs\tf2.0\Lib\sitepackages\tensorflow_core\include\unsupported\Eigen\CXX11\Tensor
文件,所以可以知道设定的工作目录是红色的部分。

再随便点开几个
G:\software\anaconda\envs\tf2.0\Lib\sitepackages\tensorflow_core\include\third_party\eigen3
文件夹中的文件(该文件夹就是编译过程中保留下来的文件夹)
可以发现其中的没有后缀名的文件中的代码都是在include工作目录下
Eigen 或者unsupported
文件夹中的文件而没有实际的执行文件。

由此可知,tensorflow调用eigen库的方式为:源码中直接include eigen库中需要的部分,直接使用其函数等逻辑操作,并且include时不是直接include eigen库中直接含有函数实现的.h头文件,而是include eigen库中(官方给)提供的没有后缀名的module,通过这种方式一次性大批量地include有函数实现的.h头文件。
之后,在编译时下载需要的eigen模块,即eigen库中的Eigen文件夹和unsupported文件夹。
最后,tensorflow安装完成后,因为tensorflow源码中的逻辑都是include的eigen的module文件(无后缀的文件),所以这些“转接口文件”(third_party\eigen3)还需要保留,用来在代码的依赖层面将tensorflow的C++代码与eigen库的含有实际可执行函数代码的.h文件链接起来。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Eigen是一个C++模板,用于线性代数计算。通过学习Eigen源码,可以深入了解其内部实现原理,从而更好地利用该进行编程。 首先,学习Eigen源码可以帮助我们理解它是如何实现矩阵和向量的表示和运算的。Eigen采用模板编程的方式,可以适应不同的矩阵和向量类型,包括动态大小和静态大小,以及不同的数据类型,如浮点数、整数等。通过查看源码,我们可以了解Eigen是如何使用模板来实现通用的矩阵和向量类型,并提供相应的运算功能。 其次,学习Eigen源码还可以帮助我们了解其高效的实现方式。Eigen在设计和实现时,考虑了性能和内存使用效率。它采用矩阵和向量的表达形式,可以有效地进行运算,并尽量减少内存的分配和拷贝。通过分析源码,我们可以学习到Eigen是如何通过优化算法和数据结构来提高计算性能的。 此外,学习Eigen源码还有助于我们了解其丰富的功能和用法。Eigen提供了大量的线性代数计算功能,包括矩阵乘法、矩阵分解、特征值分解、线性方程求解等。通过深入学习Eigen源码,我们可以理解每个功能的实现细节,进而更好地应用于实际问题中。 综上所述,通过学习Eigen源码,我们可以深入了解其内部实现原理,掌握其高效的计算方式,同时了解其丰富的功能和用法。这将有助于我们更好地利用Eigen进行线性代数计算。 ### 回答2: Eigen是一个用于线性代数的C++模板,包含了各种矩阵运算、向量运算和线性方程求解等功能。通过学习Eigen源码,可以深入理解矩阵运算的原理和实现细节,提高代码效率和准确性。 首先,Eigen源码使用模板实现了矩阵和向量的各种运算操作,这意味着可以使用不同的数据类型和维度来进行运算,使得代码更加灵活和通用。学习源码可以了解到模板元编程的技巧和实现方式,提高代码设计的灵活性。 其次,Eigen源码包含了矩阵和向量的基本运算方法,如加减乘除、转置、求逆等,可以通过源码学习到这些运算方法的具体实现原理和优化技巧。了解这些细节可以帮助我们更好地理解算法的本质和性能优化的方法,提高代码的效率。 此外,Eigen源码还包含了线性方程求解的方法,如LU分解、QR分解和特征值分解等。学习源码可以了解到这些求解方法的具体实现过程和数学原理,加深对数学建模和求解问题的理解。 最后,学习Eigen源码还可以帮助我们理解矩阵和向量的内存布局和访问方式。Eigen使用列优先的内存布局方式,了解源码可以了解到这种布局方式的原理和优势,避免内存访问的冗余和低效。 总之,通过学习Eigen源码,可以深入理解线性代数的各种运算方法和数学原理,提高代码效率和准确性。同时,还可以学习到模板元编程的技巧和实现方式,提高代码设计的灵活性。 ### 回答3: Eigen是一个用于线性代数运算的C++模板,由于其高性能和易用性,被广泛应用于科学计算、机器学习等领域。学习Eigen源码可以帮助我们深入理解其内部实现原理,进而更好地使用该进行开发。 在学习Eigen源码时,首先我们可以从它的模板结构和设计思想入手。Eigen使用了大量模板元编程的技术,利用C++的模板特性实现了高度的灵活性和通用性。通过阅读Eigen的模板实现,我们可以学习到如何利用模板编程来实现复杂的数学运算和算法,以及如何提高程序性能和可维护性。 其次,我们可以关注Eigen的矩阵和向量运算部分的源码Eigen提供了丰富的矩阵和向量运算接口,包括基本的加减乘除运算、转置、求逆、特征值分解等等。通过深入研究其源码,我们可以了解到这些运算是如何实现的,了解它们的算法和优化方法,从而更好地掌握Eigen的使用技巧。 此外,学习Eigen源码还可以让我们了解到一些底层的计算优化技术。Eigen使用了一些特殊的技巧和优化策略,如内存对齐、向量化指令、并行计算等等,以提高运算性能。通过学习这些优化技术,我们可以将其应用到自己的程序中,提高程序的执行效率。 总之,学习Eigen源码可以帮助我们更好地理解其内部实现原理,并且提高我们对线性代数的理解和运用能力。通过深入研究Eigen源码,我们可以获得更多关于高性能计算和模板编程的经验,为我们日后的程序开发和科学计算提供有益的借鉴。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值