TensorFlow C++接口編譯和使用


部分內容from: Tensorflow C++ 從訓練到部署(1):環境搭建

在之前的編譯中,已經編譯好了tensorflow_pkg相關的wheel。現在有一個需求,需要按照C++的代碼進行模型加載和訓練。查詢資料后發現,需要重新編譯一套TensorFlow支持的C++接口,主要是編譯出來libtensorflow_cc.so和libtensorflow_framework.so這兩個文件。

bazel build -c opt --copt=-mavx --copt=-msse4.2 --config=monolithic //tensorflow:libtensorflow_cc.so
bazel build -c opt --copt=-mavx  --copt=-msse4.2 --config=monolithic //tensorflow:libtensorflow_framework.so

像這種嚴格與機器相關的選項,雖然可以加快執行速度,但是在使用之前一定要查明自己的目標機器是否適合。

中間可能會遇到之前的一些問題,功查找https://www.cnblogs.com/jourluohua/p/9180709.html

編譯完成后,安裝第三方庫

source tensorflow/contrib/makefile/build_all_linux.sh
若出現 /autogen.sh: 4: autoreconf: not found 錯誤,安裝 sudo apt-get install autoconf automake libtool
安裝頭文件和lib文件(不安裝也可以,主要是要在CMakeLists文件中配置好就可以)
sudo cp -r bazel-genfiles/ /usr/local/include/tf
sudo cp -r tensorflow/cc /usr/local/include/tf/tensorflow
sudo cp -r tensorflow/core /usr/local/include/tf/tensorflow
sudo cp -r third_party /usr/local/include/tf
sudo cp bazel-bin/tensorflow/libtensorflow_cc.so /usr/local/lib
sudo cp bazel-bin/tensorflow/libtensorflow_framework.so /usr/local/lib

如果你使用的是C的接口,用的是libtensorflow.so庫的話,需要拷貝tensorflow/c/相關的文件

之后是新建一個Python文件,去生成相關的pb文件(代碼來源於他人代碼,有修改)

#!/usr/bin/env python
 
import tensorflow.compat.v1 as tf
import numpy as np
 
with tf.Session() as sess:
 
    a=tf.placeholder(tf.float32,shape=None, name='a')
    b=tf.placeholder(tf.float32,shape=None, name='b')
    c = tf.multiply(a, b, name='c')
 
    sess.run(tf.global_variables_initializer())
 
    tf.train.write_graph(sess.graph_def, 'model/', 'simple.pb', as_text=False)
 
    res = sess.run(c, feed_dict={'a:0': 2.0, 'b:0': 3.0})
    print("res = ", res)

生成了model/simple.pb文件

