List of headers to use Tensorflow C++ API using libtensorflow_cc.so - tensorflow

I want to know what all header files are required in order to use Tensorflow's C++ APIs. Like in case of C APIs, there is just a single header c_api.h which has all the functions, etc. declared, is there any such single header for C++ APIs? I tried searching this, but unable to understand what is required and what is not.
There is a huge list of headers in tensorflow/cc, tensorflow/core and tensorflow/c which are used to build libtensorflow_cc.so and we also ship most of these in the tensorflow's distribution (By TF's distribution I mean TF which is built using bazel build -c opt --config=cuda //tensorflow/tools/pip_package:build_pip_package). Is that list of headers sufficient in order to use C++ API? or do we need to build any additional target in tensorflow/BUILD?
I've also gone through https://www.tensorflow.org/api_docs/cc/ but can't really make out the exact list of required headers.
In one of the related posts, I found that tensorflow/bazel-genfiles contain the required headers. Please confirm this.
Thanks in advance,
Nishidha

For those who are building TensorFlow v2 C++ for Windows using bazel, kindly use
bazel build --config=opt tensorflow:install_headers
This will generate an include folder with the cc header files in bazel-bin/tensorflow/.

as far as I know, there is no official distributable C++ API package. There is, however, tensorflow_cc project that builds and installs TF C++ API for you, along with convenient CMake targets you can link against.
Although it probably installs slightly more files than necessary, you can find the list of installed headers in CMakeLists.txt:130:
# install *all* files with .h extension
/tensorflow/**/*.h
# install all dependencies downloaded by contrib/makefile
/tensorflow/tensorflow/contrib/makefile/downloads/
# install all files from third_party folder (e.g., Eigen/Tensor)
/tensorflow/third_party/
And you can find the list of directories which should be included by your compiler in CMakeLists.txt:58:
/tensorflow
/tensorflow/bazel-genfiles
/tensorflow/tensorflow/contrib/makefile/downloads
/tensorflow/tensorflow/contrib/makefile/downloads/eigen
/tensorflow/tensorflow/contrib/makefile/downloads/gemmlowp
/tensorflow/tensorflow/contrib/makefile/gen/protobuf-host/include
Note that C++ API requires also eigen and protobuf headers and libraries, which are, in case of tensorflow_cc, built using contrib/makefile from TF repo.
You may prefer to use tensorflow_cc directly so that you don't have to bother with all this manually.

An alternative way to build libtensorflow_cc.so is to use tensorflow/tensorflow:devel-gpu docker image, then build it with command:
bazel build --config=opt //tensorflow:libtensorflow_cc.so

Related

What are the steps to build Tensorflow with a custom oneDNN library implementation?

I am using a custom oneDNN library implementation which I need Tensorflow (v2.4.0) to build against.
However, I noticed that there are no build options to use a system-provided OneDNN libary when building Tensorflow.
I would like to know what are the steps to support a Tensorflow build that uses a oneDNN library provided by the system.
Some specifics...
The oneDNN library version is 1.6.4 and is already installed in the system (Linux).
This version corresponds to the one Tensforflow uses when compiling with the "--config=mkl_opensource_only" Bazel flag.
I have access to the library source code, but it would be best to use the compiled library.
The target architecture is RISC-V and the OS is Linux.
There is no easy way of telling bazel to link against a custom library, but if you have the modified source directory of oneDNN you can edit tensorflow/workspace.bzl file and replace mkl_dnn_v1 repository definition with a new_local_repository rule to point to your modified source directory. I.e. replace this block:
tf_http_archive(
name = "mkl_dnn_v1",
build_file = clean_dep("//third_party/mkl_dnn:mkldnn_v1.BUILD"),
sha256 = "5369f7b2f0b52b40890da50c0632c3a5d1082d98325d0f2bff125d19d0dcaa1d",
strip_prefix = "oneDNN-1.6.4",
urls = [
"https://storage.googleapis.com/mirror.tensorflow.org/github.com/oneapi-src/oneDNN/archive/v1.6.4.tar.gz",
"https://github.com/oneapi-src/oneDNN/archive/v1.6.4.tar.gz",
],
)
With something like this:
native.new_local_repository(
name = "mkl_dnn_v1",
build_file = clean_dep("//third_party/mkl_dnn:mkldnn_v1.BUILD"),
path = "/path/to/your/modified/oneDNN/sources",
)
You might also want to modify third_party/mkl_dnn/mkldnn_v1.BUILD file if you have added any new source files.
Addendum:
--config=mkl_opensource_only seems to be broken now, you might have a better luck using just --config=mkl instead.

