win10 c++编译TensorFlow1.13.1 CPU版

Ubuntu16.04 CUDA10.2 CUDNN7.6.5 tensorflow1.13.1下训练的网络,封装成pb模型,在win10下调用,需要先编译TensorFlow。一开始尝试编译GPU的版本,踩坑没爬上来。先编译一个CPU版本的试试,回头有机会再搞GPU的。

参考:https://blog.csdn.net/atpalain_csdn/article/details/97945536,https://blog.csdn.net/weixin_43868576/article/details/108491879,感谢大佬们的无私奉献!!

Step1. 安装vs2015

vs2015*(2019不行,环境变量路径不一样,编译完成之后可以在2019里面测试*)的安装这里就不多说了,Anaconda3、CUDA和cuDNN的安装可参考cmake编译opencv: Win10+cmake3.14.4+cuda10.0+cudnn7.6+opencv-4.0.0+contrib+vs2015

Step2. 安装msys2

进入msys2官网,选择msys2-x86_64-20210228.exe。

下载好后开始安装,安装路径推荐使用默认,即安装在 C:\msys64 下。安装完成,点击Finish。

弹出一个类似cmd的命令窗口,输入一下命令:

pacman -Syu

如果报秘钥错误尝试换msys2新一点儿的版本,在官网上找个新版本。第一个命令执行成功之后,分别执行:

pacman -S git
pacman -S patch unzip grep

Step3. 安装bazel

进入https://github.com/bazelbuild/bazel/tags,选择合适的bazel版本进行下载。

bazel合适版本查询:https://www.tensorflow.org/install/source_windows

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dtYA1FXp-1616465501890)(C:\Users\30109\AppData\Roaming\Typora\typora-user-images\image-20210312153234256.png)]

将下载好的 .exe 文件复制到 C:\msys64 下(路径根据个人安装情况而定),更名为 bazel.exe

复制完成后,配置bazel环境变量(环境变量配置完成之后需要重启电脑以生效设置)
新建三个系统变量:BAZEL_SHBAZEL_VCBAZEL_VSFor Visual Studio 2017 and 2019, set one of BAZEL_VC or BAZEL_VS. Additionally you may also set BAZEL_VC_FULL_VERSION.

BAZEL_VS the Visual Studio installation directory

set BAZEL_VS=C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools

BAZEL_VC the Visual C++ Build Tools installation directory

set BAZEL_VC=C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\VC

BAZEL_VC_FULL_VERSION (Optional) Only for Visual Studio 2017 and 2019, the full version number of your Visual C++ Build Tools. You can choose the exact Visual C++ Build Tools version via BAZEL_VC_FULL_VERSION if more than one version are installed, otherwise Bazel will choose the latest version.)。

  • 相应的路径如以下表格所示:
变量
BAZEL_SH C:\msys64\usr\bin\bash.exe
BAZEL_VC C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC
BAZEL_VS C:\Program Files (x86)\Microsoft Visual Studio 14.0

Step4. 下载编译所需文件(tensorflow源码及其他文件)

  1. 进入tensorflow-v1.13.1源码的github的页面https://github.com/tensorflow/tensorflow/tree/v1.13.1 ,点击页面右侧绿色按钮Clone or download,然后点击Download ZIP进行下载

  2. 进入tensorflow-windows-build-script-master的github页面,下载tensorflow-windows-build-script-master.zip

以上两个 .zip 文件下载完成后,在D盘新建一个文件夹,命名为 tensorflow-1.13.1 (也可根据个人喜好决定)。

  • 将下载好的 tensorflow-1.13.1.zip 解压到刚刚新建的文件夹下,重新命名为 source;
  • 将 tensorflow-windows-build-script-master.zip 解压到任意位置,然后把其中的 patches 和 build.ps1 文件,复制到新建的 D:\tensorflow-1.13.1目录下。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wWEwy1yC-1616465501890)(C:\Users\30109\AppData\Roaming\Typora\typora-user-images\image-20210312163145643.png)]

  • patches 下的 eigen_half.patch 复制到 tensorflow-1.13.1\source\third_party

  • patches 下的 tf_exported_symbols_msvc.lds 复制到 tensorflow-1.13.1\source\tensorflow

  • 用文本编辑器打开 build.ps1 文件,将以下语句注释掉,防止编译时出现Copy-Item命令的问题。

Copy-Item …\patches\tf_exported_symbols_msvc.lds tensorflow\

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6FyT4V89-1616465501891)(C:\Users\30109\AppData\Roaming\Typora\typora-user-images\image-20210312164406150.png)]

