#include "tensorflow/lite/core/subgraph.h"
#include <algorithm>
#include <atomic>
#include <cstdarg>
#include <cstddef>
#include <cstdint>
#include <cstdlib>
#include <cstring>
#include <iterator>
#include <memory>
#include <string>
#include <unordered_set>
#include <utility>
#include <vector>
#include "tensorflow/lite/allocation.h"
#include "tensorflow/lite/array.h"
#include "tensorflow/lite/builtin_ops.h"
#include "tensorflow/lite/c/common_internal.h"
#include "tensorflow/lite/context_util.h"
#include "tensorflow/lite/core/api/error_reporter.h"
#include "tensorflow/lite/core/api/op_resolver.h"
#include "tensorflow/lite/core/api/profiler.h"
#include "tensorflow/lite/core/api/tensor_utils.h"
#include "tensorflow/lite/core/c/c_api_types.h"
#include "tensorflow/lite/core/c/common.h"
#include "tensorflow/lite/experimental/resource/initialization_status.h"
#include "tensorflow/lite/experimental/resource/resource_base.h"
#include "tensorflow/lite/graph_info.h"
#include "tensorflow/lite/logger.h"
#include "tensorflow/lite/memory_planner.h"
#include "tensorflow/lite/minimal_logging.h"
#include "tensorflow/lite/profiling/telemetry/telemetry.h"
#include "tensorflow/lite/schema/schema_generated.h"
#include "tensorflow/lite/util.h"
#ifdef TFLITE_USE_SIMPLE_MEMORY_PLANNER
#include "tensorflow/lite/simple_planner.h"
#else
#include "tensorflow/lite/arena_planner.h"
#endif
#ifdef TF_LITE_TENSORFLOW_PROFILER
#include "tensorflow/lite/tensorflow_profiler_logger.h"
#endif
namespace tflite {
namespace {
struct TfLiteQuantizationDeleter { … };
ScopedTfLiteQuantization;
struct TfLiteSparsityDeleter { … };
ScopedTfLiteSparsity;
TfLiteStatus ReportOpError(TfLiteContext* context, const TfLiteNode& node,
const TfLiteRegistration& registration,
int node_index, const char* message) { … }
TfLiteStatus ForbiddenContextFunction(TfLiteContext* context, ...) { … }
template <typename FunctionType>
void SetForbiddenContextFunction(FunctionType* func) { … }
template <typename TensorIntArray>
bool HasDynamicTensorImpl(const TfLiteContext& context,
const TensorIntArray& int_array,
int* dynamic_tensor_index) { … }
bool HasDynamicTensor(const TfLiteContext& context,
const TfLiteIntArray* int_array,
int* dynamic_tensor_index) { … }
TfLiteQuantizationParams GetLegacyQuantization(
const TfLiteQuantization& quantization) { … }
static constexpr const char kUnknownCustomOpName[] = …;
const char* GetTFLiteOpName(const TfLiteRegistration& op_reg) { … }
TfLiteStatus VerifyCustomAllocationForTensor(
TfLiteContext* context,
const std::map<int, TfLiteCustomAllocation>& tensor_idx_to_alloc,
const int tensor_idx) { … }
}
class InterpreterInfo : public GraphInfo { … };
Subgraph::Subgraph(ErrorReporter* error_reporter,
TfLiteExternalContext** external_contexts,
std::vector<std::unique_ptr<Subgraph>>* subgraphs,
resource::ResourceMap* resources,
resource::ResourceIDMap* resource_ids,
resource::InitializationStatusMap* initialization_status_map,
int subgraph_index)
: … { … }
Subgraph::~Subgraph() { … }
void Subgraph::CleanupNode(int node_index) { … }
TfLiteStatus Subgraph::ReplaceNodeSubsetsWithDelegateKernels(
TfLiteContext* context, TfLiteRegistration registration,
const TfLiteIntArray* nodes_to_replace, TfLiteDelegate* delegate) { … }
namespace {
void CopyVectorToTfLiteIntArray(const std::vector<int>& vec,
TfLiteIntArray* arr) { … }
template <typename Params>
Params* CreateDelegateParamsImpl(TfLiteDelegate* delegate,
const NodeSubset& node_subset) { … }
TfLiteDelegateParams* CreateDelegateParams(TfLiteDelegate* delegate,
const NodeSubset& node_subset) { … }
TfLiteOpaqueDelegateParams* CreateOpaqueDelegateParams(
TfLiteDelegate* delegate, const NodeSubset& node_subset) { … }
void PopulatePreviewDelegateParams(const NodeSubset& node_subset,
TfLiteDelegateParams* params) { … }
const char* GetDelegateKernalName(const TfLiteRegistration& registration) { … }
}
TfLiteStatus Subgraph::PartitionGraph(const TfLiteIntArray* nodes_to_replace,
std::vector<NodeSubset>* node_subsets) { … }
TfLiteStatus Subgraph::ReplaceNodeSubsetsWithDelegateKernels(
TfLiteRegistration registration, const TfLiteIntArray* nodes_to_replace,
TfLiteDelegate* delegate) { … }
TfLiteExternalContext* Subgraph::GetExternalContext(
TfLiteExternalContextType type) { … }
TfLiteExternalContext* Subgraph::GetExternalContext(
struct TfLiteContext* context, TfLiteExternalContextType type) { … }
void Subgraph::SetExternalContext(TfLiteExternalContextType type,
TfLiteExternalContext* ctx) { … }
void Subgraph::SetExternalContext(struct TfLiteContext* context,
TfLiteExternalContextType type,
TfLiteExternalContext* ctx) { … }
TfLiteStatus Subgraph::GetExecutionPlan(TfLiteIntArray** execution_plan) { … }
TfLiteStatus Subgraph::GetExecutionPlan(struct TfLiteContext* context,
TfLiteIntArray** execution_plan) { … }
void Subgraph::FreeDelegatePartitioningData() { … }
TfLiteStatus Subgraph::GetModelMetadata(const char* name, const char** ptr,
size_t* bytes) { … }
TfLiteStatus Subgraph::GetModelMetadata(const struct TfLiteContext* context,
const char* name, const char** ptr,
size_t* bytes) { … }
TfLiteStatus Subgraph::AcquireSubgraphContext(
int subgraph_index, TfLiteContext** acquired_context) { … }
TfLiteStatus Subgraph::AcquireSubgraphContext(
struct TfLiteContext* context, int subgraph_index,
TfLiteContext** acquired_context) { … }
TfLiteStatus Subgraph::ReleaseSubgraphContext(int subgraph_index) { … }
TfLiteStatus Subgraph::ReleaseSubgraphContext(struct TfLiteContext* context,
int subgraph_index) { … }
TfLiteStatus Subgraph::MarkSubgraphAsDelegationSkippable(int subgraph_index) { … }
TfLiteStatus Subgraph::GetNodeInitDataMmapInfo(
const TfLiteNode* node, int* fd,
int64_t* custom_initial_data_offset_in_file,
int64_t* custom_initial_data_size) const { … }
TfLiteStatus Subgraph::PreviewDelegatePartitioning(
const TfLiteIntArray* nodes_to_replace,
TfLiteDelegateParams** partition_params_array, int* num_partitions) { … }
TfLiteStatus Subgraph::PreviewDelegatePartitioning(
struct TfLiteContext* context, const TfLiteIntArray* nodes_to_replace,
TfLiteDelegateParams** partition_params_array, int* num_partitions) { … }
TfLiteStatus Subgraph::SetInputs(std::vector<int> inputs) { … }
TfLiteStatus Subgraph::SetOutputs(std::vector<int> outputs) { … }
TfLiteStatus Subgraph::SetVariables(std::vector<int> variables) { … }
TfLiteStatus Subgraph::SetMetadata(
const std::map<std::string, std::string>* metadata,
const ControlEdges* control_edges) { … }
void Subgraph::SetCancellationFunction(void* data,
bool (*check_cancelled_func)(void*)) { … }
TfLiteStatus Subgraph::EnsureTensorDataIsReadable(int tensor_index) { … }
TfLiteStatus Subgraph::EnableCancellation(std::atomic_flag* flag) { … }
TfLiteStatus Subgraph::Cancel() { … }
bool Subgraph::IsCancelled() { … }
void Subgraph::ReserveNodes(int count) { … }
TfLiteStatus Subgraph::CheckTensorIndices(const char* label, const int* indices,
int length) { … }
TfLiteStatus Subgraph::CheckInputAndOutputForOverlap(const int* input_indices,
int num_inputs,
const int* output_indices,
int num_outputs) { … }
std::vector<int> Subgraph::GetInputTensorsCount() { … }
TfLiteStatus Subgraph::AllocateTensors() { … }
TfLiteStatus Subgraph::ResetVariableTensors() { … }
TfLiteStatus Subgraph::AddNodeWithParameters(
const std::vector<int>& inputs, const std::vector<int>& outputs,
const std::vector<int>& intermediates, const char* init_data,
size_t init_data_size, void* builtin_data,
const TfLiteRegistration* registration, int* node_index) { … }
namespace {
bool AnyTensorOfTypeResource(const std::vector<TfLiteTensor>& tensors,
const TfLiteIntArray* tensor_indexes) { … }
}
bool Subgraph::OpMightHaveSideEffect(
const TfLiteNode* node, const TfLiteRegistration* registration) const { … }
TfLiteStatus Subgraph::ResizeInputTensor(int tensor_index,
const int* const dims_data,
const int rank) { … }
TfLiteStatus Subgraph::ResizeInputTensor(int tensor_index,
const std::vector<int>& dims) { … }
TfLiteStatus Subgraph::ResizeInputTensorStrict(int tensor_index,
const std::vector<int>& dims) { … }
TfLiteStatus Subgraph::ReleaseNonPersistentMemory() { … }
TfLiteStatus Subgraph::ReleaseMemory() { … }
void* Subgraph::OpInit(const TfLiteRegistration& op_reg, const char* buffer,
size_t length) { … }
TfLiteStatus Subgraph::OpPrepare(const TfLiteRegistration& op_reg,
TfLiteNode* node) { … }
TfLiteStatus Subgraph::OpInvoke(const TfLiteRegistration& op_reg,
TfLiteNode* node) { … }
void Subgraph::OpFree(const TfLiteRegistration& op_reg, void* buffer) { … }
TfLiteStatus Subgraph::MayAllocateOpOutput(TfLiteNode* node) { … }
TfLiteStatus Subgraph::PrepareOpsStartingAt(
int first_execution_plan_index, const std::vector<int>& execution_plan,
int* last_execution_plan_index_prepared) { … }
TfLiteStatus Subgraph::PrepareOpsAndTensors() { … }
TfLiteStatus Subgraph::RemoveUnusedInputs() { … }
TfLiteStatus Subgraph::Invoke() { … }
TfLiteStatus Subgraph::InvokeImpl() { … }
TfLiteStatus Subgraph::ResizeTensor(TfLiteContext* context,
TfLiteTensor* tensor,
TfLiteIntArray* new_size) { … }
void Subgraph::ReportErrorImpl(const char* format, va_list args) { … }
void Subgraph::ReportErrorC(TfLiteContext* context, const char* format, ...) { … }
void Subgraph::ReportError(const char* format, ...) { … }
TfLiteStatus Subgraph::AddTensors(int tensors_to_add,
int* first_new_tensor_index) { … }
TfLiteStatus Subgraph::AddTensors(TfLiteContext* context, int tensors_to_add,
int* first_new_tensor_index) { … }
TfLiteStatus Subgraph::GetNodeAndRegistration(
int node_index, TfLiteNode** node, TfLiteRegistration** registration) { … }
TfLiteStatus Subgraph::GetNodeAndRegistration(
struct TfLiteContext* context, int node_index, TfLiteNode** node,
TfLiteRegistration** registration) { … }
TfLiteStatus Subgraph::SetTensorParametersReadOnly(
int tensor_index, TfLiteType type, const char* name, const size_t ndims,
const int* dims, TfLiteQuantization quantization, const char* buffer,
size_t bytes, const Allocation* allocation, TfLiteSparsity* sparsity,
const size_t buffer_identifier) { … }
TfLiteStatus Subgraph::SetTensorParametersReadWrite(
int tensor_index, TfLiteType type, const char* name, const size_t ndims,
const int* dims, TfLiteQuantization quantization, bool is_variable,
const size_t ndims_signature, const int* dims_signature) { … }
TfLiteStatus Subgraph::SetExecutionPlan(const std::vector<int>& new_plan) { … }
TfLiteStatus Subgraph::ResizeTensorImpl(TfLiteTensor* tensor,
TfLiteIntArray* new_size) { … }
void Subgraph::OptimizeMemoryForLargeTensors(
int large_tensors_thresholds_in_bytes) { … }
TfLiteStatus Subgraph::SwitchToDelegateContext() { … }
TfLiteStatus Subgraph::SwitchToKernelContext() { … }
TfLiteStatus Subgraph::UndoAllDelegates() { … }
TfLiteStatus Subgraph::RedoAllDelegates() { … }
TfLiteStatus Subgraph::RemoveAllDelegates() { … }
bool Subgraph::HasDelegates() { … }
bool Subgraph::IsFullyDelegated() const { … }
void Subgraph::EnsureTensorsVectorCapacity() { … }
TfLiteStatus Subgraph::EnsureMemoryAllocations() { … }
TfLiteStatus Subgraph::ModifyGraphWithDelegate(TfLiteDelegate* delegate) { … }
TfLiteStatus Subgraph::ModifyGraphWithDelegateImpl(TfLiteDelegate* delegate) { … }
TfLiteStatus Subgraph::SetCustomAllocationForTensor(
int tensor_index, const TfLiteCustomAllocation& allocation, int64_t flags) { … }
void Subgraph::SetName(const char* name) { … }
const std::string& Subgraph::GetName() const { … }
void Subgraph::DumpMemoryPlannerDebugInfo() const { … }
void Subgraph::GetMemoryAllocInfo(SubgraphAllocInfo* alloc_info) const { … }
std::unique_ptr<GraphInfo> Subgraph::CreateGraphInfo() { … }
void Subgraph::InitializeTensorReleaseMap() { … }
void Subgraph::MaybeReleaseDynamicTensors(const TfLiteNode& node,
size_t node_index) { … }
TfLiteStatus Subgraph::SetBufferHandleImpl(
TfLiteContext* context, TfLiteTensor* tensor,
TfLiteBufferHandle buffer_handle, TfLiteDelegate* delegate,
bool release_existing_buffer_handle) { … }
}