• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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