可能的报错信息:

pip3 install six numpy wheel后面添加-i http://pypi.douban.com/simple --trusted-host pypi.douban.com防止安装失败,包括后面的两三个pip安装项

patch安装失败的话试试单独使用pacman -S --noconfirm patch安装,能成功最好,失败也不影响后面

git-fetch之前添加git init

Step5. 使用powershell进行配置与编译

C:\Windows\SysWOW64\WindowsPowerShell\v1.0 目录下,右键以管理员身份运行 powershell.exe

powershell 窗口中输入以下命令,转到 tensorflow-1.13.1 目录下:

cd D:\tensorflow-1.13.1

输入bazel编译的选项:

$parameterString = "--config=opt --config=cuda --define=no_tensorflow_py_deps=true --copt=-nvcc_options=disable-warnings //tensorflow:libtensorflow_cc.so --verbose_failures"

然后输入以下命令,执行 build.ps1 脚本文件:

.\build.ps1 -BazelBuildParameters $parameterString -BuildCppAPI -ReserveSource

执行命令时出现 UnauthorizedAccess 错误,说明可能是 powershell 的执行策略受限,输入以下命令查看当前执行策略:

Get-ExecutionPolicy

我这里显示的是Restricted(受限的),所以需要输入以下语句来取消限制:

Set-ExecutionPolicy Unrestricted

询问是否改变执行策略,输入 y,回车。
修改好后,可以再次输入:

Get-ExecutionPolicy

查看当前执行策略是否已经取消限制。

执行策略的问题解决以后,重新执行 build.ps1 脚本文件:

.\build.ps1 -BazelBuildParameters $parameterString -BuildCppAPI -ReserveSource

如果一切正常,我们将开始编译前的配置。可参照以下两图进行配置。有些提问可以直接按回车来选择默认配置,括号中出现 default 字眼的,都可以这么做。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fW4kitn8-1616465501891)(C:\Users\30109\AppData\Roaming\Typora\typora-user-images\image-20210312165933673.png)]

如果报错:D:\tensorflow-1.13.1\build.ps1 : 无法将“py”项识别为 cmdlet、函数、脚本文件或可运行程序的名称。请检查名称的拼写,如果包括路径,请确保路径正确,然后再试一次。

解决方法:以管理员权限打开PowerShell,将python.exe所在的路径加到系统环境变量Path中,命令如下:

[Environment]::SetEnvironmentVariable("Path", "$env:Path;C:\softwares\anaconda\install")

注意 :python版本必须为3.6.7。当问到GPU的计算能力(compute capability),即出现 [Default is: 3.5, 7.0]: 时,先不要急着按回车。我们先找到跟自己显卡对应的计算能力,再进行填写,可参考后面的方法来查看显卡的计算能力。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ApqsdbGS-1616465501891)(C:\Users\30109\AppData\Roaming\Typora\typora-user-images\image-20210323100148734.png)]

打开设备管理器,找到自己的显卡型号:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FbLUD6o0-1616465501892)(C:\Users\30109\AppData\Roaming\Typora\typora-user-images\image-20210312170040856.png)]

然后进入NVDIA官网的CUDA GPUs页面,点击 CUDA-Enabled GeForce and TITAN Products,找到自己的显卡型号对应的数值,将其填入 [Default is: 3.5, 7.0]: 后面,回车继续配置。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PXu0nNzC-1616465501892)(C:\Users\30109\AppData\Roaming\Typora\typora-user-images\image-20210312170100758.png)]

都配置完成后,编译正式开始。注意保持网络通畅,因为编译之前需要下载各种依赖库,网络异常会导致下载失败停止编译。

**报错:**如果icu、grpc包下载错误(报错信息中,有下载链接),通过chrome浏览器下载包,然后将tar.gz包上传到http文件服务器,通过http文件服务器加载tar.gz包。架设简单文件服务器参考https://jingyan.baidu.com/article/3c48dd348c5f04e10ae35876.html。

最终编译完成cpu版本的截图如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eIKFUOmp-1616465501893)(C:\Users\30109\AppData\Roaming\Typora\typora-user-images\image-20210321085104048.png)]

Step6. 整理生成的文件——dll,lib,include(!!!复制!!!不能剪切!!!因为有些是重复引用的)

新建一个文件夹,在文件夹中创建以下三个目录:dlllibinclude

在这里插入图片描述

