1 /* Copyright 2020 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 #ifndef TENSORFLOW_C_EAGER_C_API_UNIFIED_EXPERIMENTAL_H_ 16 #define TENSORFLOW_C_EAGER_C_API_UNIFIED_EXPERIMENTAL_H_ 17 18 #include "tensorflow/c/eager/c_api.h" 19 #include "tensorflow/c/tf_datatype.h" 20 #include "tensorflow/c/tf_status.h" 21 22 #ifdef __cplusplus 23 extern "C" { 24 #endif 25 26 // ============================================================================= 27 // Unified Execution APIs for Eager and tracing backends. 28 // ============================================================================= 29 30 // ----------------------------------------------------------------------------- 31 // Core APIs 32 // ----------------------------------------------------------------------------- 33 34 // A TF_ExecutionContext stores knowledge about how to execute an operation. 35 // E.g. it could know whether we're in eager mode or in graph mode, keeps track 36 // of gradient tapes, etc. 37 typedef struct TF_ExecutionContext TF_ExecutionContext; 38 39 // A TF_AbstractTensor is an input to an operation. E.g. it could be a union 40 // type of eager and graph tensors. It is also the result of executing an 41 // operation. 42 typedef struct TF_AbstractTensor TF_AbstractTensor; 43 44 // A TF_AbstractOp is the metadata we need to execute an operation. E.g. this 45 // could contain the op type and other attributes. 46 typedef struct TF_AbstractOp TF_AbstractOp; 47 48 // Stores a function representation that can be used for execution or for 49 // setting functional attributes of other composite ops e.g. control flow. 50 typedef struct TF_AbstractFunction TF_AbstractFunction; 51 52 // This allows the client to swap the implementation of the tracing engine. 53 // Any future call to TF_CreateFunction will use the implementation defined 54 // here. 55 void TF_SetTracingImplementation(const char* name, TF_Status*); 56 57 // Creates a new TensorFlow function. A Function is an execution context, and as 58 // such it can trace operations through TF_ExecuteOperation. After completing 59 // tracing, a function can be obtained by TF_FinalizeFunction. 60 TF_ExecutionContext* TF_CreateFunction(const char* fn_name, TF_Status* status); 61 62 // Creates a context for eager execution of operations. 63 TF_ExecutionContext* TF_NewEagerExecutionContext(TFE_ContextOptions*, 64 TF_Status* s); 65 void TF_DeleteExecutionContext(TF_ExecutionContext*); 66 67 // Represents a (partially-defined) shape. 68 typedef struct TF_Shape { 69 int num_dims; // Must be >= -1; -1 represents unknown rank. 70 int64_t* dim_sizes; 71 } TF_Shape; 72 73 // Add a new parameter to a TensorFlow Function. 74 TF_AbstractTensor* TF_AddFunctionParameter(TF_ExecutionContext* func, 75 TF_DataType dtype, TF_Shape shape, 76 TF_Status* s); 77 78 // Create an operation suitable to use with the provided context. The operation 79 // requires its type (e.g. "AddV2") to be set independently. 80 TF_AbstractOp* TF_NewAbstractOp(TF_ExecutionContext* ctx); 81 void TF_DeleteAbstractOp(TF_AbstractOp*); 82 83 // TODO(srbs): Add APIs for specifying attrs etc. 84 // `op_type` must outlive `op`. 85 void TF_AbstractOpSetOpType(TF_AbstractOp* op, const char* const op_type, 86 TF_Status* s); 87 // `op_name` must outlive `op`. 88 void TF_AbstractOpSetOpName(TF_AbstractOp* op, const char* const op_name, 89 TF_Status* s); 90 // `attr_name` must outlive `op`. 91 void TF_AbstractOpSetAttrType(TF_AbstractOp* op, const char* const attr_name, 92 TF_DataType value, TF_Status* s); 93 94 void TF_DeleteAbstractTensor(TF_AbstractTensor*); 95 96 // TF_OutputList holds the list of TF_AbstractTensor that results from executing 97 // an operation, or provided to create a function. 98 // When executing an operation in an eager context, the expected number of 99 // outputs must be set beforehand with `TF_OutputListSetNumOutputs`. 100 typedef struct TF_OutputList TF_OutputList; 101 TF_OutputList* TF_NewOutputList(); 102 void TF_DeleteOutputList(TF_OutputList* o); 103 // Prepare tracing to the expected number of output for an operation. 104 void TF_OutputListSetNumOutputs(TF_OutputList* o, int num_outputs, TF_Status*); 105 // Return the number of outputs in the list. 106 int TF_OutputListNumOutputs(TF_OutputList* o); 107 // Return the `i`th output in the list. 108 TF_AbstractTensor* TF_OutputListGet(TF_OutputList* o, int i); 109 // Append a tensor at the end of the output list, growing its size by one. 110 void TF_OutputListPushBack(TF_OutputList* o, TF_AbstractTensor* tensor, 111 TF_Status*); 112 113 // TF_ExecuteOperation will, if in eager mode, execute, if in graph mode, maybe 114 // capture some inputs and then add a node in the graph. The output tensors are 115 // returned through the provided TF_OutputList. 116 // Any active tape will observe the effects of this execution. 117 void TF_ExecuteOperation(TF_AbstractOp* op, int num_inputs, 118 TF_AbstractTensor* const* inputs, TF_OutputList* o, 119 TF_Status* s); 120 121 // Creates a new TF_AbstractFunction from the current tracing states in the 122 // context. The provided `ctx` is consumed by this API call and deleted. 123 // The returned TF_AbstractFunction must be deleted by the client, 124 // TODO(aminim): clarify the contract on the state of the context after this 125 // call. 126 TF_AbstractFunction* TF_FinalizeFunction(TF_ExecutionContext* ctx, 127 TF_OutputList*, TF_Status*); 128 129 void TF_DeleteAbstractFunction(TF_AbstractFunction*); 130 131 // Register the function with the given context. This is particularly useful for 132 // making a function available to an eager context. 133 void TF_ExecutionContextRegisterFunction(TF_ExecutionContext*, 134 TF_AbstractFunction*, TF_Status*); 135 136 // ----------------------------------------------------------------------------- 137 // APIs specific to Eager modes 138 // ----------------------------------------------------------------------------- 139 140 // Temporary APIs till we figure out how to create scalar valued Eager 141 // tensors and how to get value out of eager abstract tensors. 142 TF_AbstractTensor* TF_CreateAbstractTensorFromEagerTensor(TFE_TensorHandle* t, 143 TF_Status* s); 144 TFE_TensorHandle* TF_AbstractTensorGetEagerTensor(TF_AbstractTensor* at, 145 TF_Status* s); 146 TFE_Context* TF_ExecutionContextGetTFEContext(TF_ExecutionContext*, 147 TF_Status* s); 148 149 #ifdef __cplusplus 150 } /* end extern "C" */ 151 #endif 152 153 #endif // TENSORFLOW_C_EAGER_C_API_UNIFIED_EXPERIMENTAL_H_ 154