Windows10 Bazel 编译 Tensorflow 2 C++ dll 和 lib 文件

Windows10 Bazel 编译 Tensorflow 2 C++ dll 和 lib 文件

    • 一. 硬件
    • 二. 软件
    • 三. 编译 Release 版本
    • 四. 编译 Debug 版本
    • 五. 使用时你可能会遇到的问题

一. 硬件

  • 内存 >= 16 G 如果不够也没有关系, 编译的时候添加设置就可以了, 下面会讲
  • 磁盘可用空间 Release 版本 >= 16G , Debug版本 >= 40G 编译的中间文件默认会放到 C:\用户\你的账号名\ _bazel_你的账号名 下. C 盘可能没有那么大的空间, 所以要改一下输出文件的路径. 下面会讲怎么改

二. 软件

  • Tensorflow 源码 2.1.1 https://github.com/tensorflow/tensorflow/releases/tag/v2.1.1
    下载后放到你喜欢的地方, 我放到了 D 盘根目录, 其他 2.0 以上的版本我试了都有问题.
  • bazel 0.29.0 https://docs.bazel.build/versions/0.29.0/install-windows.html
    这个只有一个 exe 文件, 把名字改成 bazel.exe 放到你喜欢的地方, 我放到了 D:\bazel. 然后在用户环境变量的 path 中添加D:\bazel
  • MSYS2 https://www.msys2.org/
    按默认路径安装(C:\msys64), 然后在用户环境变量的 path 中添加 C:\msys64\usr\bin, 完成后打开 cmd, 输入 pacman -S git patch unzip, 下载更新一些东东, 如果有提示要不要安装或者更新之类的, 就选 Y
  • 配置一个可以运行 tensorflow 的 Anaconda Environment
    这一步的 Tensorflow 用 2.0.0 和 2.1.0 都可以. 新增 Environment 可参考 Windows 下无痛安装 TensorFlow 2 (GPU版), 然后在用户环境变量的 path 中添加 D:\Anaconda3\envs\tf_gpu (这个是我的 Tensorflow 路径, 你的自己改), 表示用这个 Environment 中的 Python, 所以在安装 Anaconda 的时候就不要把 Python 添加到环境变量了, 如果添加了, 删除就可以了. 配置这个环境倒不是必需的, 只是编译时要用到 numpy, keras_applications 和 keras_preprocessing 这些依赖项, 你说你都要用 Tensorflow 了, 怎么不配置一个呢? 省得出问题. 在 具体依赖项 中有讲需要哪些依赖项和具体的版本. 下面是我的电脑上安装的版本, 我的 Python 是3.7, 所以有一些不用安装. 需要的话, 用 pip 就可以安装
    • absl-py 0.9.0
    • astor 0.8.1
    • gast 0.2.2
    • google-pasta 0.2.0
    • Keras 2.3.1
    • Keras-Applications 1.0.8
    • Keras-Preprocessing 1.1.2
    • numpy 1.19.0
    • opt-einsum 3.2.1
    • scipy 1.4.1
    • six 1.15.0
    • tensorboard 2.0.2
    • tensorflow-gpu 2.0.0
    • tensorflow-gpu-estimator 2.2.0
    • termcolor 1.1.0
    • wheel 0.34.2
    • wrapt 1.12.1
  • VS2017 专业版, 这个网上多得很, 自己找了下载
    安装完后, 新建一个用户环境变量, BAZEL_VC, 值: D:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\VC (改成你自己的路径)

如果想编译其他版本 Tensorflow, 可以看一下 Tensorflow 源码那个文件夹下的 configure.py 中 CUDA 和 Bazel 的需求版本

三. 编译 Release 版本

  1. 增加内存使用限制. 如果你的内存不够, 需要在编译的时候增加 --local_ram_resources=2048(这个数字按你的来改) 选项来限制使用的内存
  2. 修改 bazel 默认输出目录. 如果你的 C 盘够大, 就不需要改. 修改方法是打开 tensorflow-2.1.1 下的 .bazelrc, 在其最后增加一行 startup --output_user_root=F:/tf, 等号后面的 F:/tf 是你想要改的路径. 我有试过改到移动硬盘上, 但是会出错, 你可以试一下