根据编译结束时显示的动态库所在位置,找到生成的库 libtensorflow_cc.so 和 liblibtensorflow_cc.so.ifso。

  • libtensorflow_cc.so 更名为 tensorflow_cc.dll,放到刚才创建的 dll 目录下;
  • liblibtensorflow_cc.so.ifso 更名为 tensorflow_cc.lib,放到刚才创建的 lib 目录下。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Rr6bhaF3-1616465501893)(C:\Users\30109\AppData\Roaming\Typora\typora-user-images\image-20210321085304373.png)]

接下来要做的是填满 include 目录,该步相对繁琐,最终将包含以下文件夹:

在这里插入图片描述

1)在include目录中新建名为 _bin 的文件夹。参考以下路径,打开 _embedded_binaries 目录,将下图红框中的文件复制到 _bin 文件夹中:

C:\Users\xxx_bazel_xxx\install\d5b1be53d8db6a1e2d160364df2e7ef6\_embedded_binaries
或C:\Users\****\_bazel_****\install\d5b1be53d8db6a1e2d160364df2e7ef6\_embedded_binaries

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pIsnjKQT-1616465501894)(C:\Users\30109\AppData\Roaming\Typora\typora-user-images\image-20210321085607162.png)]

2-1) 参考以下路径,将下图红框中的 bazel-out 文件夹复制到 include 目录下:

C:\Users\xxx_bazel_xxx\y46qiod6\execroot\org_tensorflow
或C:\Users\****\_bazel_****\y46qiod6\execroot\org_tensorflow

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-z8jZ7Oag-1616465501894)(C:\Users\30109\AppData\Roaming\Typora\typora-user-images\image-20210321085734661.png)]

2-2) 参考以下路径,将 protobuf_archive 文件夹复制到 include 下的 bazel-out\x64_windows-opt\genfiles\external 目录中:

C:\Users\xxx_bazel_xxx\y46qiod6\external
或C:\Users\****\_bazel_****\y46qiod6\external

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OVRsioIS-1616465501894)(C:\Users\30109\AppData\Roaming\Typora\typora-user-images\image-20210321095843932.png)]

3) 将 D:\tensorflow-1.13.1\source 下的 tensorflowthird_party 复制到 include 目录下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2e1bqjPU-1616465501895)(C:\Users\30109\AppData\Roaming\Typora\typora-user-images\image-20210321100030375.png)]

4-1) 参照以下路径,将下图红框中的 external 文件夹复制到 include 目录下:

C:\Users\xxx_bazel_xxx\y46qiod6
或C:\Users\****\_bazel_****\y46qiod6

在这里插入图片描述

4-2) 参照以下路径,将 embedded_tools 文件夹下的所有文件复制到 include 下的 external\bazel_tools 目录中(如果 external 里面没有该文件夹,需新建并命名为 bazel_tools):

C:\Users\xxx_bazel_xxx\install\d5b1be53d8db6a1e2d160364df2e7ef6_embedded_binaries\embedded_tools

在这里插入图片描述

4-3) 将 D:\tensorflow-1.13.1\source 下的 tensorflow 复制到 include 下的 external\org_tensorflow 目录中(如果 external 里面没有该文件夹,需新建并命名为 org_tensorflow):

在这里插入图片描述

至此,调用tensorflow所需的库及包含的目录准备完毕!

测试

新建控制台程序,测试代码:

test_tensorflow.cpp

#include "TestTensorFlow.h"
#include "tensorflow/cc/client/client_session.h"
#include "tensorflow/cc/ops/standard_ops.h"
#include "tensorflow/core/framework/tensor.h"

int main() {
	using namespace tensorflow;
	using namespace tensorflow::ops;
	Scope root = Scope::NewRootScope();
	// Matrix A = [3 2; -1 0]
	auto A = Const(root, { { 3.f, 2.f },{ -1.f, 0.f } });
	// Vector b = [3 5]
	auto b = Const(root, { { 3.f, 5.f } });
	// v = Ab^T
	auto v = MatMul(root.WithOpName("v"), A, b, MatMul::TransposeB(true));
	std::vector<Tensor> outputs;
	ClientSession session(root);
	// Run and fetch v
	TF_CHECK_OK(session.Run({ v }, &outputs));
	// Expect outputs[0] == [19; -3]
	LOG(INFO) << outputs[0].matrix<float>();
	return 0;
}

test_tensorflow.h

#pragma once  //这一句防止重复include头文件

#define COMPILER_MSVC
#define NOMINMAX  //这一句防止max/min函数命名冲突#pragma once

