Home | History | Annotate | Download | only in cc
      1 # C++ API
      2 
      3 Note: By default [tensorflow.org](https://www.tensorflow.org) shows docs for the
      4 most recent stable version. The instructions in this doc require building from
      5 source. You will probably want to build from the `master` version of tensorflow.
      6 You 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),
      8 in case there have been any changes.
      9 
     10 [TOC]
     11 
     12 TensorFlow's C++ API provides mechanisms for constructing and executing a data
     13 flow graph. The API is designed to be simple and concise: graph operations are
     14 clearly expressed using a "functional" construction style, including easy
     15 specification of names, device placement, etc., and the resulting graph can be
     16 efficiently run and the desired outputs fetched in a few lines of code. This
     17 guide explains the basic concepts and data structures needed to get started with
     18 TensorFlow graph construction and execution in C++.
     19 
     20 ## The Basics
     21 
     22 Let's start with a simple example that illustrates graph construction and
     23 execution 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 
     32 int 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 
     52 Place this example code in the file `tensorflow/cc/example/example.cc` inside a
     53 clone of the
     54 TensorFlow
     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
     59 load("//tensorflow:tensorflow.bzl", "tf_cc_binary")
     60 
     61 tf_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 
     72 Use `tf_cc_binary` rather than Bazel's native `cc_binary` to link in necessary
     73 symbols from `libtensorflow_framework.so`. You should be able to build and run
     74 the example using the following command (be sure to run `./configure` in your
     75 build sandbox first):
     76 
     77 ```shell
     78 bazel run -c opt //tensorflow/cc/example:example
     79 ```
     80 
     81 This example shows some of the important features of the C++ API such as the
     82 following:
     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 
     89 We 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
     96 of graph construction. A `Scope` acts as a handle to the graph being
     97 constructed, as well as storing TensorFlow operation properties. The `Scope`
     98 object is the first argument to operation constructors, and operations that use
     99 a given `Scope` as their first argument inherit that `Scope`'s properties, such
    100 as a common name prefix. Multiple `Scope`s can refer to the same graph, as
    101 explained further below.
    102 
    103 Create a new `Scope` object by calling `Scope::NewRootScope`. This creates
    104 some 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
    106 when constructing operations. The `Scope` class has value semantics, thus, a
    107 `Scope` object can be freely copied and passed around.
    108 
    109 The `Scope` object returned by `Scope::NewRootScope` is referred
    110 to as the root scope. "Child" scopes can be constructed from the root scope by
    111 calling various member functions of the `Scope` class, thus forming a hierarchy
    112 of scopes. A child scope inherits all of the properties of the parent scope and
    113 typically has one property added or changed. For instance, `NewSubScope(name)`
    114 appends `name` to the prefix of names for operations created using the returned
    115 `Scope` object.
    116 
    117 Here 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 
    124 Please refer to @{tensorflow::Scope} for the complete list of member functions
    125 that let you create child scopes with new properties.
    126 
    127 ### Operation Constructors
    128 
    129 You can create graph operations with operation constructors, one C++ class per
    130 TensorFlow operation. Unlike the Python API which uses snake-case to name the
    131 operation constructors, the C++ API uses camel-case to conform to C++ coding
    132 style. For instance, the `MatMul` operation has a C++ class with the same name.
    133 
    134 Using this class-per-operation method, it is possible, though not recommended,
    135 to construct an operation as follows:
    136 
    137 ```c++
    138 // Not recommended
    139 MatMul m(scope, a, b);
    140 ```
    141 
    142 Instead, we recommend the following "functional" style for constructing
    143 operations:
    144 
    145 ```c++
    146 // Recommended
    147 auto m = MatMul(scope, a, b);
    148 ```
    149 
    150 The first parameter for all operation constructors is always a `Scope` object.
    151 Tensor inputs and mandatory attributes form the rest of the arguments.
    152 
    153 For optional arguments, constructors have an optional parameter that allows
    154 optional attributes.  For operations with optional arguments, the constructor's
    155 last optional parameter is a `struct` type called `[operation]:Attrs` that
    156 contains 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
    160 using the `static` functions provided in the C++ class for the operation. For
    161 example:
    162 
    163 ```c++
    164 auto 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++
    171 auto m = MatMul(scope, a, b, MatMul::TransposeA(true).TransposeB(true));
    172 
    173 // Or, alternatively
    174 auto m = MatMul(scope, a, b, MatMul::Attrs().TransposeA(true).TransposeB(true));
    175 ```
    176 
    177 The arguments and return values of operations are handled in different ways
    178 depending 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++
    185 auto m = MatMul(scope, x, W);
    186 auto 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++
    195 auto u = Unique(scope, a);
    196 // u.y has the unique values and u.idx has the unique indices
    197 auto 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++
    205 auto s = Split(scope, 0, a, 2);
    206 // Access elements of the returned list.
    207 auto b = Add(scope, s[0], s[1]);
    208 // Pass the list as a whole to other constructors.
    209 auto c = Concat(scope, s, 0);
    210 ```
    211 
    212 ### Constants
    213 
    214 You may pass many different types of C++ values directly to tensor
    215 constants. You may explicitly create a tensor constant by calling the
    216 @{tensorflow::ops::Const} function from various kinds of C++ values. For
    217 example:
    218 
    219 * Scalars
    220 
    221 ```c++
    222 auto f = Const(scope, 42.0f);
    223 auto s = Const(scope, "hello world!");
    224 ```
    225 
    226 * Nested initializer lists
    227 
    228 ```c++
    229 // 2x2 matrix
    230 auto c1 = Const(scope, { {1, 2}, {2, 4} });
    231 // 1x3x1 tensor
    232 auto c2 = Const(scope, { { {1}, {2}, {3} } });
    233 // 1x2x0 tensor
    234 auto c3 = ops::Const(scope, { { {}, {} } });
    235 ```
    236 
    237 * Shapes explicitly specified
    238 
    239 ```c++
    240 // 2x2 matrix with all elements = 10
    241 auto c1 = Const(scope, 10, /* shape */ {2, 2});
    242 // 1x3x2x1 tensor
    243 auto c2 = Const(scope, {1, 2, 3, 4, 5, 6}, /* shape */ {1, 3, 2, 1});
    244 ```
    245 
    246 You may directly pass constants to other operation constructors, either by
    247 explicitly constructing one using the `Const` function, or implicitly as any of
    248 the above types of C++ values. For example:
    249 
    250 ```c++
    251 // [1 1] * [41; 1]
    252 auto x = MatMul(scope, { {1, 1} }, { {41}, {1} });
    253 // [1 2 3 4] + 10
    254 auto y = Add(scope, {1, 2, 3, 4}, 10);
    255 ```
    256 
    257 ## Graph Execution
    258 
    259 When executing a graph, you will need a session. The C++ API provides a
    260 @{tensorflow::ClientSession} class that will execute ops created by the
    261 operation constructors. TensorFlow will automatically determine which parts of
    262 the graph need to be executed, and what values need feeding. For example:
    263 
    264 ```c++
    265 Scope root = Scope::NewRootScope();
    266 auto c = Const(root, { {1, 1} });
    267 auto m = MatMul(root, c, { {42}, {1} });
    268 
    269 ClientSession session(root);
    270 std::vector<Tensor> outputs;
    271 session.Run({m}, &outputs);
    272 // outputs[0] == {42}
    273 ```
    274 
    275 Similarly, the object returned by the operation constructor can be used as the
    276 argument to specify a value being fed when executing the graph. Furthermore, the
    277 value to feed can be specified with the different kinds of C++ values used to
    278 specify tensor constants. For example:
    279 
    280 ```c++
    281 Scope root = Scope::NewRootScope();
    282 auto a = Placeholder(root, DT_INT32);
    283 // [3 3; 3 3]
    284 auto b = Const(root, 3, {2, 2});
    285 auto c = Add(root, a, b);
    286 ClientSession session(root);
    287 std::vector<Tensor> outputs;
    288 
    289 // Feed a <- [1 2; 3 4]
    290 session.Run({ {a, { {1, 2}, {3, 4} } } }, {c}, &outputs);
    291 // outputs[0] == [4 5; 6 7]
    292 ```
    293 
    294 Please see the @{tensorflow::Tensor} documentation for more information on how
    295 to use the execution output.
    296