# Put user-specific options in .bazelrc.user
try-import %workspace%/.bazelrc.user

startup --output_user_root=F:/tf
  1. 打开 Anaconda Prompt, 输入activate tf_gpu(这个是我的名称, 改成你的) 来激活 Environment
  2. 切换到你放 Tensorflow 的目录, 我的是D:\tensorflow-2.1.1
    Windows10 Bazel 编译 Tensorflow 2 C++ dll 和 lib 文件_第1张图片
  3. 配置选项, 按上面操作这后, 已经来到了 tensorflow-2.1.1 目录下, 输入 python configure.py 运行配置程序, 如果之前有运行过 bazel, 就会自动关闭 bazel, 然后让你设置一些选项, 默认的话, 直接回车就可以
  • python: 默认
  • library paths: 默认
  • XLA JIT: N
  • ROCm: N
  • CUDA: 如果编译 CPU 版本, N, GPU 版本, y, 如果选 y, 下面有一个输入 GPU 算力, 按你的 GPU 输入就好了, 我没有编译过 GPU的版本, 因为使用的电脑没有显卡, 所以我选的是 N
  • option “–config=opt” is …arch: /arch:AVX2 (比较新的CPU都支持这个, 注意输入的是 /arch:AVX2)
  • override eigen strong inline: Y, 这个可以减少编译时间.

下面是我编译时的选项. 最好和我的一样, 不然有可能会失败.
Windows10 Bazel 编译 Tensorflow 2 C++ dll 和 lib 文件_第2张图片
6. 编译 dll. 输入 bazel build --config=opt //tensorflow:tensorflow_cc.dll 就开始编译 C++ 版本的 dll 了, 有警告的话不用理会. 编译的时候要下载东西, 所以有可能会失败, 看人品哈. 编译的时间还是比较长的, 电脑配置好的话, 会快一点. 我的用了30分钟左右. mkl 我试了好几次都失败. 所以你就不要把这些加进去编译了. 其他的也不要加.
Windows10 Bazel 编译 Tensorflow 2 C++ dll 和 lib 文件_第3张图片
编译过程
Windows10 Bazel 编译 Tensorflow 2 C++ dll 和 lib 文件_第4张图片
编译成功后是下面这个样子. 不成功的话再输入 bazel build --config=opt //tensorflow:tensorflow_cc.dll 多来几次. 不成就不行了, 你问我也许知道, 也许不知道.
Windows10 Bazel 编译 Tensorflow 2 C++ dll 和 lib 文件_第5张图片
7. 编译 lib. 如果上面编译成功了, 那你就离成功不远了. 再输入 bazel build --config=opt //tensorflow:tensorflow_cc_dll_import_lib 开始编译 lib 文件, 有输出警告的话不用理会. 这个还是比较快的
Windows10 Bazel 编译 Tensorflow 2 C++ dll 和 lib 文件_第6张图片
成功后的样子
Windows10 Bazel 编译 Tensorflow 2 C++ dll 和 lib 文件_第7张图片
8. 头文件. 接下来再输入 bazel build --config=opt //tensorflow:install_headers 开始输出头文件, 有警告也不用理会, 只要不是错误就没有问题
Windows10 Bazel 编译 Tensorflow 2 C++ dll 和 lib 文件_第8张图片
完成后的样子
Windows10 Bazel 编译 Tensorflow 2 C++ dll 和 lib 文件_第9张图片
上面的步骤完成后, 在 D:\tensorflow-2.1.1(你的在你放源码的地方) 下的 bazel_bin 中会有相应的 include 文件夹, tensorflow_cc.dll 和 tensorflow_cc.lib 文件, 把它们复制出来放到你的程序里就可以了. 编译出来的是 Release 的版本
Windows10 Bazel 编译 Tensorflow 2 C++ dll 和 lib 文件_第10张图片
如果你把编译好的文件都复制出来了, 可以输入 bazel clean 清除不用的文件释放硬盘空间, 毕竟 16 个 G 还是挺多的, 不过先看完下面的可能会遇到的情况再清除