环境配置

1)包含目录:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-10j0W89D-1616465501896)(C:\Users\30109\AppData\Roaming\Typora\typora-user-images\image-20210321112655337.png)]

C:\libtensorflow-cpu-x64-1.13.1
C:\libtensorflow-cpu-x64-1.13.1\include
C:\libtensorflow-cpu-x64-1.13.1\include\external\org_tensorflow
C:\libtensorflow-cpu-x64-1.13.1\include\external\protobuf_archive\src
C:\libtensorflow-cpu-x64-1.13.1\include\external\com_google_absl
C:\libtensorflow-cpu-x64-1.13.1\include\external\eigen_archive
C:\libtensorflow-cpu-x64-1.13.1\include\bazel-out\x64_windows-opt\genfiles

2)库目录:

C:\libtensorflow-cpu-x64-1.13.1\lib

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bKRQ8GYf-1616465501896)(C:\Users\30109\AppData\Roaming\Typora\typora-user-images\image-20210321112753230.png)]

3)链接器输入附加依赖项:

tensorflow_cc.lib;

环境配置好后,将之前生成的动态库放入应用程序目录,即复制 tensorflow_cc.dlltensorflow_cc.lib到与工程文件 .sln 同级的 x64\Release 文件夹下,如下图所示:

在这里插入图片描述

生成解决方案

报错1:

E1696 无法打开 源 文件 “tensorflow/core/framework/tensor.pb.h” Dll1 C:\libtensorflow-cpu-x64-1.13.1\include\tensorflow\cc\framework\ops.h 22

解决方法:相关问题描述可见https://github.com/tensorflow/tensorflow/issues/9253,不过没有拷贝,直接重启vs就行,重启治百病
报错2: C2857 在源文件中没有找到用 /Ycpch.h 命令行选项指定的“#include”语句

解决方法:在属性->c/c+±>预编译头中,选择“不适用预编译头”,把预编译头文件的pch.h删掉。

报错3:编译可能出现无法解析的外部符号的问题,以下面的错误为例:

无法解析的外部符号 “public: virtual __cdecl tensorflow::internal::LogMessage::~LogMessage(void)” (??1LogMessage@internal@tensorflow@@UEAA@XZ),该符号在函数 “public: void __cdecl tensorflow::internal::LogMessage::`vbase destructor’(void)” (??_DLogMessage@internal@tensorflow@@QEAAXXZ) 中被引用

解决方法:用文本编辑器打开 D:\tensorflow-1.13.1\source\tensorflow\tf_exported_symbols_msvc.lds ,将前面一个括号中带问号的内容:

??1LogMessage@internal@tensorflow@@UEAA@XZ

复制到该文件的末尾,如下图所示。
如果有多个无法解析外部符号的问题,用同样的方法逐一添加。全部添加完成后保存关闭文件,然后重新编译tensorflow,也就是说从运行脚本文件开始,后面的流程要重新走一遍。
img

    ??0MatMul@ops@tensorflow@@QEAA@AEBVScope@2@VInput@2@1AEBUAttrs@012@@Z
    ?Const@ops@tensorflow@@YA?AVOutput@2@AEBVScope@2@AEBUInitializer@Input@2@@Z
    ??1LogMessage@internal@tensorflow@@UEAA@XZ
    ??0LogMessage@internal@tensorflow@@QEAA@PEBDHH@Z
    ?WithOpNameImpl@Scope@tensorflow@@AEBA?AV12@AEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z
    ?NewRootScope@Scope@tensorflow@@SA?AV12@XZ
    ??1Scope@tensorflow@@QEAA@XZ
    ?Run@ClientSession@tensorflow@@QEBA?AVStatus@2@AEBV?$vector@VOutput@tensorflow@@V?$allocator@VOutput@tensorflow@@@std@@@std@@PEAV?$vector@VTensor@tensorflow@@V?$allocator@VTensor@tensorflow@@@std@@@5@@Z
    ??1ClientSession@tensorflow@@QEAA@XZ
    ??0ClientSession@tensorflow@@QEAA@AEBVScope@1@@Z
    ??0Initializer@Input@tensorflow@@QEAA@AEBV?$initializer_list@UInitializer@Input@tensorflow@@@std@@@Z

报错4:无法打开源文件 “google/protobuf/stubs/common.h”。文件不要剪切,要复制!!!

猜你喜欢

转载自blog.csdn.net/qq_41870658/article/details/115111148
今日推荐