cmake - linking static library pytorch cannot find its internal functions during build

I'm trying to build a program using cmake. For several reasons, the program must be built using static libraries rather than dynamic libraries, and I need to use PyTorch so this is what I've done:
Downloaded and installed PyTorch static library (I've found libtorch.a in the proper path, in /home/me/pytorch/torch/lib)
Made CMakeLists.txt with the following contents:
cmake_minimum_required(VERSION 3.5.1 FATAL_ERROR)
project(example-app LANGUAGES CXX)
find_package(Torch REQUIRED)
add_executable(example-app example-app.cpp argparse/argparse.cpp)
target_link_libraries(example-app "${TORCH_LIBRARIES}" -static -fopenmp)
set_property(TARGET example-app PROPERTY CXX_STANDARD 14)
FYI, example-app.cpp is the file with the main function, and argparse/ is a directory with some source code for functions called in example-app.cpp
It works until cmake -DCMAKE_PREFIX_PATH=/home/me/pytorch/torch .., but the following build incurs some errors, saying it could not find the reference to some functions, namely functions starting with fbgemm::. fbgemm is (as long as I know) some sort of GEMM library used in implementing PyTorch.
It seems to me that while linking the static PyTorch library, its internal libraries like fbgemm stuff have not been linked properly, but I'm not an expert on cmake and honestly not entirely sure.
Am I doing something wrong, or is there a workaround for this problem? Any help or push in the right direction would be greatly appreciated.
P.S.
The exact error has not been posted because it is way too long, but it consists of mostly undefined reference to ~ errors. If looking at the error message might be helpful for some people, I'd be happy to edit the question and post it.
building and running the file works fine if I remove the parts that require the library's functions from the code without commenting out #include <torch/torch.h> from example-app.cpp.
Lately went through similar process with static linking of PyTorch and to be honest it wasn't too pretty.
I will outline the steps I have undertaken (you can find exact source code in torchlambda, here is CMakeLists.txt (it also includes AWS SDK and AWS Lambda static builds), here is a script building pytorch from source ( cloning and building via /scripts/build_mobile.sh with only CPU support)),
though it's only with CPU support (though similar steps should be fine if you need CUDA, it will get you started at least).
Pytorch static library
Pre-built static PyTorch
First of all, you need pre-built static library files (all of them need to be static, hence no .so, only those with .a extension are suitable).
Tbh I've been looking for those provided by PyTorch on installation page, yet there is only shared version.
In one GitHub issue I've found a way to download them as follows:
Instead of downloading (here via wget) shared libraries:
$ wget https://download.pytorch.org/libtorch/cu101/libtorch-shared-with-deps-1.4.0.zip
you rename shared to static (as described in this issue), so it would become:
$ wget https://download.pytorch.org/libtorch/cu101/libtorch-static-with-deps-1.4.0.zip
Yet, when you download it there is no libtorch.a under lib folder (didn't find libcaffe2.a either as indicated by this issue), so what I was left with was building explicitly from source.
If you have those files somehow (if so, please provide where you got them from please), you can skip the next step.
Building from source
For CPU version I have used /pytorch/scripts/build_mobile.sh file, you can base your version off of this if GPU support is needed (maybe you only have to pass -DUSE_CUDA=ON to this script, not sure though).
Most important is cmake's -DBUILD_SHARED_LIBS=OFF in order to build everything as static library. You can also check script from my tool which passes arguments to build_mobile.sh as well.
Running above will give you static files in /pytorch/build_mobile/install by default where there is everything you need.
CMake
Now you can copy above build files to /usr/local (better not to unless you are using Docker as torchlambda) or set path to it from within your CMakeLists.txt like this:
set(LIBTORCH "/path/to/pytorch/build_mobile/install")
# Below will append libtorch to path so CMake can see files
set(CMAKE_PREFIX_PATH "${CMAKE_PREFIX_PATH};${LIBTORCH}")
Now the rest is fine except target_link_libraries, which should be (as indicated by this issue, see related issues listed there for additional reference) used with -Wl,--whole-archive linker flag, which brought me to this:
target_link_libraries(example-app PRIVATE -lm
-Wl,--whole-archive "${TORCH_LIBRARIES}"
-Wl,--no-whole-archive
-lpthread
${CMAKE_DL_LIBS})
You may not need either of -lm, -lpthread or ${CMAKE_DL_LIBS}, though I needed it when building on Amazon Linux AMI.
Building
Now you are off to building your application. Standard libtorch way should be fine but here is another command I used:
mkdir build && \
cd build && \
cmake .. && \
cmake --build . --config Release
Above will create build folder where example-app binary should be now safely located.
Finally use ld build/example-app to verify everything from PyTorch was statically linked, see aforementioned issue point 5., your output should look similar.

How to force tensorflow to use a custom version of Eigen?

I am compiling Tensorflow 1.5, and I want to force bazel to include a custom version of the eigen header files, which are at:
usr/local/lib/python2.7/dist-packages/...
Conversely, whenever I try to compile (even after a bazel clean --expunge) tensorflow uses different files, which are copied during the build procedure at:
/root/.cache/bazel/_bazel_root/
Is there any way to force tensorflow to use different files?
You can change the tf_http_archive rule for eigen_archive (you must not change the name) in tensorflow/workspace.bzl to new_local_repository and use Tensorflow's eigen BUILD file (//third_party:eigen.BUILD).

Integrating tensorflow in a larger C++ project -- Library conflicts

Objective: Integrate tensorflow into a larger project.
Solution: 1) Integrate tensorflow into cmake by passing appropriate arguments to bazel and get a working build.
2) Unzip the *.whl file to get the library and headers.
Problem: Tensorflow builds but has its own header files for protobufs and Eigen. My project also depends on these two libraries and the versions might mismatch. However, I can use the libraries that tensorflow fetches and replace the one we currently use. We currently build protobuf in our system.
Question: I can find the protobuf and Eigen header files used by tesorflow inside the whl files built, but I cannot find the .so files.
My understanding of bazel is low, but it might be that it is removing the .so files from the sandbox it uses, I am not sure.
What can I do to always fetch the lib and include folders for tensorflow dependencies that it dowloads. Namely, protobuf. Eigen is header only.
Tried already: search in ~/.cache/bazel/ directory.