四. 编译 Debug 版本

编译 Debug 版本的命令是增加 -c dbg 选项, 比如编译 dll 用的是 bazel build -c dbg --config=opt //tensorflow:tensorflow_cc.dll. 但是你会遇到以下问题. 问题修改之后再输入编译指令重新开始

bazel build -c dbg --config=opt //tensorflow:tensorflow_cc.dll
  • path.cc(290): error C4716: “tensorflow::io::GetTempFilename”: 必须返回一个值
    我们打开报错的文件, 文件路径报错的地方已经告诉你了, 错误在 290 行, 这个错误是因为宏定义中没有返回值造成的. 这里使用的是Windos平台, 而 255 行说这个函数在 Windows 平台和 Android 平台中没有实现. 解决方法就是在 255 行后面插入一行, 直接返回就可以了. 增加一个 return string(); 如下所示
string GetTempFilename(const string& extension) {
#if defined(PLATFORM_WINDOWS) || defined(__ANDROID__)
  LOG(FATAL) << "GetTempFilename is not implemented in this platform.";
  return string();
#else
...
#endif
  • device_base.cc(42) : error C4716: “tensorflow::DeviceBase::name”: 必须返回一个值
    和上面 GetTempFilename”: 必须返回一个值的解决方法一样, 打开文件, 找到报错的地方添加 return string();

  • device_base.cc(38) : error C4716: “tensorflow::DeviceBase::attributes”: 必须返回一个值
    这个返回值的类型是 DeviceAttributes, 所以我们直接返回一个这样的类型就可以

const DeviceAttributes& DeviceBase::attributes() const {
  LOG(FATAL) << "Device does not implement attributes()";
  DeviceAttributes da;
  return da;
}

这个坑还没有完, 因为这样会报 DeviceAttributes 没有定义, 所以还要把头文件包含进来. 在文件的开始增加 #include “tensorflow/core/framework/device_attributes.pb.h”

#include "tensorflow/core/util/work_sharder.h"

#include "tensorflow/core/framework/device_attributes.pb.h"

namespace tensorflow {
  • remote_device.cc(46) : error C4716: “tensorflow::RemoteDevice::resource_manager”: 必须返回一个值
    这个需要返回一个指针, 直接 return nullptr; 就好了

解决了上面的问题, 你就可以编译成功了

五. 使用时你可能会遇到的问题

  1. VS 编译项目时报 fatal error C1083: 无法打开包括文件: “google/protobuf/port_def.inc”: No such file or directory 之类的错误. 那你就把 D:\Anaconda3\envs\tf_gpu\Lib\site-packages\tensorflow_core\include 中的 google 整个文件夹复制到编译出来的那个 include 文件夹中就好了.
  2. VS 编译项目时报 error LNK2001: 无法解析的外部符号, 打开D:\tensorflow-2.1.1(你的在你放源码的地方) \tensorflow\tools\def_file_filter\def_file_filter.py.tpl, 212行 # Header for the def file.下面添加那些无法解析的符号, 格式如下. 注意不能使用 Tab 键, 要用空格缩进, 保存后再重新编译一次 dll, lib 和 头文件就可以了.
 # Header for the def file.
    if args.target:
      def_fp.write("LIBRARY " + args.target + "\n")
    def_fp.write("EXPORTS\n")
    def_fp.write("\t ??1OpDef@tensorflow@@UEAA@XZ\n")
    # 添加在这里
  1. Release 版本在 Debug 模式运行会崩溃, 因为编译的 Tensorflow 是 Release 版本, 所以切换到 Release 模式运行或者编译 Debug 版本

你可能感兴趣的:(TensorFlow,Anaconda)