寫load_simple_net.cpp文件(代碼來源於他人代碼,有修改https://gitee.com/liuzc/tensorflow_cpp.git)

#include "tensorflow/core/public/session.h"
#include "tensorflow/core/platform/env.h"

using namespace tensorflow;
int main(int argc, char* argv[]) {
    // Initialize a tensorflow session
    Session* session;
    Status status = NewSession(SessionOptions(), &session);
    if (!status.ok()) {
        std::cerr << status.ToString() << std::endl;
        return 1;
    } else {
        std::cout << "Session created successfully" << std::endl;
    }

    if (argc != 2)
    {
        std::cerr << std::endl << "Usage: ./project path_to_graph.pb" << std::endl;
        return 1;
    }

    // Load the protobuf graph
    GraphDef graph_def;
    std::string graph_path = argv[1];
    status = ReadBinaryProto(Env::Default(), graph_path, &graph_def);
    if (!status.ok()) {
        std::cerr << status.ToString() << std::endl;
        return 1;
    } else {
        std::cout << "Load graph protobuf successfully" << std::endl;
    }

    // Add the graph to the session
    status = session->Create(graph_def);
    if (!status.ok()) {
        std::cerr << status.ToString() << std::endl;
        return 1;
    } else {
        std::cout << "Add graph to session successfully" << std::endl;
    }

    // Setup inputs and outputs:

    // Our graph doesn't require any inputs, since it specifies default values,
    // but we'll change an input to demonstrate.
    Tensor a(DT_FLOAT, TensorShape());
    a.scalar<float>()() = 2.0;

    Tensor b(DT_FLOAT, TensorShape());
    b.scalar<float>()() = 3.0;

    std::vector<std::pair<string, tensorflow::Tensor>> inputs = {
            { "a:0", a },
            { "b:0", b },
    };

    // The session will initialize the outputs
    std::vector<tensorflow::Tensor> outputs;

    // Run the session, evaluating our "c" operation from the graph
    status = session->Run(inputs, {"c:0"}, {}, &outputs);
    if (!status.ok()) {
        std::cerr << status.ToString() << std::endl;
        return 1;
    } else {
        std::cout << "Run session successfully" << std::endl;
    }

    // Grab the first output (we only evaluated one graph node: "c")
    // and convert the node to a scalar representation.
    auto output_c = outputs[0].scalar<float>();

    // (There are similar methods for vectors and matrices here:
    // https://github.com/tensorflow/tensorflow/blob/master/tensorflow/core/public/tensor.h)

    // Print the results
    std::cout << outputs[0].DebugString() << std::endl; // Tensor<type: float shape: [] values: 30>
    std::cout << "Output value: " << output_c() << std::endl; // 30

    // Free any resources used by the session
    session->Close();

    return 0;
}

添加CMakeLists文件,目錄結構變為

 

 添加eigen庫,這里的原因是TensorFlow默認的eigen庫,里邊實際上是不支持C++接口的,不信的人可以試下,里邊的unsupported/CXX/Tensor里邊自己include了自己,會導致遞歸死循環包含錯誤,因此需要自己添加eigen庫,拷貝到當前目錄eigen3文件夾下

修改CMakeLists文件,內容為

cmake_minimum_required(VERSION 3.5)
project(tensorflow_cpp)

set(CMAKE_CXX_STANDARD 11)

find_package(OpenCV 3.0 QUIET)
if(NOT OpenCV_FOUND)
    find_package(OpenCV 2.4.3 QUIET)
    if(NOT OpenCV_FOUND)
        message(FATAL_ERROR "OpenCV > 2.4.3 not found.")
    endif()
endif()

set(TENSORFLOW_INCLUDES
        /usr/local/include/tf/
        /usr/local/include/tf/bazel-genfiles
        /usr/local/include/tf/tensorflow/
        /usr/local/include/tf/tensorflow/third-party
        )

set(TENSORFLOW_LIBS
        /usr/local/lib/libtensorflow_cc.so
        /usr/local/lib/libtensorflow_framework.so
        )


include_directories(
        ${TENSORFLOW_INCLUDES}
        ${PROJECT_SOURCE_DIR}/eigen3
)


add_executable(load_simple_net load_simple_net.cpp)
target_link_libraries(load_simple_net
        ${TENSORFLOW_LIBS}
        ${OpenCV_LIBS}
        )

新建build文件,進入該build文件中

cd ./build
cmake ..
make

這里有一個非常重要的點,/usr/local/lib/libtensorflow_cc.so /usr/local/lib/libtensorflow_framework.so的順序關系,如果順序不對,會一直報

E tensorflow/core/common_runtime/session.cc:89] Not found: No session factory registered for the given session options: {target: "" config: } Registered factories are {}.

使用./load_simple_net  ../model/simple.pb,按道理可以得到正確的值

Session created successfully
Load graph protobuf successfully
Add graph to session successfully
Run session successfully
Tensor<type: float shape: [] values: 6>
Output value: 6

 

 

參考資料:

https://medium.com/jim-fleming/loading-tensorflow-graphs-via-host-languages-be10fd81876f

https://medium.com/jim-fleming/loading-a-tensorflow-graph-with-the-c-api-4caaff88463f#.z4qeoyfb0

https://www.tensorflow.org/install/install_c

http://www.liuxiao.org/2018/08/ubuntu-tensorflow-c-%e4%bb%8e%e8%ae%ad%e7%bb%83%e5%88%b0%e9%a2%84%e6%b5%8b1%ef%bc%9a%e7%8e%af%e5%a2%83%e6%90%ad%e5%bb%ba/

https://blog.csdn.net/melissa_cjt/article/details/85983659

https://www.cnblogs.com/shouhuxianjian/p/9416934.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM