System information
OS Platform and Distribution : ( Ubuntu 18.04)
TensorFlow installed from : (source)
TensorFlow version: Tags v2.4.1
Python version: Python 3.7.6
Installed using virtualenv? pip? conda?: conda
Bazel version (if compiling from source): have tried bazel 3.4.0 、 bazel 3.1.0
GCC/Compiler version (if compiling from source): gcc (GCC) 7.4.0
CUDA/cuDNN version: cuda_11.1 , cudnn 8.0.5
GPU model and memory: rtx3060
nvidia-driver version: 460.91
eigen version : eigen-3.3.90
建议搭配:tf2.4.0 、cuda 11.0、cudnn 8.0.5
构建tensorflow的c++接口
bazel:用来自动化构建大型工程的,和make、maven属于同一类工具。
bazel版本需要和tensorflow版本对应
tf2.4 适配的bazel版本为3.1.0
使用sh文件安装bazel,执行bazel version时报错
/usr/local/lib/bazel/bin/bazel-real: cannot execute binary file: Exec format error
改为下载zip后解压安装
wget https://github.com/bazelbuild/bazel/releases/download/3.1.0/bazel-3.1.0-dist.zip
mkdir bazel
unzip -d bazel bazel-3.1.0-dist.zip
cd bazel
bash ./compile.sh
sudo cp output/bazel /usr/local/bin
bazel version
tf_http_archive(
name = "com_google_protobuf",
patch_file = clean_dep("//third_party/protobuf:protobuf.patch"),
sha256 = "cfcba2df10feec52a84208693937c17a4b5df7775e1635c1e3baffc487b24c9b",
strip_prefix = "protobuf-3.9.2",
system_build_file = clean_dep("//third_party/systemlibs:protobuf.BUILD"),
system_link_files = {
"//third_party/systemlibs:protobuf.bzl": "protobuf.bzl",
},
urls = [
"https://storage.googleapis.com/mirror.tensorflow.org/github.com/protocolbuffers/protobuf/archive/v3.9.2.zip",
"https://github.com/protocolbuffers/protobuf/archive/v3.9.2.zip",
],
)
安装步骤
wget https://storage.googleapis.com/mirror.tensorflow.org/github.com/protocolbuffers/protobuf/archive/v3.9.2.zip
unzip v3.9.2.zip
cd protobuf-3.9.2
./autogen.sh
./configure
make
sudo make install
protoc --version
tar -zxvf eigen-3.3.90.tar.gz
cd eigen-3.3.90/
mkdir build
cd build
cmake ..
sudo make
sudo make install
mkdir tensorflow
cd tensorflow
git clone --depth 1 --branch v2.4.1 https://github.com/tensorflow/tensorflow.git
cd tensorflow
./configure
compute capability计算力点进提示给的nvidia官网url中查看
bazel build --config=opt //tensorflow:libtensorflow_cc.so
bazel build --config=opt --config=cuda //tensorflow:libtensorflow_cc.so
- 编译过程报错
1)...include/cudnn_backend.h No such file or directory
解决方法:缺失cudnn_backend.h、cudnn_adv_infer.h等文件,下载cudnn压缩包将解压后的文件夹中所有报错中提示缺失的文件重新拷贝到cuda文件夹下。
2)llvm下载报错Error downloading [https://storage.googleapis.com/mirror.tensorflow.org/github.com/llvm/llvm-project/archive/f402e682d0ef5598eeffc9a21a691b03e602ff58.tar.gz, https://github.com/llvm/llvm-project/archive/f402e682d0ef5598eeffc9a21a691b03e602ff58.tar.gz]
去报错提示中的github地址(我这里是https://github.com/llvm/llvm-project/archive/f402e682d0ef5598eeffc9a21a691b03e602ff58.tar.gz)手动下载llvm-project,
放到任意本地路径下 (我的路径 /home/app/llvm-project-f402e682d0ef5598eeffc9a21a691b03e602ff58.tar.gz;
然后修改 tensorflow/tensorflow/workspace.bzl 文件中的llvm下载路径,改为所存的本地路径
LLVM_URLS = [
"file:///home/app/llvm-project-f402e682d0ef5598eeffc9a21a691b03e602ff58.tar.gz",
"https://github.com/llvm/llvm-project/archive/{commit}.tar.gz".format(commit = LLVM_COMMIT),
]
cd tensorflow/tensorflow/lite/tools/make
./download_dependencies.sh
若网络原因下载失败,可分别手动下载相应文件并解压,下载的文件url见 download_dependencies.sh文件;
将以上下载的文件解压后并按照以上文件名进行命名,统一存放在 tensorflow/tensorflow/lite/tools/make/downloads
文件夹中。
使用tensorflow c++接口运行.pb模型
大概的步骤:
$ cd ~/demo/build
$ cmake ..
$ make
$ ./demo
注: 我的tensorflow 2.4.1编译完成后没有contrib文件夹、没有bazel-genfiles文件夹。
这里采取的是将依赖的文件夹移动到运行项目demo/
目录下,为的是方便后期该项目迁移到其他主机运行时能带着 依赖一起迁移。
如果你只在本机运行该项目,那么移动的目的文件夹就是/usr/local/include/tf/
我移动后的 demo/
文件夹层级结构:
demo/
CMakeLists.txt
build/
model.pb
include/
UseTensorFlowDLL.h
src/
main.cpp
opencv3.4.0/
bin/
include/
lib/
share/
tf2/
bazel-bin/
external/
_solib_local/
tensorflow/
third_party/
eigen/
..太多这里省略
lib/
libtensorflow_cc.so.2
libtensorflow_framework.so.2
tensorflow/
..省略
third_party/
..省略
其中tf2目录为自己手动创建,tf2/ 下的各个文件夹手动从编译完成的目录下拷贝过来,各文件夹来源:
① bazel-bin/:tensorflow/bazel-bin/
(tensorflow/
为编译完成的最终文件夹)
② eigen/ :tensorflow/lite/tools/make/downloads/eigen
③ lib/: 两个文件(拷贝完可能需要重命名)分别来自
tensorflow/bazel-bin/tensorflow/libtensorflow_cc.so.2.4.1
和
tensorflow/bazel-bin/tensorflow/libtensorflow_framework.so.2.4.1
④ tensorflow/ :tensorflow/
⑤ third_party/ :tensorflow/third_party
其中CMakeLists.txt 内容:
# cmake needs this line
cmake_minimum_required(VERSION 3.10)
# Define project name
project(shufflenetPbLinuxDemo)
find_package(OpenCV REQUIRED)
message(STATUS "OpenCV library status:")
message(STATUS " config: ${OpenCV_DIR}")
message(STATUS " version: ${OpenCV_VERSION}")
message(STATUS " libraries: ${OpenCV_LIBS}")
message(STATUS " include path: ${OpenCV_INCLUDE_DIRS}")
set(TENSORFLOW_LIBS
${CMAKE_CURRENT_SOURCE_DIR}/tf2/lib/libtensorflow_cc.so.2
${CMAKE_CURRENT_SOURCE_DIR}/tf2/lib/libtensorflow_framework.so.2
)
# 头文件的搜索目录
include_directories(
${CMAKE_CURRENT_SOURCE_DIR}/include
${CMAKE_CURRENT_SOURCE_DIR}/tf2
${CMAKE_CURRENT_SOURCE_DIR}/tf2/bazel-bin
${CMAKE_CURRENT_SOURCE_DIR}/tf2/tensorflow
${CMAKE_CURRENT_SOURCE_DIR}/tf2/third-party
${CMAKE_CURRENT_SOURCE_DIR}/tf2/eigen
)
# Declare the executable target built from your sources
add_executable(shufflenetPbLinuxDemo ${CMAKE_CURRENT_SOURCE_DIR}/src/main.cpp)
# Link your application with OpenCV libraries
target_link_libraries(shufflenetPbLinuxDemo PRIVATE ${OpenCV_LIBS} ${TENSORFLOW_LIBS})
报错及解决办法
正常情况下,pb.h是在编译过程中由protobuf编译生成的,应该存在于
bazel-genfiles/tensorflow/core/framework
文件夹下。
.pb.h is a generated file when you build with bazel build. The
.pb.h files should appear under bazel-genfiles folder thereafter.
而我之前用tensorflow2.4.0版本虽然也没生成bazel-genfiles/ ,但没有这个报错,不知道为什么换成tf2.4.1 分支后就报错了。
解决方法:手动用命令挨个将报错中的 proto文件转为pb.h
sudo protoc <protofile> --cpp_out=./ </protofile>
在tensorflow github的相关提问
若执行protoc命令报错 tensorflow/core/framework/xx.proto File not found
即import的文件未找到。可能是执行protoc命令时所处的路径层级不对,在import后跟的路径的层级下重新尝试。
方法:设置环境变量:
sudo gedit /etc/profile
添加: export OpenCV_DIR=/home/workspace/demo/opencv3.4.0
保存退出, source /etc/profile
文件头加入tensorflow定义域:
#include "tensorflow/core/public/session.h"
#include "tensorflow/core/platform/env.h"
如果你的 model.pb为 meta_graph,ReadBinaryProto可能只适用于frozen graph,
因此需要将加载模型方式改为 tensorflow::LoadSavedModel(session_options, run_options, model_path,{tensorflow::kSavedModelTagServe}, &bundle))
LoadSavedModel示例
find . -name "eigen*" -type d
修改CMakeLists.txt 的include_directories 里eigen的路径,换成上面find出来的结果(如果find出来多个路径则可以挨个尝试)。
原因:程序发生了越界访问
1)内存访问越界(数组越界)
2)多线程 线程不安全
3)堆栈溢出(使用大的局部变量容易造成栈溢出,因为局部变量都分配在栈上)
扩展:core报错具体原因可以 配置操作系统使其生成core文件,用gdb查看core文件 结合程序崩溃后的core文件分析bug
最终原因以及解决办法:
升级到tf2.4.1+cuda11.1后报这个错是因为main.cpp最后输出outputs置信度这里的outputs数组越界,
tensorflow::Status status_run = session->Run(inputs, { out_put_nodes }, {}, &outputs);
auto confidence_vector = outputs[0].tensor<float, 2>();
for (int ProposalNum = 0; ProposalNum < maxbatchSize; ProposalNum++) {
float confidence_float1 = confidence_vector(ProposalNum, 1);
cout << "the confidence is:" << confidence_float1 << endl;
}
return 0;
outputs[0] 越界
是因为session 根本就没有run成功,
(通过在session->Run 之后加上
tensorflow::Status status_run = session->Run(inputs, {out_put_nodes}, {}, &output)
if (!status_run.ok()) {
std::cout << "ERROR: RUN failed in session run..." << std::endl;
std::cout << status_run.ToString() << "\n";
判断出session没有run成功,所以outputs自然是空数组, outputs[0]
也就越界访问了)
而session没有run成功的原因在 下一个问题中描述。
原因: main.cpp中的 Tensor变量
ShuffleOutputPb:0
和python中生成pb模型的设置的tensor名不一样,修改main.cpp中的变量名。
然后再重新跑,终于status_run.ok()
为True了,但是又报下面的错:
① main.cpp 中的 bundle.session->Run(inputs,{out_put_nodes},{},&outputs);
这里直接写inputs,而不是 {{input_name, input}}
因为本项目中已经提前把input_name和resized_tensor都push_back进inputs张量中了。
② OP_REQUIRES failed at conv_ops.cc:Not found: No algorithm worked!
原因:tensorflow官方github的issue中查询这个报错,判断可能是OOM 内存超出,可以在运行时同时
watch -n 0.5 nvidia-smi
看到当memory使用快到达最大容量时,就报错。
c++的解决方法:
在session定义前如果没有设置限制GPU的内存使用,要加上内存限制的相关语句:
tensorflow::SessionOptions session_options;
tensorflow::ConfigProto* session_options_config = &session_options.config;
session_options_config->set_allow_soft_placement(true);
session_options_config->mutable_gpu_options()->set_per_process_gpu_memory_fraction(0.33);
session_options_config->mutable_gpu_options()->set_allow_growth(true);
status = NewSession(session_options, &session);
status_load = tensorflow::ReadBinaryProto(tensorflow::Env::Default(), "model.pb", &graphdef);
status_create = session->Create(graphdef);
我的问题是把 session_options_config-> ...
这3行写在了NewSession定义之后了,把这3行设置移到 NewSession定义语句前面就可以了。
问题搜索的网站:
1、tensorflow官方github的 Issues 中搜索报错或问题关键词。
2、和cuda相关的问题搜索 nvidia官网论坛
3、stackoverflow
总结解决问题中卡壳的原因以及获取的经验:
① 如果报错没有展开详细描述,寻找其是否存在错误log日志,根据错误日志分析原因。
② 明确报错的最初有可能产生位置,而非眉毛胡子一把抓。
③ 同样的代码在别人主机上能运行成功,不代表这份代码或流程就是正确的(可能其中几行逻辑错误,但他人主机上这几行等于注释、不起作用)
重点是理清排查思路,再下手。
Original: https://blog.csdn.net/qq_33936417/article/details/121955645
Author: nolabel
Title: linux上的tensorflow 2.4.1-gpu c++接口编译并用其运行.pb模型
相关阅读
Title: AttributeError: module ‘tensorflow_core.compat.v1‘ has no attribute ‘contrib‘
由于tensorflow版本问题,在tensorflow2.x版本里没有contrib组件,因此无法使用LSTMRNN实例中的sequence_loss_by_example函数。
AttributeError: module 'tensorflow_core.compat.v1' has no attribute 'contrib'
解决办法:找到自己运行代码的环境下的Lib\site-packages\tensorflow_core,在我的机器上是如下:
C:\Users\Dell\anaconda3\envs\tf_gpu\Lib\site-packages\tensorflow_core
然后在这个文件夹下创建一个新的.py文件,即seq_loss.py文件,里面代码为
from six.moves import xrange # pylint: disable=redefined-builtin
from six.moves import zip # pylint: disable=redefined-builtin
from tensorflow.python.framework import dtypes
from tensorflow.python.framework import ops
from tensorflow.python.ops import array_ops
from tensorflow.python.ops import control_flow_ops
from tensorflow.python.ops import embedding_ops
from tensorflow.python.ops import math_ops
from tensorflow.python.ops import nn_ops
from tensorflow.python.ops import rnn
from tensorflow.python.ops import rnn_cell_impl
from tensorflow.python.ops import variable_scope
from tensorflow.python.util import nest
def sequence_loss_by_example(logits,
targets,
weights,
average_across_timesteps=True,
softmax_loss_function=None,
name=None):
if len(targets) != len(logits) or len(weights) != len(logits):
raise ValueError("Lengths of logits, weights, and targets must be the same "
"%d, %d, %d." % (len(logits), len(weights), len(targets)))
with ops.name_scope(name, "sequence_loss_by_example",
logits + targets + weights):
log_perp_list = []
for logit, target, weight in zip(logits, targets, weights):
if softmax_loss_function is None:
TODO(irving,ebrevdo): This reshape is needed because
sequence_loss_by_example is called with scalars sometimes, which
violates our general scalar strictness policy.
target = array_ops.reshape(target, [-1])
crossent = nn_ops.sparse_softmax_cross_entropy_with_logits(
labels=target, logits=logit)
else:
crossent = softmax_loss_function(labels=target, logits=logit)
log_perp_list.append(crossent * weight)
log_perps = math_ops.add_n(log_perp_list)
if average_across_timesteps:
total_size = math_ops.add_n(weights)
total_size += 1e-12 # Just to avoid division by 0 for all-0 weights.
log_perps /= total_size
return log_perps
这里怎么创建.py文件呢?如下步骤:
然后进去之后
然后把这个文件复制粘贴到C:\Users\Dell\anaconda3\envs\tf_gpu\Lib\site-packages\tensorflow_core下面即可。
然后再LSTMRNN实例代码添加头文件
from tensorflow_core import seq_loss
并且将计算损失调用函数语句
losses = tf.contrib.legacy_seq2seq.sequence_loss_by_example
改为
losses = seq_loss.sequence_loss_by_example
即可。
这时候运行的时候可能还有问题是
TypeError: ms_error() got an unexpected keyword argument 'labels'
这是因为
; def ms_error(self, y_target, y_pre):
return tf.square(tf.sub(y_target, y_pre))
这里定义传入参数的错误,改为
def ms_error(self,labels,logits):
return tf.square(tf.subtract(labels,logits))
应该就好了。
Original: https://blog.csdn.net/qq_38766019/article/details/123480243
Author: qq_38766019
Title: AttributeError: module ‘tensorflow_core.compat.v1‘ has no attribute ‘contrib‘