Compiling againt another version of Eigen using CMake

Am using ubuntu 16 which seems automatically linking against Eigen version 3.2.92 located at /usr/include/Eigen3. I would like to link against version 3.2.0. Thus my questions is
How could I get Eigen version 3.2.0? It is not clear from Eigen website
What I did so far is just copying /usr/include/Eigen3 from an ubuntu 14 machine, since the latter automatically comes with version 3.2.0
How to link against it using CMake?
Tried
SET (EIGEN3_INCLUDE_DIR "/home/usr/mylib/eigen/eigen3/Eigen") but without success.
For info, am using ROS (Kinetic) catkin. It happens that catkin somehow forces the development packages to linking/compiling against packages installed by default (/usr/include/..)
Other versions of Eigen are available on the website or better, from the hg repo.
How is the EIGEN3_INCLUDE_DIR used in your cmake file? For example, in one of my projects, we have set(EIGEN_INCLUDE_DIR ${SOURCE_DIR}/Common). Note that it doesn't have the "3" (it's just a variable name) and that it doesn't include the last "/Eigen" in the path.
First of all, Eigen is a header-only library, so you are not linking against it :-) Instead you want to use specific header files.
For your own packages, you can use include_directories(SYSTEM ${EIGEN3_INCLUDE_DIR}, assuming you set EIGEN3_INCLUDE_DIR correspondingly to the version you want to use. Beware that if that version differs too much (e.g. 2.x vs 3.x) with versions used by interfaces (e.g. tf library?), this may cause some issues if datatypes changed. You also need to make sure that no other directive overwrites that - best to check the parameters to g++ for that.