1# C++ API 2 3Note: By default [tensorflow.org](https://www.tensorflow.org) shows docs for the 4most recent stable version. The instructions in this doc require building from 5source. You will probably want to build from the `master` version of tensorflow. 6You should, as a result, be sure you are following the 7[`master` version of this doc](https://www.tensorflow.org/versions/master/api_guides/cc/guide), 8in case there have been any changes. 9 10[TOC] 11 12TensorFlow's C++ API provides mechanisms for constructing and executing a data 13flow graph. The API is designed to be simple and concise: graph operations are 14clearly expressed using a "functional" construction style, including easy 15specification of names, device placement, etc., and the resulting graph can be 16efficiently run and the desired outputs fetched in a few lines of code. This 17guide explains the basic concepts and data structures needed to get started with 18TensorFlow graph construction and execution in C++. 19 20## The Basics 21 22Let's start with a simple example that illustrates graph construction and 23execution using the C++ API. 24 25```c++ 26// tensorflow/cc/example/example.cc 27 28#include "tensorflow/cc/client/client_session.h" 29#include "tensorflow/cc/ops/standard_ops.h" 30#include "tensorflow/core/framework/tensor.h" 31 32int main() { 33 using namespace tensorflow; 34 using namespace tensorflow::ops; 35 Scope root = Scope::NewRootScope(); 36 // Matrix A = [3 2; -1 0] 37 auto A = Const(root, { {3.f, 2.f}, {-1.f, 0.f} }); 38 // Vector b = [3 5] 39 auto b = Const(root, { {3.f, 5.f} }); 40 // v = Ab^T 41 auto v = MatMul(root.WithOpName("v"), A, b, MatMul::TransposeB(true)); 42 std::vector<Tensor> outputs; 43 ClientSession session(root); 44 // Run and fetch v 45 TF_CHECK_OK(session.Run({v}, &outputs)); 46 // Expect outputs[0] == [19; -3] 47 LOG(INFO) << outputs[0].matrix<float>(); 48 return 0; 49} 50``` 51 52Place this example code in the file `tensorflow/cc/example/example.cc` inside a 53clone of the 54TensorFlow 55[github repository](http://www.github.com/tensorflow/tensorflow). Also place a 56`BUILD` file in the same directory with the following contents: 57 58```python 59load("//tensorflow:tensorflow.bzl", "tf_cc_binary") 60 61tf_cc_binary( 62 name = "example", 63 srcs = ["example.cc"], 64 deps = [ 65 "//tensorflow/cc:cc_ops", 66 "//tensorflow/cc:client_session", 67 "//tensorflow/core:tensorflow", 68 ], 69) 70``` 71 72Use `tf_cc_binary` rather than Bazel's native `cc_binary` to link in necessary 73symbols from `libtensorflow_framework.so`. You should be able to build and run 74the example using the following command (be sure to run `./configure` in your 75build sandbox first): 76 77```shell 78bazel run -c opt //tensorflow/cc/example:example 79``` 80 81This example shows some of the important features of the C++ API such as the 82following: 83 84* Constructing tensor constants from C++ nested initializer lists 85* Constructing and naming of TensorFlow operations 86* Specifying optional attributes to operation constructors 87* Executing and fetching the tensor values from the TensorFlow session. 88 89We will delve into the details of each below. 90 91## Graph Construction 92 93### Scope 94 95@{tensorflow::Scope} is the main data structure that holds the current state 96of graph construction. A `Scope` acts as a handle to the graph being 97constructed, as well as storing TensorFlow operation properties. The `Scope` 98object is the first argument to operation constructors, and operations that use 99a given `Scope` as their first argument inherit that `Scope`'s properties, such 100as a common name prefix. Multiple `Scope`s can refer to the same graph, as 101explained further below. 102 103Create a new `Scope` object by calling `Scope::NewRootScope`. This creates 104some resources such as a graph to which operations are added. It also creates a 105@{tensorflow::Status} object which will be used to indicate errors encountered 106when constructing operations. The `Scope` class has value semantics, thus, a 107`Scope` object can be freely copied and passed around. 108 109The `Scope` object returned by `Scope::NewRootScope` is referred 110to as the root scope. "Child" scopes can be constructed from the root scope by 111calling various member functions of the `Scope` class, thus forming a hierarchy 112of scopes. A child scope inherits all of the properties of the parent scope and 113typically has one property added or changed. For instance, `NewSubScope(name)` 114appends `name` to the prefix of names for operations created using the returned 115`Scope` object. 116 117Here are some of the properties controlled by a `Scope` object: 118 119* Operation names 120* Set of control dependencies for an operation 121* Device placement for an operation 122* Kernel attribute for an operation 123 124Please refer to @{tensorflow::Scope} for the complete list of member functions 125that let you create child scopes with new properties. 126 127### Operation Constructors 128 129You can create graph operations with operation constructors, one C++ class per 130TensorFlow operation. Unlike the Python API which uses snake-case to name the 131operation constructors, the C++ API uses camel-case to conform to C++ coding 132style. For instance, the `MatMul` operation has a C++ class with the same name. 133 134Using this class-per-operation method, it is possible, though not recommended, 135to construct an operation as follows: 136 137```c++ 138// Not recommended 139MatMul m(scope, a, b); 140``` 141 142Instead, we recommend the following "functional" style for constructing 143operations: 144 145```c++ 146// Recommended 147auto m = MatMul(scope, a, b); 148``` 149 150The first parameter for all operation constructors is always a `Scope` object. 151Tensor inputs and mandatory attributes form the rest of the arguments. 152 153For optional arguments, constructors have an optional parameter that allows 154optional attributes. For operations with optional arguments, the constructor's 155last optional parameter is a `struct` type called `[operation]:Attrs` that 156contains data members for each optional attribute. You can construct such 157`Attrs` in multiple ways: 158 159* You can specify a single optional attribute by constructing an `Attrs` object 160using the `static` functions provided in the C++ class for the operation. For 161example: 162 163```c++ 164auto m = MatMul(scope, a, b, MatMul::TransposeA(true)); 165``` 166 167* You can specify multiple optional attributes by chaining together functions 168 available in the `Attrs` struct. For example: 169 170```c++ 171auto m = MatMul(scope, a, b, MatMul::TransposeA(true).TransposeB(true)); 172 173// Or, alternatively 174auto m = MatMul(scope, a, b, MatMul::Attrs().TransposeA(true).TransposeB(true)); 175``` 176 177The arguments and return values of operations are handled in different ways 178depending on their type: 179 180* For operations that return single tensors, the object returned by 181 the operation object can be passed directly to other operation 182 constructors. For example: 183 184```c++ 185auto m = MatMul(scope, x, W); 186auto sum = Add(scope, m, bias); 187``` 188 189* For operations producing multiple outputs, the object returned by the 190 operation constructor has a member for each of the outputs. The names of those 191 members are identical to the names present in the `OpDef` for the 192 operation. For example: 193 194```c++ 195auto u = Unique(scope, a); 196// u.y has the unique values and u.idx has the unique indices 197auto m = Add(scope, u.y, b); 198``` 199 200* Operations producing a list-typed output return an object that can 201 be indexed using the `[]` operator. That object can also be directly passed to 202 other constructors that expect list-typed inputs. For example: 203 204```c++ 205auto s = Split(scope, 0, a, 2); 206// Access elements of the returned list. 207auto b = Add(scope, s[0], s[1]); 208// Pass the list as a whole to other constructors. 209auto c = Concat(scope, s, 0); 210``` 211 212### Constants 213 214You may pass many different types of C++ values directly to tensor 215constants. You may explicitly create a tensor constant by calling the 216@{tensorflow::ops::Const} function from various kinds of C++ values. For 217example: 218 219* Scalars 220 221```c++ 222auto f = Const(scope, 42.0f); 223auto s = Const(scope, "hello world!"); 224``` 225 226* Nested initializer lists 227 228```c++ 229// 2x2 matrix 230auto c1 = Const(scope, { {1, 2}, {2, 4} }); 231// 1x3x1 tensor 232auto c2 = Const(scope, { { {1}, {2}, {3} } }); 233// 1x2x0 tensor 234auto c3 = ops::Const(scope, { { {}, {} } }); 235``` 236 237* Shapes explicitly specified 238 239```c++ 240// 2x2 matrix with all elements = 10 241auto c1 = Const(scope, 10, /* shape */ {2, 2}); 242// 1x3x2x1 tensor 243auto c2 = Const(scope, {1, 2, 3, 4, 5, 6}, /* shape */ {1, 3, 2, 1}); 244``` 245 246You may directly pass constants to other operation constructors, either by 247explicitly constructing one using the `Const` function, or implicitly as any of 248the above types of C++ values. For example: 249 250```c++ 251// [1 1] * [41; 1] 252auto x = MatMul(scope, { {1, 1} }, { {41}, {1} }); 253// [1 2 3 4] + 10 254auto y = Add(scope, {1, 2, 3, 4}, 10); 255``` 256 257## Graph Execution 258 259When executing a graph, you will need a session. The C++ API provides a 260@{tensorflow::ClientSession} class that will execute ops created by the 261operation constructors. TensorFlow will automatically determine which parts of 262the graph need to be executed, and what values need feeding. For example: 263 264```c++ 265Scope root = Scope::NewRootScope(); 266auto c = Const(root, { {1, 1} }); 267auto m = MatMul(root, c, { {42}, {1} }); 268 269ClientSession session(root); 270std::vector<Tensor> outputs; 271session.Run({m}, &outputs); 272// outputs[0] == {42} 273``` 274 275Similarly, the object returned by the operation constructor can be used as the 276argument to specify a value being fed when executing the graph. Furthermore, the 277value to feed can be specified with the different kinds of C++ values used to 278specify tensor constants. For example: 279 280```c++ 281Scope root = Scope::NewRootScope(); 282auto a = Placeholder(root, DT_INT32); 283// [3 3; 3 3] 284auto b = Const(root, 3, {2, 2}); 285auto c = Add(root, a, b); 286ClientSession session(root); 287std::vector<Tensor> outputs; 288 289// Feed a <- [1 2; 3 4] 290session.Run({ {a, { {1, 2}, {3, 4} } } }, {c}, &outputs); 291// outputs[0] == [4 5; 6 7] 292``` 293 294Please see the @{tensorflow::Tensor} documentation for more information on how 295to use the execution output. 296