• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright 2018 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_LITE_CORE_SUBGRAPH_H_
16 #define TENSORFLOW_LITE_CORE_SUBGRAPH_H_
17 
18 #include <stdarg.h>
19 #include <stddef.h>
20 
21 #include <cstdint>
22 #include <cstdlib>
23 #include <map>
24 #include <memory>
25 #include <set>
26 #include <string>
27 #include <utility>
28 #include <vector>
29 
30 #include "tensorflow/lite/allocation.h"
31 #include "tensorflow/lite/c/common.h"
32 #include "tensorflow/lite/core/api/error_reporter.h"
33 #include "tensorflow/lite/core/api/profiler.h"
34 #include "tensorflow/lite/core/macros.h"
35 #include "tensorflow/lite/experimental/resource/initialization_status.h"
36 #include "tensorflow/lite/experimental/resource/resource_base.h"
37 #include "tensorflow/lite/graph_info.h"
38 #include "tensorflow/lite/interpreter_options.h"
39 #include "tensorflow/lite/memory_planner.h"
40 #include "tensorflow/lite/util.h"
41 
42 namespace tflite {
43 
44 class SingleOpModel;  // Class for friend declarations.
45 
46 namespace delegates {
47 namespace test_utils {
48 class TestDelegate;  // Class for friend declarations.
49 }  // namespace test_utils
50 }  // namespace delegates
51 
52 class Subgraph {
53  public:
54   friend class Interpreter;
55   friend class SingleOpModel;
56 
57   Subgraph(ErrorReporter* error_reporter,
58            TfLiteExternalContext** external_contexts,
59            std::vector<std::unique_ptr<Subgraph>>* subgraphs,
60            resource::ResourceMap* resources,
61            resource::ResourceIDMap* resource_ids,
62            resource::InitializationStatusMap* initialization_status_map,
63            int subgraph_index = kInvalidSubgraphIndex);
64 
65   Subgraph(const Subgraph&) = delete;
66 
67   // Subgraphs should be movable but not copyable.
68   Subgraph(Subgraph&&) = default;
69   Subgraph& operator=(const Subgraph&) = delete;
70   virtual ~Subgraph();
71 
72   // Provide a list of tensor indexes that are inputs to the model.
73   // Each index is bound check and this modifies the consistent_ flag of the
74   // interpreter.
75   TfLiteStatus SetInputs(std::vector<int> inputs);
76 
77   // Provide a list of tensor indexes that are outputs to the model
78   // Each index is bound check and this modifies the consistent_ flag of the
79   // interpreter.
80   TfLiteStatus SetOutputs(std::vector<int> outputs);
81 
82   // Provide a list of tensor indexes that are variable tensors.
83   // Each index is bound check and this modifies the consistent_ flag of the
84   // interpreter.
85   TfLiteStatus SetVariables(std::vector<int> variables);
86 
87   // Adds a node with the given parameters and returns the index of the new
88   // node in `node_index` (optionally). Interpreter will take ownership of
89   // `builtin_data` and destroy it with `free`. Ownership of 'init_data'
90   // remains with the caller.
91   TfLiteStatus AddNodeWithParameters(const std::vector<int>& inputs,
92                                      const std::vector<int>& outputs,
93                                      const std::vector<int>& intermediates,
94                                      const char* init_data,
95                                      size_t init_data_size, void* builtin_data,
96                                      const TfLiteRegistration* registration,
97                                      int* node_index = nullptr);
98 
99   // Adds `tensors_to_add` tensors, preserving pre-existing Tensor entries.
100   // The value pointed to by `first_new_tensor_index` will be set to the
101   // index of the first new tensor if `first_new_tensor_index` is non-null.
102   TfLiteStatus AddTensors(int tensors_to_add,
103                           int* first_new_tensor_index = nullptr);
104 
105   // Set description of inputs/outputs/data/fptrs for node `node_index`.
106   // This variant assumes an external buffer has been allocated of size
107   // bytes. The lifetime of buffer must be ensured to be greater or equal
108   // to Interpreter. `quantization` ownership is passed to the subgraph.
109   inline TfLiteStatus SetTensorParametersReadOnly(
110       int tensor_index, TfLiteType type, const char* name,
111       const std::vector<int>& dims, TfLiteQuantization quantization,
112       const char* buffer, size_t bytes, const Allocation* allocation = nullptr,
113       TfLiteSparsity* sparsity = nullptr) {
114     return SetTensorParametersReadOnly(tensor_index, type, name, dims.size(),
115                                        dims.data(), quantization, buffer, bytes,
116                                        allocation, sparsity);
117   }
118   TfLiteStatus SetTensorParametersReadOnly(
119       int tensor_index, TfLiteType type, const char* name, const size_t ndims,
120       const int* dims, TfLiteQuantization quantization, const char* buffer,
121       size_t bytes, const Allocation* allocation = nullptr,
122       TfLiteSparsity* sparsity = nullptr);
123 
124   // Set description of inputs/outputs/data/fptrs for node `node_index`.
125   // This variant assumes an external buffer has been allocated of size
126   // bytes. The lifetime of buffer must be ensured to be greater or equal
127   // to Interpreter. `quantization` ownership is passed to the subgraph.
128   inline TfLiteStatus SetTensorParametersReadWrite(
129       int tensor_index, TfLiteType type, const char* name,
130       const std::vector<int>& dims, TfLiteQuantization quantization,
131       bool is_variable = false, const std::vector<int>& dims_signature = {}) {
132     if (dims_signature.empty()) {
133       return SetTensorParametersReadWrite(tensor_index, type, name, dims.size(),
134                                           dims.data(), quantization,
135                                           is_variable);
136     }
137     return SetTensorParametersReadWrite(
138         tensor_index, type, name, dims.size(), dims.data(), quantization,
139         is_variable, dims_signature.size(), dims_signature.data());
140   }
141   TfLiteStatus SetTensorParametersReadWrite(
142       int tensor_index, TfLiteType type, const char* name, const size_t ndims,
143       const int* dims, TfLiteQuantization quantization,
144       bool is_variable = false, const size_t ndims_signature = 0,
145       const int* dims_signature = nullptr);
146 
147   // Get a mutable tensor data structure.
tensor(int tensor_index)148   TfLiteTensor* tensor(int tensor_index) {
149     if (tensor_index < 0 ||
150         static_cast<size_t>(tensor_index) >= context_.tensors_size) {
151       return nullptr;
152     }
153     return &context_.tensors[tensor_index];
154   }
155 
156   // Get an immutable tensor data structure.
tensor(int tensor_index)157   const TfLiteTensor* tensor(int tensor_index) const {
158     if (tensor_index < 0 ||
159         static_cast<size_t>(tensor_index) >= context_.tensors_size) {
160       return nullptr;
161     }
162     return &context_.tensors[tensor_index];
163   }
164 
165   // Read only access to list of inputs.
inputs()166   std::vector<int>& inputs() { return inputs_; }
167 
168   // Read only access to list of inputs.
inputs()169   const std::vector<int>& inputs() const { return inputs_; }
170 
171   // Read only access to list of outputs.
outputs()172   std::vector<int>& outputs() { return outputs_; }
173 
174   // Read only access to list of outputs.
outputs()175   const std::vector<int>& outputs() const { return outputs_; }
176 
177   // Read only access to list of variable tensors.
variables()178   std::vector<int>& variables() { return variables_; }
179 
180   // Read only access to list of variable tensors.
variables()181   const std::vector<int>& variables() const { return variables_; }
182 
183   // WARNING: Experimental interface, subject to change.
184   // TODO(ycling): Move this function to an external context interface.
resources()185   resource::ResourceMap& resources() { return *resources_; }
186 
187   // WARNING: Experimental interface, subject to change.
188   // TODO(b/149099381): Move this function to an external context interface.
resource_ids()189   resource::ResourceIDMap& resource_ids() { return *resource_ids_; }
190 
191   // WARNING: Experimental interface, subject to change.
192   // TODO(b/149099381): Move this function to an external context interface.
initialization_status_map()193   resource::InitializationStatusMap& initialization_status_map() {
194     return *initialization_status_map_;
195   }
196 
tensors_size()197   size_t tensors_size() const { return tensors_.size(); }
198 
199   // Return the number of ops in the model.
nodes_size()200   size_t nodes_size() const { return nodes_and_registration_.size(); }
201 
202   // Return vector of node indices in the order of execution.
execution_plan()203   std::vector<int>& execution_plan() { return execution_plan_; }
204 
205   // Return read-only vector of node indices in the order of execution.
execution_plan()206   const std::vector<int>& execution_plan() const { return execution_plan_; }
207 
208   const std::vector<std::pair<TfLiteNode, TfLiteRegistration>>&
nodes_and_registration()209   nodes_and_registration() const {
210     return nodes_and_registration_;
211   }
212 
213   // Get a pointer to an operation and registration data structure if in bounds.
node_and_registration(int node_index)214   const std::pair<TfLiteNode, TfLiteRegistration>* node_and_registration(
215       int node_index) const {
216     if (node_index < 0 || static_cast<size_t>(node_index) >= nodes_size())
217       return nullptr;
218     return &nodes_and_registration_[node_index];
219   }
220 
221   // Change the dimensionality of a given tensor. Note, this is only acceptable
222   // for tensor indices that are inputs.
223   // Returns status of failure or success.
224   TfLiteStatus ResizeInputTensor(int tensor_index,
225                                  const std::vector<int>& dims);
226 
227   // WARNING: Experimental interface, subject to change
228   // Change the dimensionality of a given tensor. This is only acceptable for
229   // tensor indices that are inputs or variables. Only unknown dimensions can be
230   // resized with this function. Unknown dimensions are indicated as `-1` in the
231   // `dims_signature` attribute of a `TfLiteTensor`. Returns status of failure
232   // or success.
233   TfLiteStatus ResizeInputTensorStrict(int tensor_index,
234                                        const std::vector<int>& dims);
235 
236   // This releases memory held by non-persistent tensors. It does NOT re-perform
237   // memory planning.
238   // AllocateTensors needs to be called before next invocation.
239   TfLiteStatus ReleaseNonPersistentMemory();
240 
241   // WARNING: Experimental interface, subject to change
242   // This API releases memory held by the given subgraph. This method is
243   // designed to release memory of control flow subgraphs.
244   // AllocateTensors needs to be called before next invocation.
245   TfLiteStatus ReleaseMemory();
246 
247   // Update allocations for all tensors. This will redim dependent tensors using
248   // the input tensor dimensionality as given. This is relatively expensive.
249   // If you know that your sizes are not changing, you need not call this.
250   // Returns status of success or failure.
251   TfLiteStatus AllocateTensors();
252 
253   // Invoke the subgraph (run the whole graph in dependency order).
254   //
255   // NOTE: It is possible that the interpreter is not in a ready state
256   // to evaluate (i.e. if a ResizeTensor() has been performed without an
257   // AllocateTensors().
258   // Returns status of success or failure.
259   TfLiteStatus Invoke();
260 
261   // Entry point for C node plugin API to report an error.
262   void ReportError(const char* format, ...);
263 
264   // Return the subgraph specific context.
context()265   TfLiteContext* context() { return &context_; }
context()266   const TfLiteContext* context() const { return &context_; }
267 
268   // Set the value of an external context.
269   void SetExternalContext(TfLiteExternalContextType type,
270                           TfLiteExternalContext* ctx);
271   // Get the half precision flag.
272   // WARNING: This is an experimental API and subject to change.
GetAllowFp16PrecisionForFp32()273   bool GetAllowFp16PrecisionForFp32() const {
274     return context_.allow_fp32_relax_to_fp16;
275   }
276 
277   // Sets the cancellation function pointer in order to cancel a request in the
278   // middle of a call to Invoke(). The interpreter queries this function during
279   // inference, between op invocations; when it returns true, the interpreter
280   // will abort execution and return `kTfLiteError`. The `data` parameter
281   // contains any data used by the cancellation function, and if non-null,
282   // remains owned by the caller.
283   // WARNING: This is an experimental API and subject to change.
284   void SetCancellationFunction(void* data, bool (*check_cancelled_func)(void*));
285 
286   // Ensure the data in `tensor.data` is readable. In case delegate is used,
287   // it might require to copy the data from delegate buffer to raw memory.
288   // WARNING: This is an experimental API and subject to change.
EnsureTensorDataIsReadable(int tensor_index)289   TfLiteStatus EnsureTensorDataIsReadable(int tensor_index) {
290     TfLiteTensor* t = &tensors_[tensor_index];
291     TF_LITE_ENSURE(&context_, t != nullptr);
292     if (t->data_is_stale) {
293       TF_LITE_ENSURE(&context_, t->delegate != nullptr);
294       TF_LITE_ENSURE(&context_, t->buffer_handle != kTfLiteNullBufferHandle);
295       TF_LITE_ENSURE(&context_, t->delegate->CopyFromBufferHandle != nullptr);
296       TF_LITE_ENSURE_STATUS(t->delegate->CopyFromBufferHandle(
297           &context_, t->delegate, t->buffer_handle, t));
298       t->data_is_stale = false;
299     }
300     return kTfLiteOk;
301   }
302 
303   // The default capacity of `tensors_` vector.
304   static constexpr int kTensorsReservedCapacity = 128;
305   // The capacity headroom of `tensors_` vector before calling ops'
306   // `prepare` and `invoke` function. In these functions, it's guaranteed
307   // allocating up to `kTensorsCapacityHeadroom` more tensors won't invalidate
308   // pointers to existing tensors.
309   static constexpr int kTensorsCapacityHeadroom = 16;
310 
311   // Reset all variable tensors to the default value.
312   // If a variable tensor doesn't have a buffer, reset it to zero.
313   // TODO(b/115961645): Implement - If a variable tensor has a buffer, reset it
314   // to the value of the buffer.
315   // WARNING: This is an experimental API and subject to change.
316   TfLiteStatus ResetVariableTensors();
317 
SetProfiler(Profiler * profiler,int associated_subgraph_idx)318   void SetProfiler(Profiler* profiler, int associated_subgraph_idx) {
319     if (!profiler) {
320       profiler_.reset(nullptr);
321       context_.profiler = nullptr;
322     } else {
323       profiler_ = std::make_unique<SubgraphAwareProfiler>(
324           profiler, associated_subgraph_idx);
325       context_.profiler = profiler_.get();
326     }
327   }
328 
GetProfiler()329   Profiler* GetProfiler() { return profiler_.get(); }
330 
331   // Returns a pointer to vector of subgraphs.
332   // WARNING: This is an experimental API and subject to change.
GetSubgraphs()333   std::vector<std::unique_ptr<Subgraph>>* GetSubgraphs() { return subgraphs_; }
334 
335   // Returns the location of this object within subgraphs_, or
336   // kInvalidSubgraphIndex if subgraphs_ is nullptr or *this is not
337   // represented *subgraphs_.
338   // WARNING: This is an experimental API and subject to
339   // change.
340   static constexpr int kInvalidSubgraphIndex = -1;
GetSubgraphIndex()341   int GetSubgraphIndex() const { return subgraph_index_; }
342 
343   // True if all tensors in the graph has static size after calling
344   // `AllocateTensors` function.
345   // Before `AllocateTensors` is called, this will always return true;
HasDynamicTensors()346   bool HasDynamicTensors() { return has_dynamic_tensors_; }
347 
348   // Assigns (or reassigns) a custom memory allocation for the given tensor.
349   // `flags` is a bitmask, see TfLiteCustomAllocationFlags.
350   // The runtime does NOT take ownership of the underlying memory.
351   //
352   // NOTE: User needs to call AllocateTensors() after this.
353   // Invalid/insufficient buffers will cause an error during AllocateTensors or
354   // Invoke (in case of dynamic shapes in the graph).
355   //
356   // Parameters should satisfy the following conditions:
357   // 1. tensor->allocation_type == kTfLiteArenaRw or kTfLiteArenaRwPersistent
358   //    In general, this is true for I/O tensors & variable tensors.
359   // 2. allocation->data has the appropriate permissions for runtime access
360   //    (Read-only for inputs, Read-Write for others), and outlives Interpreter.
361   // 3. allocation->bytes >= tensor->bytes.
362   //    This condition is checked again if any tensors are resized.
363   // 4. allocation->data should be aligned to kDefaultTensorAlignment
364   //    defined in lite/util.h. (Currently 64 bytes)
365   //    This check is skipped if kTfLiteCustomAllocationFlagsSkipAlignCheck is
366   //    set through `flags`.
367   // TODO(b/182215910): Expand on this documentation in a g3doc.
368   //
369   // WARNING: This is an experimental interface that is subject to change.
370   TfLiteStatus SetCustomAllocationForTensor(
371       int tensor_index, const TfLiteCustomAllocation& allocation,
372       int64_t flags = kTfLiteCustomAllocationFlagsNone);
373 
374   void SetName(const char* name);
375   const std::string& GetName() const;
376 
377   // WARNING: This is an experimental API and subject to change.
378   // Dumps debugging info by the underlying memory planner.
379   // Note: to have minimal binary increase caused by this debug info dump for
380   // the TfLite library and allow users to plug-in their own memory planner
381   // debugger, we have utilized weak symbols to meet these two requirements. By
382   // default, there is no debugging info dumped. However, if the TfLite-provided
383   // lite:simple_memory_arena_debug_dump (i.e. containing the strong defintion)
384   // is linked to the program, calling this function will output memory usage
385   // information about tenosrs and ops.
386   void DumpMemoryPlannerDebugInfo() const;
387 
388   typedef struct SubgraphAllocInfo {
389     size_t arena_size;
390     size_t arena_persist_size;
391     size_t dynamic_size;
392     size_t resource_size;
393   } SubgraphAllocInfo;
394 
395   // WARNING: This is an experimental API and subject to change.
396   // Returns memory allocation status.
397   void GetMemoryAllocInfo(SubgraphAllocInfo* alloc_info) const;
398 
399   // WARNING: This is an experimental API and subject to change.
400   // Set the given `InterpreterOptions` object.
SetOptions(InterpreterOptions * options)401   void SetOptions(InterpreterOptions* options) { options_ = options; }
402 
403   // WARNING: This is an experimental API and subject to change.
404   // True if all intermediates tensors should be preserved for debugging.
ShouldPreserveAllTensors()405   bool ShouldPreserveAllTensors() const {
406     return (options_ && options_->GetPreserveAllTensors());
407   }
408 
409   // WARNING: This is an experimental API and subject to change.
410   // True if all intermediate dynamic tensors should be released once they are
411   // not used by the model.
ShouldReleaseDynamicTensors()412   bool ShouldReleaseDynamicTensors() const {
413     return (options_ && options_->GetEnsureDynamicTensorsAreReleased());
414   }
415 
416   /// WARNING: This is an experimental API and subject to change.
417   /// Use dynamic tensor allocation and deallocation method for large tensors
418   /// instead of static memory planner. Dynamic tensors are allocated just
419   /// before when they're needed and released when they're not needed anymore.
420   /// It improves peak memory usage but there could be some latency impact. The
421   /// parameter `large_tensors_thresholds_in_bytes` is used to determine large
422   /// tensors. This API must be called before `AllocateTensors`.
423   void OptimizeMemoryForLargeTensors(int large_tensors_thresholds_in_bytes);
424 
425   // WARNING: This is an experimental API and subject to change.
426   // True if dynamic tensor allocation / deallocation method is enabled by
427   // `OptimizeMemoryForLargeTensors` API.
ShouldOptimizeMemoryForLargeTensors()428   bool ShouldOptimizeMemoryForLargeTensors() {
429     return (options_ && (options_->GetDynamicAllocationForLargeTensors() > 0));
430   }
431 
432   // WARNING: This is an experimental API and subject to change.
433   // Remove unused inputs of the subgraph. It checks usage of inputs and mark it
434   // as kTfLiteOptionalTensor if the input is not used in graph execution.
435   // Currently, it's used to remove unused inputs of WHILE cond subgraphs.
436   TfLiteStatus RemoveUnusedInputs();
437 
438  private:
439   friend class InterpreterBuilder;
440   friend class TestDelegate;
441   // SubgraphAwareProfiler wraps an actual TFLite profiler, such as a
442   // BufferedProfiler instance, and takes care of event profiling/tracing in a
443   // certain subgraph.
444   class SubgraphAwareProfiler : public Profiler {
445    public:
446     // Constructor should be called with the non-nullptr profiler argument.
SubgraphAwareProfiler(Profiler * profiler,int64_t subgraph_index)447     SubgraphAwareProfiler(Profiler* profiler, int64_t subgraph_index)
448         : profiler_(profiler), subgraph_index_(subgraph_index) {}
~SubgraphAwareProfiler()449     ~SubgraphAwareProfiler() override {}
450 
BeginEvent(const char * tag,EventType event_type,int64_t event_metadata1,int64_t event_metadata2)451     uint32_t BeginEvent(const char* tag, EventType event_type,
452                         int64_t event_metadata1,
453                         int64_t event_metadata2) override {
454       if (!profiler_) return 0;
455       return profiler_->BeginEvent(tag, event_type, event_metadata1,
456                                    subgraph_index_);
457     }
458 
EndEvent(uint32_t event_handle)459     void EndEvent(uint32_t event_handle) override {
460       if (!profiler_) return;
461       profiler_->EndEvent(event_handle);
462     }
463 
EndEvent(uint32_t event_handle,int64_t event_metadata1,int64_t event_metadata2)464     void EndEvent(uint32_t event_handle, int64_t event_metadata1,
465                   int64_t event_metadata2) override {
466       if (!profiler_) return;
467       profiler_->EndEvent(event_handle, event_metadata1, event_metadata2);
468     }
469 
AddEvent(const char * tag,EventType event_type,uint64_t elapsed_time,int64_t event_metadata1,int64_t event_metadata2)470     void AddEvent(const char* tag, EventType event_type, uint64_t elapsed_time,
471                   int64_t event_metadata1, int64_t event_metadata2) override {
472       if (!profiler_) return;
473       profiler_->AddEvent(tag, event_type, elapsed_time, event_metadata1,
474                           subgraph_index_);
475     }
476 
477    private:
478     // Not own the memory.
479     Profiler* const profiler_;
480     const int64_t subgraph_index_;
481   };
482 
483   // Ensure the internal node storage memory allocates at least `count`
484   // spots for node. NOTE, this doesn't actually add operators. This is an
485   // efficiency optimization that is subject to change.
486   // Note: Only used during initialization.
487   void ReserveNodes(int count);
488 
489   // Overrides execution plan. This bounds checks indices sent in.
490   // Note: Only used during initialization.
491   TfLiteStatus SetExecutionPlan(const std::vector<int>& new_plan);
492 
493   // Prevent 'context_' from accessing functions that are only available to
494   // delegated kernels.
495   void SwitchToKernelContext();
496 
497   // Add delegate-only functions to 'context_'.
498   void SwitchToDelegateContext();
499 
500   // Give 'op_reg' a chance to initialize itself using the contents of
501   // 'buffer'. If registration_external is valid, use the 'init' callback from
502   // that.
503   void* OpInit(const TfLiteRegistration& op_reg, const char* buffer,
504                size_t length);
505 
506   // Let 'op_reg' release any memory it might have allocated via 'OpInit'.
507   // If registration_external is valid, use the 'free' callback from that.
508   void OpFree(const TfLiteRegistration& op_reg, void* buffer);
509 
510   // Prepare the given 'node' for execution.
511   TfLiteStatus OpPrepare(const TfLiteRegistration& op_reg, TfLiteNode* node);
512 
513   // Invoke the operator represented by 'node'.
514   TfLiteStatus OpInvoke(const TfLiteRegistration& op_reg, TfLiteNode* node);
515 
516   // Call OpPrepare() for as many ops as possible, allocating memory for their
517   // tensors. If an op containing dynamic tensors is found, preparation will be
518   // postponed until this function is called again. This allows the interpreter
519   // to wait until Invoke() to resolve the sizes of dynamic tensors.
520   TfLiteStatus PrepareOpsAndTensors();
521 
522   // Call OpPrepare() for all ops starting at 'first_node'. Stop when a
523   // dynamic tensors is found or all ops have been prepared. Fill
524   // 'last_node_prepared' with the id of the op containing dynamic tensors, or
525   // the last in the graph.
526   TfLiteStatus PrepareOpsStartingAt(int first_execution_plan_index,
527                                     const std::vector<int>& execution_plan,
528                                     int* last_execution_plan_index_prepared);
529 
530   // Tensors needed by the interpreter. Use `AddTensors` to add more blank
531   // tensor entries. Note, `tensors_.data()` needs to be synchronized to the
532   // `context_` whenever this std::vector is reallocated. Currently this
533   // only happens in `AddTensors()`.
534   std::vector<TfLiteTensor> tensors_;
535 
536   // Check if an array of tensor indices are valid with respect to the Tensor
537   // array.
538   // NOTE: this changes consistent_ to be false if indices are out of bounds.
539   TfLiteStatus CheckTensorIndices(const char* label, const int* indices,
540                                   int length);
541 
542   // Check that the input indices and the output indices don't overlap.
543   // This is needed because same tensor must not be used both as input and
544   // output for an operator.
545   // NOTE: this changes consistent_ to be false if indices are out of bounds.
546   TfLiteStatus CheckInputAndOutputForOverlap(const int* input_indices,
547                                              int num_inputs,
548                                              const int* output_indices,
549                                              int num_outputs);
550 
551   // Compute the number of bytes required to represent a tensor with dimensions
552   // specified by the array dims (of length dims_size). Returns the status code
553   // and bytes.
554   TfLiteStatus BytesRequired(TfLiteType type, const int* dims, size_t dims_size,
555                              size_t* bytes);
556 
557   // Request an tensor be resized implementation. If the given tensor is of
558   // type kTfLiteDynamic it will also be allocated new memory.
559   TfLiteStatus ResizeTensorImpl(TfLiteTensor* tensor, TfLiteIntArray* new_size);
560 
561   // Report a detailed error string (will be printed to stderr).
562   void ReportErrorImpl(const char* format, va_list args);
563 
564   // Entry point for C node plugin API to request an tensor be resized.
565   static TfLiteStatus ResizeTensor(TfLiteContext* context, TfLiteTensor* tensor,
566                                    TfLiteIntArray* new_size);
567   // Entry point for C node plugin API to report an error.
568   static void ReportErrorC(TfLiteContext* context, const char* format, ...);
569 
570   // Entry point for C node plugin API to add new tensors.
571   static TfLiteStatus AddTensors(TfLiteContext* context, int tensors_to_add,
572                                  int* first_new_tensor_index);
573 
574   // WARNING: This is an experimental API and subject to change.
575   // Entry point for C API ReplaceNodeSubsetsWithDelegateKernels
576   static TfLiteStatus ReplaceNodeSubsetsWithDelegateKernels(
577       TfLiteContext* context, TfLiteRegistration registration,
578       const TfLiteIntArray* nodes_to_replace, TfLiteDelegate* delegate);
579 
580   // Update the execution graph to replace some of the nodes with stub
581   // nodes. Specifically any node index that has `nodes[index]==1` will be
582   // slated for replacement with a delegate kernel specified by registration.
583   // Ownership of 'nodes_to_replace' and 'delegate' remains with the caller.
584   // WARNING: This is an experimental interface that is subject to change.
585   TfLiteStatus ReplaceNodeSubsetsWithDelegateKernels(
586       TfLiteRegistration registration, const TfLiteIntArray* nodes_to_replace,
587       TfLiteDelegate* delegate);
588 
589   // WARNING: This is an experimental interface that is subject to change.
590   // Gets the internal pointer to a TensorFlow lite node by node_index.
591   TfLiteStatus GetNodeAndRegistration(int node_index, TfLiteNode** node,
592                                       TfLiteRegistration** registration);
593 
594   // WARNING: This is an experimental interface that is subject to change.
595   // Entry point for C node plugin API to get a node by index.
596   static TfLiteStatus GetNodeAndRegistration(struct TfLiteContext*,
597                                              int node_index, TfLiteNode** node,
598                                              TfLiteRegistration** registration);
599 
600   // WARNING: This is an experimental interface that is subject to change.
601   // Gets an TfLiteIntArray* representing the execution plan. The interpreter
602   // owns this memory and it is only guaranteed to exist during the invocation
603   // of the delegate prepare.
604   TfLiteStatus GetExecutionPlan(TfLiteIntArray** execution_plan);
605 
606   // WARNING: This is an experimental interface that is subject to change.
607   // Entry point for C node plugin API to get the execution plan.
608   static TfLiteStatus GetExecutionPlan(struct TfLiteContext* context,
609                                        TfLiteIntArray** execution_plan);
610 
611   // WARNING: This is an experimental interface that is subject to change.
612   // Provides a preview of post-delegation partitioning. Each
613   // TfLiteDelegateParams in the referenced array corresponds to one instance of
614   // the delegate kernel.
615   // nodes_to_replace should point to a valid array. partition_params_array &
616   // num_partitions should be non-null.
617   // Memory allocated by this method is automatically released with another call
618   // to PreviewDelegateParitioning, or after TfLiteDelegate::Prepare is done.
619   TfLiteStatus PreviewDelegatePartitioning(
620       const TfLiteIntArray* nodes_to_replace,
621       TfLiteDelegateParams** partition_params_array, int* num_partitions);
622 
623   // WARNING: This is an experimental interface that is subject to change.
624   // Entry point for C node plugin API to preview delegation partitioning.
625   static TfLiteStatus PreviewDelegatePartitioning(
626       struct TfLiteContext* context, const TfLiteIntArray* nodes_to_replace,
627       TfLiteDelegateParams** partition_params_array, int* num_partitions);
628 
629   // Retrieves named metadata from the TFLite model. Returns kTfLiteOk if
630   // metadata is successfully obtained.
631   // See the Metadata table in TFLite schema.
632   TfLiteStatus GetModelMetadata(const char* name, const char** ptr,
633                                 size_t* bytes);
634 
635   // Entry point for C node plugin API to get model metadata based on name.
636   static TfLiteStatus GetModelMetadata(const struct TfLiteContext* context,
637                                        const char* name, const char** ptr,
638                                        size_t* bytes);
639 
640   // Used to clear partitioning_preview_cache_, in case
641   // PreviewDelegatePartitioning was called.
642   void FreeDelegatePartitioningData();
643 
644   // Retrieve an existing external context by type.
645   TfLiteExternalContext* GetExternalContext(TfLiteExternalContextType type);
646   static TfLiteExternalContext* GetExternalContext(
647       struct TfLiteContext* context, TfLiteExternalContextType type);
648 
649   // Set the value of an external context.
650   static void SetExternalContext(struct TfLiteContext* context,
651                                  TfLiteExternalContextType type,
652                                  TfLiteExternalContext* ctx);
653 
654   // WARNING: This is an experimental API and subject to change.
655   // Allow a delegate to look at the graph and modify the graph to handle
656   // parts of the graph themselves. After this is called, the graph may
657   // contain new nodes that replace 1 more nodes.
658   // NOTE: If tensors were allocated prior to delegate application, they will
659   // be reallocated if the graph was modified (i.e., the caller does *not* need
660   // to explicitly call |AllocateTensors()| again). If tensors were unallocated,
661   // they will remain unallocated after delegate application.
662   // Returns one of the following status codes:
663   // 1. kTfLiteOk: Delegation succeeded
664   // 2. kTfLiteDelegateError: Delegation failed due to an error *in the
665   // delegate*, or the delegate parameter was null. The Subgraph has been
666   // restored to its pre-delegation state.
667   // NOTE: This reverts all delegates previously applied to the Subgraph.
668   // 3. kTfLiteApplicationError : Delegation failed to be applied due to the
669   // incompatibility with the TF Lite runtime, e.g., the model graph is already
670   // immutable when applying the delegate. However, the Subgraph is still in a
671   // invokable state.
672   // 4. kTfLiteUnresolvedOps: Delegation failed because the model has an
673   // operator that cannot be resolved. This can happen when the op is not
674   // registered or built with the TF Lite framework.
675   // 5. kTfLiteError: Unexpected/runtime failure.
676   TfLiteStatus ModifyGraphWithDelegate(TfLiteDelegate* delegate);
677 
678   // This un-applies all delegates that have been applied till now, but retains
679   // pointers to them.
680   // The old execution plan and nodes are restored.
681   TfLiteStatus UndoAllDelegates();
682 
683   // This re-applies all delegates that were undone.
684   // Does nothing if UndoAllDelegates wasn't previously called.
685   TfLiteStatus RedoAllDelegates();
686 
687   // This removes all delegates.
688   // The old execution plan and nodes are restored. The graph is invokable
689   // afterwards.
690   TfLiteStatus RemoveAllDelegates();
691 
692   // Returns true if the subgraph has delegates applied.
693   bool HasDelegates();
694 
695   // Returns true if the subgraph has been fully delegated.
696   bool IsFullyDelegated() const;
697 
698   // Cleanups up data reserved for the given node. Does not remove the {node,
699   // registration} pair from nodes_and_registrations_.
700   void CleanupNode(int node_index);
701 
702   // Ensures that `tensors_` has at least `kTensorsCapacityHeadroom` extra
703   // capacity. Calling this function may invalidate existing pointers to
704   // tensors. After calling this function, adding `kTensorsCapacityHeadroom`
705   // more tensors won't invalidate the pointer to existing tensors.
706   void EnsureTensorsVectorCapacity();
707 
708   // Ensures the memory required is planned and allocated.
709   TfLiteStatus EnsureMemoryAllocations();
710 
711   // Returns true if cancellation function returns true.
712   bool IsCancelled();
713 
714   // Returns true if 'node' could have side effect (e.g. stateful op).
715   // Note that any node that might update other tensors beside op's output
716   // are considered to have side effect.
717   // So control flow ops like 'If' and 'While' are considered to have
718   // side effect because they can have ops that have side effect in the
719   // condition and body subgraphs.
720   bool OpMightHaveSideEffect(const TfLiteNode* node,
721                              const TfLiteRegistration* registration) const;
722 
723   // Returns new GraphInfo object based on the current Subgraph.
724   std::unique_ptr<GraphInfo> CreateGraphInfo();
725 
726   // Store a ptr to the model metadata owned by the Interpreter.
727   // Since the lifetime of the Interpreter exceeds the Subgraph, metadata
728   // remains valid for the latter's lifetime.
729   // Also sets relevant fields on context_ based on known metadata.
730   TfLiteStatus SetMetadata(const std::map<std::string, std::string>* metadata);
731 
732   // Initializes the mapping between tensor index to the index of the
733   // last operation that uses the tensor as input.
734   void InitializeTensorReleaseMap();
735 
736   // May allocate dynamic tensor memory of node outputs. It's used when
737   // `EnsureDynamicTensorsAreReleased` or`UseDynamicAllocationForLargeTensors`
738   // API is used.
739   TfLiteStatus MayAllocateOpOutput(TfLiteNode* node);
740 
741   // Checks the options for releasing dynamic tensors and release dynamic
742   // tensors if configured.
743   void MaybeReleaseDynamicTensors(const TfLiteNode& node, size_t node_index);
744 
745   // The state of the Subgraph.
746   enum State {
747     // The Subgraph isn't ready to be invoked.
748     // `AllocateTensor` need to be called to enter an invokable state.
749     kStateUninvokable = 0,
750     // The Subgraph is ready to be invoked.
751     kStateInvokable,
752     // The Subgraph is ready to be invoked, and graph can't be further
753     // modified. The Subgraph will enter this state when calling
754     // `ModifyGraphWithDelegate` and the delegate doesn't support dynamic
755     // tensors.
756     kStateInvokableAndImmutable,
757   };
758   State state_ = kStateUninvokable;
759 
760   // A pure C data structure used to communicate with the pure C plugin
761   // interface. To avoid copying tensor metadata, this is also the definitive
762   // structure to store tensors.
763   TfLiteContext context_ = {};
764 
765   // A pointer to the external contexts (kTfLiteMaxExternalContexts) array that
766   // sits inside the associated TFLite interpreter instance.
767   TfLiteExternalContext** external_contexts_;
768 
769   // Node inputs/outputs are stored in TfLiteNode and TfLiteRegistration stores
770   // function pointers to actual implementation.
771   // Nodes should appear in the order in which they are instantiated at runtime.
772   // Delegated nodes are appended after all the original ones.
773   std::vector<std::pair<TfLiteNode, TfLiteRegistration>>
774       nodes_and_registration_;
775 
776   // Whether the model is consistent. That is to say if the inputs and outputs
777   // of every node and the global inputs and outputs are valid indexes into
778   // the tensor array.
779   bool consistent_ = true;
780 
781   // Array of indices representing the tensors that are inputs to the
782   // interpreter.
783   std::vector<int> inputs_;
784 
785   // Array of indices representing the tensors that are outputs to the
786   // interpreter.
787   std::vector<int> outputs_;
788 
789   // Array of indices representing the tensors that are variable tensors.
790   std::vector<int> variables_;
791 
792   // The error reporter delegate that tflite will forward queries errors to.
793   ErrorReporter* error_reporter_;
794 
795   // Index of the next node to prepare.
796   // During Invoke(), Interpreter will allocate input tensors first, which are
797   // known to be fixed size. Then it will allocate outputs from nodes as many
798   // as possible. When there is a node that produces dynamic sized tensor.
799   // Interpreter will stop allocating tensors, set the value of next allocate
800   // node id, and execute the node to generate the output tensor before continue
801   // to allocate successors. This process repeats until all nodes are executed.
802   // NOTE: this relies on the order of nodes that is in topological order.
803   int next_execution_plan_index_to_prepare_;
804 
805   // Only used in cases where a delegate supporting dynamic tensors is applied.
806   // This helps prepare the original execution before the post-delegation one,
807   // so that tensor shapes propagate.
808   int next_original_execution_plan_index_to_prepare_;
809 
810   // This is similar to `next_execution_plan_index_to_prepare_`, but it tracks
811   // which nodes' allocation is planned with the arena planner.
812   //
813   // This is a workaround for b/127354079. It shouldn't be necessary if
814   // ArenaPlanner can "rewind" to a specific point.
815   // TODO(b/127354079): Improve ArenaPlanner and remove this mechanism.
816   int next_execution_plan_index_to_plan_allocation_;
817 
818   // WARNING: This is an experimental interface that is subject to change.
819   // This is a list of node indices (to index into nodes_and_registration).
820   // This represents a valid topological sort (dependency ordered) execution
821   // plan. In particular, it is valid for this ordering to contain only a
822   // subset of the node indices.
823   std::vector<int> execution_plan_;
824 
825   // This is a copy of the first execution_plan_ before any delegates were
826   // applied. It is empty if no delegates were applied to this Subgraph.
827   std::vector<int> pre_delegation_execution_plan_;
828 
829   // Contains a list of delegates applied by the user so far, in order.
830   std::vector<TfLiteDelegate*> delegates_applied_;
831 
832   // Set to true if UndoAllDelegates was called, and to false during
833   // RedoAllDelegates.
834   bool delegates_undone_ = false;
835 
836   // In the future, we'd like a TfLiteIntArray compatible representation.
837   // TODO(aselle): replace execution_plan_ with this.
838   std::unique_ptr<TfLiteIntArray, TfLiteIntArrayDeleter> plan_cache_;
839 
840   // Used by PreviewDelegateParitioning.
841   std::vector<TfLiteDelegateParams> partitioning_preview_cache_;
842 
843   std::unique_ptr<MemoryPlanner> memory_planner_;
844 
845   // Maps tensor index to custom allocation for all applicable tensors.
846   std::map<int, TfLiteCustomAllocation> custom_allocations_;
847 
848   // Tracking bit for whether a tensor was resized in the course of an op
849   // invocation. This is a useful hint to ensure that dynamic tensor outputs
850   // trigger downstream reallocation after op invocation.
851   bool tensor_resized_since_op_invoke_ = false;
852 
853   // Profiler for this interpreter instance.
854   std::unique_ptr<SubgraphAwareProfiler> profiler_;
855 
856   // A pointer to vector of subgraphs. The vector is owned by the interpreter.
857   std::vector<std::unique_ptr<Subgraph>>* subgraphs_ = nullptr;
858 
859   // Location of the pointer to *this in *subgraphs_, or kInvalidSubgraphIndex.
860   const int subgraph_index_;
861 
862   // True if not all tensors in the graph has static size after calling
863   // `PrepareOpsStartingAt` function (which is called by the `AllocateTensors`
864   // public function).
865   // The value is invalid before `PrepareOpStartingAt` is called.
866   bool has_dynamic_tensors_ = true;
867 
868   // WARNING: This is an experimental interface that is subject to change.
869   // This is the index of dynamic tensor which was checked at
870   // PrepareOpsStartingAt() when `has_dynamic_tensors_` is set. This information
871   // is kept only for user error message.
872   int dynamic_tensor_index_ = -1;
873 
874   // Reference to cancellation function that can cancel a request in the middle
875   // of a call to Invoke(). When this function returns True, a kTfLiteError is
876   // thrown by Invoke().
877   bool (*check_cancelled_func_)(void*) = nullptr;
878 
879   // Reference to data used by the cancellation function in
880   // `check_cancelled_func_`.
881   void* cancellation_data_ = nullptr;
882 
883   // A map of resources. Owned by interpreter and shared by multiple subgraphs.
884   resource::ResourceMap* resources_ = nullptr;
885 
886   // A map of resources IDs. Owned by interpreter and shared by multiple
887   // subgraphs.
888   resource::ResourceIDMap* resource_ids_ = nullptr;
889 
890   // A map of initialization statuses, that indicate whether the intialization
891   // subgraph invocation is done or not.
892   resource::InitializationStatusMap* initialization_status_map_;
893 
894   // Name of the subgraph (analogous to function name).
895   std::string name_;
896 
897   // Model-metadata owned by the Interpreter.
898   const std::map<std::string, std::string>* metadata_ = nullptr;
899 
900   // Mapping between tensor index to the last index of the execution plan that
901   // uses this tensor.
902   std::map<int, int> tensor_to_last_op_index_;
903 
904   // `InterpreterOptions` object which is being used and owned by Interpreter.
905   InterpreterOptions* options_;
906 };
907 
908 }  // namespace tflite
909 #endif  // TENSORFLOW_LITE_CORE_SUBGRAPH_H_
910