1 /* Copyright 2015 The TensorFlow Authors. All Rights Reserved.
2 
3 Licensed under the Apache License, Version 2.0 (the "License");
4 you may not use this file except in compliance with the License.
5 You may obtain a copy of the License at
6 
7     http://www.apache.org/licenses/LICENSE-2.0
8 
9 Unless required by applicable law or agreed to in writing, software
10 distributed under the License is distributed on an "AS IS" BASIS,
11 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 See the License for the specific language governing permissions and
13 limitations under the License.
14 ==============================================================================*/
15 
16 #ifndef TENSORFLOW_PYTHON_CLIENT_TF_SESSION_HELPER_H_
17 #define TENSORFLOW_PYTHON_CLIENT_TF_SESSION_HELPER_H_
18 
19 // Must be included first
20 #include "tensorflow/python/lib/core/numpy.h"
21 
22 #include "tensorflow/c/c_api.h"
23 #include "tensorflow/core/framework/graph.pb.h"
24 #include "tensorflow/core/lib/core/errors.h"
25 #include "tensorflow/core/lib/core/status.h"
26 #include "tensorflow/core/lib/gtl/inlined_vector.h"
27 
28 namespace tensorflow {
29 
30 // Container types for the various arguments and temporary values used
31 // in the wrapper.
32 
33 // A NameVector is a vector of tensor or operation names, as borrowed
34 // C strings.
35 typedef tensorflow::gtl::InlinedVector<const char*, 8> NameVector;
36 
37 // A PyObjectVector is a vector of borrowed pointers to PyObjects.
38 typedef tensorflow::gtl::InlinedVector<PyObject*, 8> PyObjectVector;
39 
40 // A TF_TensorVector is a vector of borrowed pointers to TF_Tensors.
41 typedef gtl::InlinedVector<TF_Tensor*, 8> TF_TensorVector;
42 
43 TF_Session* TF_NewSessionRef(TF_Graph* graph, const TF_SessionOptions* opts,
44                              TF_Status* status);
45 
46 // Run the graph associated with the session starting with the
47 // supplied inputs[].  Regardless of success or failure, inputs[] are
48 // stolen by the implementation (i.e. the implementation will
49 // eventually call Py_DECREF on each array input).
50 //
51 // The PyObject* feed_dict must be a dictionary mapping strings to
52 // NumPy arrays. This function does not modify its reference count.
53 //
54 // On success, the tensors corresponding to output_names[0,noutputs-1]
55 // are placed in out_values[], and these outputs[] become the property
56 // of the caller (the caller must eventually call Py_DECREF on them).
57 //
58 // On failure, out_status contains a tensorflow::Status with an error
59 // message.
60 void TF_Run_wrapper(TF_DeprecatedSession* session, const TF_Buffer* run_options,
61                     PyObject* feed_dict, const NameVector& output_names,
62                     const NameVector& target_nodes, TF_Status* out_status,
63                     PyObjectVector* out_values, TF_Buffer* run_outputs);
64 
65 // Python wrappers for the `Session::MakeCallable()` API.
66 void TF_DeprecatedSessionMakeCallable(TF_DeprecatedSession* session,
67                                       const TF_Buffer* callable_options,
68                                       int64_t* out_handle,
69                                       TF_Status* out_status);
70 void TF_SessionMakeCallable(TF_Session* session,
71                             const TF_Buffer* callable_options,
72                             int64_t* out_handle, TF_Status* out_status);
73 
74 // Python wrappers for the `Session::RunCallable()` API.
75 void TF_DeprecatedSessionRunCallable(TF_DeprecatedSession* session,
76                                      int64_t handle, PyObject* feed_values,
77                                      TF_Status* out_status,
78                                      PyObjectVector* out_values,
79                                      TF_Buffer* run_metadata);
80 void TF_SessionRunCallable(TF_Session* session, int64_t handle,
81                            PyObject* feed_values, TF_Status* out_status,
82                            PyObjectVector* out_values, TF_Buffer* run_metadata);
83 
84 // Python wrappers for the `Session::ReleaseCallable()` API.
85 void TF_DeprecatedSessionReleaseCallable(TF_DeprecatedSession* session,
86                                          int64_t handle, TF_Status* out_status);
87 void TF_SessionReleaseCallable(TF_Session* session, int64_t handle,
88                                TF_Status* out_status);
89 
90 // Set up the graph with the intended feeds and fetches for partial run.
91 // *out_handle is owned by the caller.
92 //
93 // On success, returns a handle that is used for subsequent PRun calls.
94 //
95 // On failure, out_status contains a tensorflow::Status with an error
96 // message.
97 void TF_PRunSetup_wrapper(TF_DeprecatedSession* session,
98                           const NameVector& input_names,
99                           const NameVector& output_names,
100                           const NameVector& target_nodes, TF_Status* out_status,
101                           const char** out_handle);
102 
103 // Continue to run the graph with additional feeds and fetches. The
104 // execution state is uniquely identified by the handle.
105 //
106 // The PyObject* feed_dict must be a dictionary mapping strings to
107 // NumPy arrays. This function does not modify its reference count.
108 //
109 // On success,  the tensors corresponding to output_names[0,noutputs-1]
110 // are placed in out_values[], and these outputs[] become the property
111 // of the caller (the caller must eventually call Py_DECREF on them).
112 //
113 // On failure,  out_status contains a tensorflow::Status with an error
114 // message.
115 void TF_PRun_wrapper(TF_DeprecatedSession* session, const char* handle,
116                      PyObject* feed_dict, const NameVector& output_names,
117                      TF_Status* out_status, PyObjectVector* out_values);
118 
119 // Wrapper for TF_Reset that converts the string vectors to character arrays.
120 void TF_Reset_wrapper(const TF_SessionOptions* opt,
121                       const NameVector& containers, TF_Status* out_status);
122 
123 // Convenience wrapper around EqualGraphDef to make it easier to wrap.
124 // Returns an explanation if a difference is found, or the empty string
125 // for no difference.
126 string EqualGraphDefWrapper(const string& actual, const string& expected);
127 
128 // Convenience wrapper around AreAttrValuesEqual to make it easier to wrap.
129 // The actual and expected strings must correspond to a serialized binary
130 // representation of two AttrValue proto instances.
131 // Returns an explanation if a difference is found, or the empty string
132 // for no difference.
133 string EqualAttrValueWrapper(const string& actual, const string& expected);
134 
135 // Gets shape from C API Graph object.
136 //
137 // If shape is known, returns shape vector where -1 means "unknown
138 // dimension".  Sets unknown_shape to false.
139 //
140 // If shape is unknown, sets unknown_shape to true.
141 tensorflow::gtl::InlinedVector<int64_t, 6> TF_GraphGetTensorShapeHelper(
142     TF_Graph* graph, TF_Output output, TF_Status* status, bool* unknown_shape);
143 
144 // Runs the graph associated with the session starting with the supplied inputs.
145 // On success, `py_outputs` is populated with a numpy ndarray for each output
146 // (the caller must decref these ndarrays, although this will likely be handled
147 // by the Python gc). `session`, `out_status`, and `py_outputs` must be
148 // non-null. `py_outputs` should be empty.
149 void TF_SessionRun_wrapper(TF_Session* session, const TF_Buffer* run_options,
150                            const std::vector<TF_Output>& inputs,
151                            const std::vector<PyObject*>& input_ndarrays,
152                            const std::vector<TF_Output>& outputs,
153                            const std::vector<TF_Operation*>& targets,
154                            TF_Buffer* run_metadata, TF_Status* status,
155                            std::vector<PyObject*>* py_outputs);
156 
157 // Set up the graph with the intended feeds (inputs) and fetches (output) for
158 // a sequence of partial run calls.
159 //
160 // On success, returns a handle that can be used for subsequent PRun calls. The
161 // handle is owned by the caller and should be deleted with TF_DeletePRunHandle
162 // when it is no longer needed.
163 //
164 // On failure, out_status contains a tensorflow::Status with an error
165 // message.
166 void TF_SessionPRunSetup_wrapper(TF_Session* session,
167                                  const std::vector<TF_Output>& inputs,
168                                  const std::vector<TF_Output>& outputs,
169                                  const std::vector<TF_Operation*>& targets,
170                                  const char** out_handle, TF_Status* status);
171 
172 // Continue to run the graph with additional feeds and fetches. The
173 // execution state is uniquely identified by the handle.
174 //
175 // On success, `py_outputs` is populated with a numpy ndarray for each output
176 // (the caller must decref these ndarrays, although this will likely be handled
177 // by the Python gc). `session`, `handle`, `out_status`, and `py_outputs` must
178 // be non-null. `py_outputs` should be empty.
179 //
180 // On failure, out_status contains a tensorflow::Status with an error
181 // message.
182 void TF_SessionPRun_wrapper(TF_Session* session, const char* handle,
183                             const std::vector<TF_Output>& inputs,
184                             const std::vector<PyObject*>& input_ndarrays,
185                             const std::vector<TF_Output>& outputs,
186                             TF_Status* status,
187                             std::vector<PyObject*>* py_outputs);
188 
189 // Retrieves the inputs of this operation.
190 std::vector<TF_Output> GetOperationInputs(TF_Operation* oper);
191 
192 // Retrieves the control inputs of this operation.
193 std::vector<TF_Operation*> TF_OperationGetControlInputs_wrapper(
194     TF_Operation* oper);
195 
196 // Retrieves the control outputs of this operation.
197 std::vector<TF_Operation*> TF_OperationGetControlOutputs_wrapper(
198     TF_Operation* oper);
199 
200 // Retrieves the op names of the consumers of `oper_out`. The returned strings
201 // have the lifetime of the underlying TF_Graph.
202 std::vector<const char*> TF_OperationOutputConsumers_wrapper(
203     TF_Output oper_out);
204 
205 // `opers` equaling NULL are converted to `nopers = -1`.
206 // `output_names` must be empty or have the same length as `outputs`.
207 TF_Function* TF_GraphToFunction_wrapper(
208     const TF_Graph* fn_body, const char* fn_name, bool append_hash_to_fn_name,
209     const std::vector<TF_Operation*>* opers,
210     const std::vector<TF_Output>& inputs, const std::vector<TF_Output>& outputs,
211     const NameVector& output_names,
212     const std::vector<TF_Operation*>* control_outputs,
213     const NameVector& control_output_names, const TF_FunctionOptions* opts,
214     const char* description, TF_Status* status);
215 
216 // Set the shapes and types for the output's handle.
217 //
218 // The sizes of 'shapes', 'ranks', and 'types' must be equal; `shapes[i]`
219 // contains the shape of the handle's i-th value, `ranks[i]` contains the i-th
220 // shape's rank, and `types[i]` contains the i-th value's dtype. If the i-th
221 // shape is unknown, then `ranks[i]` must be equal to -1.
222 //
223 // The space between the double angle brackets below looks extraneous, but
224 // our version of SWIG cannot parse ">>".
225 void TF_GraphSetOutputHandleShapesAndTypes_wrapper(
226     TF_Graph* graph, TF_Output output,
227     const std::vector<std::vector<int64_t> >& shapes,
228     const std::vector<int>& ranks, const std::vector<TF_DataType>& types,
229     TF_Status* status);
230 
231 // Set the shape of output. If unknown is true, `num_dims` must be set to
232 // -1 and `dims` is set to nullptr.
233 void TF_GraphSetTensorShape_wrapper(TF_Graph* graph, TF_Output output,
234                                     const std::vector<int64_t>& dims,
235                                     bool unknown_shape, TF_Status* status);
236 
237 // Returns the string representations of the missing unused input mappings.
238 std::vector<string> TF_ImportGraphDefResultsMissingUnusedInputMappings_wrapper(
239     TF_ImportGraphDefResults* results);
240 
241 // If evaluation was possible, returns the numpy ndarray of the evaluated
242 // result. Otherwise returns None.
243 PyObject* TF_TryEvaluateConstant_wrapper(TF_Graph* graph, TF_Output output,
244                                          TF_Status* status);
245 
246 }  // namespace tensorflow
247 
248 #endif  // TENSORFLOW_PYTHON_CLIENT_TF_SESSION_HELPER_H_
249