How to use your C++ muscle using TensorFlow 2.
0 and XCode (without using Bazel builds)Benny FriedmanBlockedUnblockFollowFollowingApr 16This post will describe how to code in C++ using TensorFlow, on a Mac, while bypassing Bazel builds, which I find too cumbersome to use.
First, a confession:I studied Computer Science in the 90’s.
As a result, my programming mind is heavily influenced by C++, the language I like and prefer.
When everyone began coding in Java, I had already moved into management positions, so I did not go through the process of moving to what most people call 3rd generation languages (which refers to having a framework built inside).
I like the aesthetics of C++, and with its recent developments (mainly incorporating STD as part of the language) I think it also overcame the disadvantages of pointer related bugs which used to result in crashes and memory leaks.
According to a recent survey by Stack Overflow, Python is the fastest growing major programing language.
It is not at the top of the list, but over 40% of developers are using it.
C++ is being used by 23.
Maybe I’m old-fashioned.
There, I said it.
When I became interested in Machine Learning, I had to learn Python.
This is a must, as most frameworks do not support any other language, making Python the de-facto language of the domain.
Python is nice, don’t get me wrong.
It also contains some concepts from C++ and its internals are also written in C++ (AFAIK).
However white spaces and indentations are something that are difficult for me to wrap my head around.
So when I heard that TensorFlow 2.
0 will be including some major improvements in the C++ APIs, I had to check it out.
I use a Mac, and I guess some of you do as well.
This is still not mainstream, but it makes it easier to bridge the gap between Windows and Linux.
Doing without BazelThis post will explain how to get started with TensorFlow 2.
0 Alpha, on a Mac with a standalone project that you can use XCode for, without using a Bazel builds in terminal.
Most of the instructions you can find on the web deal with Bazel builds.
I find Bazel a little bit cumbersome and less intuitive, so I will show you how to start with Bazel to build the basic framework and then how to move on into developing your C++ code in XCode without needing a Terminal for every step in the way.
Let’s start!To be able to get there, you will need to do the following:1.
Install some prerequisites2.
Build TensorFlow 2.
0 Alpha from source3.
Build some other dependencies4.
Create an XCode project and configure it5.
Compile a test project to validate everything is installed properlySome instructions here are taken from the TensorFlow install guide page.
Requirements to begin with:1.
2 and above (I have 10.
Python 2 or 3 (I have 3.
Pip (if you do not have pip, run “sudo easy_install pip”)PrerequisitesOpen a Terminal window and start installing:pip install -U –user pip six numpy wheel setuptools mockpip install -U –user keras_applications==1.
6 –no-depspip install -U –user keras_preprocessing==1.
5 –no-depsInstalling Bazel:Follow the instructions here, but if you use a MacOS — continue with this:Install XCode command-line tools:1.
Go to https://developer.
com/download/, scroll down and click See more downloads.
In the small search box on the left, write “command line” and hit enter.
Select the appropriate XCode version and click the + sign.
Click the link to download the dmg file and install it.
Accept the license agreementThat’s a tricky part.
The instructions say you only need to run:sudo xcodebuild -license acceptbut this did not work for me.
After looking around, this is the safest sequence that will help you pass this part:sudo xcode-select -s /Applications/Xcode.
app/Contents/Developersudo xcodebuild -licenseNow type your local password, the license agreement should be displayed.
Scroll down using space all the way down (read it, if you like) and at the end type “agree” and hit enter.
Go to this URL and search for the relevant OS you have.
For MacOS this should be bazel-0.
sh (or a newer version which means 0.
1 will be different)2.
Download this file to your home directory and open terminal3.
Run the two following commands (assuming you are the home directory and the sh file is there):chmod +x bazel-0.
sh — user(again, if you have a different version change the commands)4.
Check that bazel is working:bazel versionIf it is not, check your path, it might be missing $(HOME)/binInstall a few more packages:Brew install autoconf automake libtool cmakeDownload and install TensorFlowFirst create a folder where you want to keep all the code.
I will show you how to separate your project from the framework, so select a structure that will not confuse you.
I have a main folder under my home that I named “Code” and under it I have my projects.
I created a new folder under that, that is called Tensorflow2.
There I have the framework code.
Download the framework code1.
Open terminal and cd to that directory2.
Download the source files:git clone https://github.
This will get you code from Master.
If you want a release branch (which at this time is not a release yet) you can check it out.
Example:git checkout v2.
At the same place in terminal (under the tensorflow directory — this is your root folder) run.
Now comes the part where the script asks you questions, and you need to answer3.
It will tell you if it found bazel and what version, and will ask for the python location.
The easiest way to find it is to open a new Terminal windows and to typewhich python3(replace python3 with whatever you use to run python, run “python3 –version” to see what version it is)5.
Then it will ask you a bunch of other questions about special support for various features.
I selected the default for all apart from the one.
That one is about CPU features.
It will ask you for “optimization flags to use during compilation” with bazel.
This is important for two reasons:a.
It will make your models run fasterb.
It will eliminate some warnings that will be displayed every time you run your code.
I found out about this only after being able to run my project, so I had to go back and run configure again and type “-mavx -mavx2 -mfma -msse4.
2” when prompted for these flags.
Not sure how you can find that out up front, try to look here or here.
So I recommend that at first leave it as default and if you get the runtime warnings, go back and do the configuration again, and compile the framework again.
Finish the configuration process and if you have a GPU — read this.
Compile the frameworkFinally, we get to the point where we can start building things.
Let’s build the framework libraries that we will link into the project later.
We need to build the C++ API and the framework.
Important: the next two commands will take several hours to finish.
It will maximize your CPU usage and drain your battery.
Make sure to be hooked up and take a long break.
At the root folder run:bazel build -c opt — verbose_failures //tensorflow:libtensorflow_cc.
soNext compile the framework:bazel build -c opt — verbose_failures //tensorflow:libtensorflow_framework.
soIf these two succeed with not errors (there are many warnings, that’s normal), you will find the two libraries in the folder (root folder)/bazel-bin/tensorflow/.
We will need these to link with our project.
If you remember, we configured first for CPU features and that should have made this build optimized for your personal case.
However, if you get the CPU features error such as in the troubleshooting section below, try and re-run the framework build again with the command-line bazel options that matches the flags you need.
In my case I should run:bazel build -c opt — copt=-mavx — copt=-mavx2 — copt=-mfma — copt=-msse4.
2 — verbose_failures //tensorflow:libtensorflow_framework.
soGet and build dependenciesWe need a few more things to download before we create our project.
Run this from the root folder:tensorflow/contrib/makefile/download_dependencies.
shIt will download files into tensorflow/contrib/makefile/downloads/Build protobufsRun the following:cd tensorflow/contrib/makefile/downloads/protobuf/.
/configuremakemake installCreate an XCode projectNow open XCode and create a C++ project.
I create mine in the Code folder under my home.
I called my project “TF2example”.
I will have a folder under home:~/Code/TF2example/TF2example/(the main.
cpp file will be located there).
Now create two subfolders under that directory: include and lib.
We want to copy headers to include and libraries to lib.
My folders are built like this:~/Code/ Tensorflow2/tensorflow/ tensorflow/ bazel-binTF2example/TF2example/ include/ lib/Let’s copy library files (you may need to sudo before the cp commands):cd ~/Codecp Tensorflow2/tensorflow/bazel-bin/tensorflow/libtensorflow_cc.
so TF2example/TF2example/lib/cp Tensorflow2/tensorflow/bazel-bin/tensorflow/libtensorflow_framework.
so TF2example/TF2example/lib/cp /usr/local/lib/libprotobuf.
a TF2example/TF2example/lib/Now copy the headers:cp -r Tensorflow2/tensorflow/bazel-genfiles/* TF2example/TF2example/includecp -r Tensorflow2/tensorflow/tensorflow/cc TF2example/TF2example/include/tensorflowcp -r Tensorflow2/tensorflow/tensorflow/core TF2example/TF2example/include/tensorflowcp -r Tensorflow2/tensorflow/third_party TF2example/TF2example/includecp -r /usr/local/include/google TF2example/TF2example/includecp -r Tensorflow2/tensorflow/tensorflow/contrib/makefile/downloads/absl/absl TF2example/TF2example/includecp -r Tensorflow2/tensorflow/bazel-tensorflow/external/eigen_archive/unsupported TF2example/TF2example/includecp -r Tensorflow2/tensorflow/bazel-tensorflow/external/eigen_archive/Eigen TF2example/TF2example/includeTest project codeFirst let’s copy the sample code that came with tensorflow 2.
cc TF2example/TF2example/Now go back to XCode and replace your main.
cpp with the example_trainer.
cc we just copied.
Test project configurationIn XCode select the project name on the project navigator on the left.
The main screen will show the project settings.
Make sure you select the project and not the target.
Select the Build settings tab and scroll to the “Search Paths”.
In “Header Search Paths” add $(PROJECT_DIR)/TF2example/include (change if you have a different name).
If you do not see that item, you are probably on “Basic” view.
Change to “All”.
In “Library Search Paths” add $(PROJECT_DIR)/TF2example/libUnder “Linking” search for “Runpath Search Paths” and add $(PROJECT_DIR)/TF2example/libGo to “Build Phases” tab (switch to Targets if needed depending on your view) and open the “Link Binary With Libraries” section.
Add the two .
so files we copied earlier (libtensorflow_cc.
so and libtensorflow_framework.
Note that you need to click the “Add Other…” button, and select the files under lib.
Now try to build the project and run it.
If everything worked out fine, you should see in the output window a bunch of x and y values which were written from multiple threads created by the sample program.
If you have compilation errors, link errors or runtime errors, try and look for help in the below troubleshooting section or comment on the article, so I can see if I can help.
TroubleshootingApple crosstoolIf you get an error about “Apple CROSSTOOL” that means you did not successfully accept the license agreement for the command-line tools.
At the root folder run this:bazel clean — expungesudo xcode-select -s /Applications/Xcode.
app/Contents/Developersudo xcodebuild -licensebazel clean –expungeand run the bazel build again.
CPU featuresWhen running your project, you get errors like “The TensorFlow library wasn’tcompiled to use SSE4.
2 instructions, but these are available on your machine andcould speed up CPU computations.
”This means you need to run configure again and set the proper flags that you see in the message.
I added “-mavx -mavx2 -mfma -msse4.
Documentation showing you can also add that to the bazel build command, but this did not do the trick for me, I had to do the configure again and re-build the framework .
Note also that in case you select the wrong flags, you may get a runtime error which will not indicate that it is related to the CPU features.
It is better to be safe than sorry.
Dynamic Lib loaderIf at runtime you get a “dyld library not loaded” error, check that you set the Runpath search path correctly and in case you did, you may need to use the install_name_tool command to make it work.