blob: e029e2c42006ff2522c5547f0a7be95521676306 [file] [log] [blame]
Sadik Armagan3c24f432020-10-19 17:35:30 +01001//
2// Copyright © 2020 Arm Ltd and Contributors. All rights reserved.
3// SPDX-License-Identifier: MIT
4//
5
6#include <armnn_delegate.hpp>
Sadik Armagan62483be2020-10-23 17:14:43 +01007
Matthew Sloyanac001ee2021-02-03 10:43:04 +00008#include "Version.hpp"
9
Sadik Armagan62483be2020-10-23 17:14:43 +010010#include "Activation.hpp"
11#include "ArgMinMax.hpp"
12#include "BatchSpace.hpp"
13#include "Comparison.hpp"
14#include "Convolution.hpp"
15#include "Control.hpp"
16#include "ElementwiseBinary.hpp"
17#include "ElementwiseUnary.hpp"
18#include "Fill.hpp"
19#include "FullyConnected.hpp"
20#include "Gather.hpp"
Matthew Sloyanc8eb9552020-11-26 10:54:22 +000021#include "LogicalBinary.hpp"
Sadik Armagan62483be2020-10-23 17:14:43 +010022#include "Lstm.hpp"
23#include "Normalization.hpp"
Matthew Sloyana7a12f52021-05-06 10:05:28 +010024#include "Pack.hpp"
Sadik Armagan62483be2020-10-23 17:14:43 +010025#include "Pad.hpp"
26#include "Pooling.hpp"
James Conroy39825482021-05-27 17:44:50 +010027#include "Prelu.hpp"
Sadik Armagan62483be2020-10-23 17:14:43 +010028#include "Quantization.hpp"
29#include "Redefine.hpp"
Sadik Armagana2747482021-02-09 10:28:54 +000030#include "Reduce.hpp"
Sadik Armagan62483be2020-10-23 17:14:43 +010031#include "Resize.hpp"
32#include "Round.hpp"
Keith Davis0176fd82021-06-01 17:36:32 +010033#include "Shape.hpp"
Sadik Armagan62483be2020-10-23 17:14:43 +010034#include "Slice.hpp"
35#include "Softmax.hpp"
36#include "SpaceDepth.hpp"
Sadik Armagan34fa1bd2020-11-27 12:40:52 +000037#include "Split.hpp"
Sadik Armagan62483be2020-10-23 17:14:43 +010038#include "Transpose.hpp"
Narumol Prangnawarat7684b182021-08-12 14:48:15 +010039#include "UnidirectionalSequenceLstm.hpp"
Kevin May8ab2d7a2021-05-07 09:32:51 +010040#include "Unpack.hpp"
Sadik Armagan62483be2020-10-23 17:14:43 +010041
Colm Donelan3e32a872021-10-04 22:55:37 +010042#include <armnnUtils/Filesystem.hpp>
Sadik Armagan62483be2020-10-23 17:14:43 +010043#include <flatbuffers/flatbuffers.h>
44#include <tensorflow/lite/context_util.h>
45
Sadik Armagan3c24f432020-10-19 17:35:30 +010046#include <algorithm>
Matthew Sloyanac001ee2021-02-03 10:43:04 +000047#include <iostream>
Sadik Armagan62483be2020-10-23 17:14:43 +010048#include <sstream>
Sadik Armagan3c24f432020-10-19 17:35:30 +010049
50namespace armnnDelegate
51{
52
Sadik Armagan62483be2020-10-23 17:14:43 +010053DelegateOptions TfLiteArmnnDelegateOptionsDefault()
54{
55 DelegateOptions options(armnn::Compute::CpuRef);
56 return options;
57}
58
59TfLiteDelegate* TfLiteArmnnDelegateCreate(armnnDelegate::DelegateOptions options)
60{
61 auto* armnnDelegate = new ::armnnDelegate::Delegate(options);
62 return armnnDelegate->GetDelegate();
63}
64
65void TfLiteArmnnDelegateDelete(TfLiteDelegate* tfLiteDelegate)
66{
67 if (tfLiteDelegate != nullptr)
68 {
69 delete static_cast<::armnnDelegate::Delegate*>(tfLiteDelegate->data_);
70 }
71}
72
73TfLiteStatus DoPrepare(TfLiteContext* tfLiteContext, TfLiteDelegate* tfLiteDelegate)
74{
75 TfLiteIntArray* supportedOperators =
76 static_cast<::armnnDelegate::Delegate*>(tfLiteDelegate->data_)->IdentifyOperatorsToDelegate(tfLiteContext);
77
78 // ArmNN Delegate Registration
79 static const TfLiteRegistration kArmnnSubgraphRegistration = {
80 // ArmnnSubgraph Init
81 .init = [](TfLiteContext* tfLiteContext, const char* buffer, size_t length) -> void* {
Finn Williams6f9f9902020-11-13 13:23:15 +000082 armnn::IgnoreUnused(length);
Sadik Armagan62483be2020-10-23 17:14:43 +010083 const TfLiteDelegateParams* parameters = reinterpret_cast<const TfLiteDelegateParams*>(buffer);
84
85 return static_cast<void*>(ArmnnSubgraph::Create(
86 tfLiteContext, parameters, static_cast<::armnnDelegate::Delegate*>(parameters->delegate->data_)));
87 },
88 // ArmnnSubgraph Free
89 .free = [](TfLiteContext* tfLiteContext, void* buffer) -> void {
Finn Williams6f9f9902020-11-13 13:23:15 +000090 armnn::IgnoreUnused(tfLiteContext);
Sadik Armagan62483be2020-10-23 17:14:43 +010091 if (buffer != nullptr)
92 {
93 delete static_cast<ArmnnSubgraph*>(buffer);
94 }
95 },
96 // ArmnnSubgraph Prepare
97 .prepare = [](TfLiteContext* tfLiteContext, TfLiteNode* tfLiteNode) -> TfLiteStatus {
98 if (tfLiteNode->user_data == nullptr)
99 {
100 return kTfLiteError;
101 }
Sadik Armagan62483be2020-10-23 17:14:43 +0100102 return static_cast<ArmnnSubgraph*>(tfLiteNode->user_data)->Prepare(tfLiteContext);
103 },
104 // ArmnnSubgraph Invoke
105 .invoke = [](TfLiteContext* tfLiteContext, TfLiteNode* tfLiteNode) -> TfLiteStatus {
106 if (tfLiteNode->user_data == nullptr)
107 {
108 return kTfLiteError;
109 }
110
111 return static_cast<ArmnnSubgraph*>(tfLiteNode->user_data)->Invoke(tfLiteContext, tfLiteNode);
112 },
113
114 .profiling_string = nullptr,
115 .builtin_code = kTfLiteBuiltinDelegate,
116 .custom_name = "TfLiteArmNnDelegate",
117 .version = 1,
118 };
119
120 const TfLiteStatus status =
121 tfLiteContext->ReplaceNodeSubsetsWithDelegateKernels(
122 tfLiteContext, kArmnnSubgraphRegistration, supportedOperators, tfLiteDelegate);
123
124 TfLiteIntArrayFree(supportedOperators);
125 return status;
126
127}
128
Sadik Armagan3c24f432020-10-19 17:35:30 +0100129Delegate::Delegate(armnnDelegate::DelegateOptions options)
130 : m_Runtime(nullptr, nullptr),
131 m_Options(std::move(options))
132{
Jan Eilers2cd18472020-12-15 10:42:38 +0000133 // Configures logging for ARMNN
134 if (options.IsLoggingEnabled())
135 {
136 armnn::ConfigureLogging(true, true, options.GetLoggingSeverity());
137 }
138
Sadik Armagan3c24f432020-10-19 17:35:30 +0100139 // Create ArmNN Runtime
140 armnn::IRuntime::CreationOptions runtimeOptions;
Colm Donelan3e32a872021-10-04 22:55:37 +0100141 runtimeOptions.m_DynamicBackendsPath = m_Options.GetDynamicBackendsPath();
142 runtimeOptions.m_EnableGpuProfiling = m_Options.GetGpuProfilingState();
143 runtimeOptions.m_ProfilingOptions = m_Options.GetExternalProfilingParams();
Sadik Armagan4189cc52020-11-11 18:01:48 +0000144
145 auto backendOptions = m_Options.GetBackendOptions();
146 if (!backendOptions.empty())
147 {
148 runtimeOptions.m_BackendOptions = backendOptions;
149 }
Narumol Prangnawarat0b51d5a2021-01-20 15:58:29 +0000150 else if (!m_Options.GetOptimizerOptions().m_ModelOptions.empty())
151 {
152 runtimeOptions.m_BackendOptions = m_Options.GetOptimizerOptions().m_ModelOptions;
153 }
Sadik Armagan3c24f432020-10-19 17:35:30 +0100154 m_Runtime = armnn::IRuntime::Create(runtimeOptions);
155
156 std::vector<armnn::BackendId> backends;
Sadik Armagan3c24f432020-10-19 17:35:30 +0100157 if (m_Runtime)
158 {
159 const armnn::BackendIdSet supportedDevices = m_Runtime->GetDeviceSpec().GetSupportedBackends();
160 for (auto& backend : m_Options.GetBackends())
161 {
162 if (std::find(supportedDevices.cbegin(), supportedDevices.cend(), backend) == supportedDevices.cend())
163 {
Sadik Armagan0534e032020-10-27 17:30:18 +0000164 TFLITE_LOG_PROD(tflite::TFLITE_LOG_INFO,
Sadik Armagan3c24f432020-10-19 17:35:30 +0100165 "TfLiteArmnnDelegate: Requested unknown backend %s", backend.Get().c_str());
166 }
167 else
168 {
169 backends.push_back(backend);
170 }
171 }
172 }
173
174 if (backends.empty())
175 {
176 // No known backend specified
177 throw armnn::InvalidArgumentException("TfLiteArmnnDelegate: No known backend specified.");
178 }
179 m_Options.SetBackends(backends);
180
181 TFLITE_LOG_PROD_ONCE(tflite::TFLITE_LOG_INFO, "TfLiteArmnnDelegate: Created TfLite ArmNN delegate.");
182}
183
Sadik Armagan62483be2020-10-23 17:14:43 +0100184TfLiteIntArray* Delegate::IdentifyOperatorsToDelegate(TfLiteContext* tfLiteContext)
Sadik Armagan3c24f432020-10-19 17:35:30 +0100185{
186 TfLiteIntArray* executionPlan = nullptr;
187 if (tfLiteContext->GetExecutionPlan(tfLiteContext, &executionPlan) != kTfLiteOk)
188 {
189 TF_LITE_KERNEL_LOG(tfLiteContext, "TfLiteArmnnDelegate: Unable to get graph execution plan.");
190 return nullptr;
191 }
192
Sadik Armagan62483be2020-10-23 17:14:43 +0100193 // Delegate data with null network
194 DelegateData delegateData(m_Options.GetBackends());
Sadik Armagan3c24f432020-10-19 17:35:30 +0100195
196 TfLiteIntArray* nodesToDelegate = TfLiteIntArrayCreate(executionPlan->size);
197 nodesToDelegate->size = 0;
198 for (int i = 0; i < executionPlan->size; ++i)
199 {
200 const int nodeIndex = executionPlan->data[i];
201
202 // If TfLite nodes can be delegated to ArmNN
203 TfLiteNode* tfLiteNode = nullptr;
204 TfLiteRegistration* tfLiteRegistration = nullptr;
205 if (tfLiteContext->GetNodeAndRegistration(
206 tfLiteContext, nodeIndex, &tfLiteNode, &tfLiteRegistration) != kTfLiteOk)
207 {
208 TF_LITE_KERNEL_LOG(tfLiteContext,
209 "TfLiteArmnnDelegate: Unable to get node and registration for node %d.",
210 nodeIndex);
211 continue;
212 }
213
214 if (ArmnnSubgraph::VisitNode(
Sadik Armagan62483be2020-10-23 17:14:43 +0100215 delegateData, tfLiteContext, tfLiteRegistration, tfLiteNode, nodeIndex) != kTfLiteOk)
Sadik Armagan3c24f432020-10-19 17:35:30 +0100216 {
217 // node is not supported by ArmNN
218 continue;
219 }
220
221 nodesToDelegate->data[nodesToDelegate->size++] = nodeIndex;
222 }
223
Sadik Armagan62483be2020-10-23 17:14:43 +0100224 std::sort(&nodesToDelegate->data[0], &nodesToDelegate->data[nodesToDelegate->size]);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100225 return nodesToDelegate;
226}
227
228TfLiteDelegate* Delegate::GetDelegate()
229{
230 return &m_Delegate;
231}
232
Matthew Sloyanac001ee2021-02-03 10:43:04 +0000233const std::string Delegate::GetVersion()
234{
235 return DELEGATE_VERSION;
236}
237
Sadik Armagan62483be2020-10-23 17:14:43 +0100238TfLiteStatus ArmnnSubgraph::AddInputLayer(DelegateData& delegateData,
239 TfLiteContext* tfLiteContext,
240 const TfLiteIntArray* inputs,
241 std::vector<armnn::BindingPointInfo>& inputBindings)
242{
Finn Williams6f9f9902020-11-13 13:23:15 +0000243 const size_t numInputs = static_cast<size_t>(inputs->size);
Sadik Armagan62483be2020-10-23 17:14:43 +0100244 for (unsigned int i = 0; i < numInputs; ++i)
245 {
246 const int32_t tensorId = inputs->data[i];
247 const TfLiteTensor tensor = tfLiteContext->tensors[tensorId];
Sadik Armagan6e36a642020-11-10 21:18:41 +0000248 // Do not create bindings for constant inputs
249 if (tensor.allocation_type == kTfLiteMmapRo)
250 {
251 continue;
252 }
Sadik Armagan62483be2020-10-23 17:14:43 +0100253
254 auto bindingId = static_cast<armnn::LayerBindingId>((tensorId));
255 armnn::IConnectableLayer* layer = delegateData.m_Network->AddInputLayer(bindingId);
256
257 auto tensorInfo = GetTensorInfoForTfLiteTensor(tensor);
258 armnn::IOutputSlot& outputSlot = layer->GetOutputSlot(0);
259 outputSlot.SetTensorInfo(tensorInfo);
260
261 // Store for creating connections
Finn Williams6f9f9902020-11-13 13:23:15 +0000262 delegateData.m_OutputSlotForNode[static_cast<unsigned long>(tensorId)] = &outputSlot;
Sadik Armagan62483be2020-10-23 17:14:43 +0100263
Sadik Armagan6e36a642020-11-10 21:18:41 +0000264 inputBindings.push_back(std::make_pair(bindingId, tensorInfo));
Sadik Armagan62483be2020-10-23 17:14:43 +0100265 }
Sadik Armagan6e36a642020-11-10 21:18:41 +0000266
Sadik Armagan62483be2020-10-23 17:14:43 +0100267 return kTfLiteOk;
268}
269
270TfLiteStatus ArmnnSubgraph::AddOutputLayer(DelegateData& delegateData,
271 TfLiteContext* tfLiteContext,
272 const TfLiteIntArray* outputs,
273 std::vector<armnn::BindingPointInfo>& outputBindings)
274{
Finn Williams6f9f9902020-11-13 13:23:15 +0000275 const size_t numOutputs = static_cast<size_t>(outputs->size);
Sadik Armagan62483be2020-10-23 17:14:43 +0100276 for (unsigned int i = 0; i < numOutputs; ++i)
277 {
278 const int32_t tensorId = outputs->data[i];
279 const TfLiteTensor tensor = tfLiteContext->tensors[tensorId];
280
281 auto bindingId = static_cast<armnn::LayerBindingId>((tensorId));
282 armnn::IConnectableLayer* layer = delegateData.m_Network->AddOutputLayer(bindingId);
283
284 auto tensorInfo = GetTensorInfoForTfLiteTensor(tensor);
Finn Williams6f9f9902020-11-13 13:23:15 +0000285 ARMNN_ASSERT(delegateData.m_OutputSlotForNode[static_cast<unsigned long>(tensorId)] != nullptr);
286 delegateData.m_OutputSlotForNode[static_cast<unsigned long>(tensorId)]->Connect(layer->GetInputSlot(0));
Sadik Armagan62483be2020-10-23 17:14:43 +0100287 outputBindings.push_back(std::make_pair(bindingId, tensorInfo));
288 }
289
290 return kTfLiteOk;
291}
292
Sadik Armagan3c24f432020-10-19 17:35:30 +0100293ArmnnSubgraph* ArmnnSubgraph::Create(TfLiteContext* tfLiteContext,
294 const TfLiteDelegateParams* parameters,
295 const Delegate* delegate)
296{
297 TfLiteIntArray* executionPlan;
298 if (tfLiteContext->GetExecutionPlan(tfLiteContext, &executionPlan) != kTfLiteOk)
299 {
300 return nullptr;
301 }
302
Sadik Armagan62483be2020-10-23 17:14:43 +0100303 // Initialize DelegateData holds network and output slots information
304 DelegateData delegateData(delegate->m_Options.GetBackends());
305
306 // Build ArmNN Network
Sadik Armagan3c24f432020-10-19 17:35:30 +0100307 armnn::NetworkOptions networkOptions = {};
308 armnn::NetworkId networkId;
Sadik Armagan62483be2020-10-23 17:14:43 +0100309 delegateData.m_Network = armnn::INetwork::Create(networkOptions);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100310
Sadik Armagan6e36a642020-11-10 21:18:41 +0000311 delegateData.m_OutputSlotForNode = std::vector<armnn::IOutputSlot*>(tfLiteContext->tensors_size, nullptr);
312
Sadik Armagan62483be2020-10-23 17:14:43 +0100313 std::vector<armnn::BindingPointInfo> inputBindings;
314 std::vector<armnn::BindingPointInfo> outputBindings;
315
316 // Add input layer
317 auto status = AddInputLayer(delegateData, tfLiteContext, parameters->input_tensors, inputBindings);
318 if (status != kTfLiteOk)
319 {
320 throw armnn::Exception("TfLiteArmnnDelegate: Unable to add Inputs to the network!");
321 }
322
323 // Parse TfLite delegate nodes to ArmNN
Sadik Armagan3c24f432020-10-19 17:35:30 +0100324 for (int i = 0; i < parameters->nodes_to_replace->size; ++i)
325 {
326 const int nodeIndex = parameters->nodes_to_replace->data[i];
327
328 TfLiteNode* tfLiteNode = nullptr;
329 TfLiteRegistration* tfLiteRegistration = nullptr;
330 if (tfLiteContext->GetNodeAndRegistration(
331 tfLiteContext, nodeIndex, &tfLiteNode, &tfLiteRegistration) != kTfLiteOk)
332 {
Finn Williams6f9f9902020-11-13 13:23:15 +0000333 throw armnn::Exception(&"TfLiteArmnnDelegate: Unable to get node registration: " [ nodeIndex]);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100334 }
335
Sadik Armagan62483be2020-10-23 17:14:43 +0100336 if (VisitNode(delegateData, tfLiteContext, tfLiteRegistration, tfLiteNode, nodeIndex) != kTfLiteOk)
Sadik Armagan3c24f432020-10-19 17:35:30 +0100337 {
Finn Williams6f9f9902020-11-13 13:23:15 +0000338 throw armnn::Exception(&"TfLiteArmnnDelegate: Unable to parse node: " [ nodeIndex]);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100339 }
340 }
341
Sadik Armagan62483be2020-10-23 17:14:43 +0100342 // Add Output layer
343 status = AddOutputLayer(delegateData, tfLiteContext, parameters->output_tensors, outputBindings);
344 if (status != kTfLiteOk)
345 {
346 throw armnn::Exception("TfLiteArmnnDelegate: Unable to add Outputs to the network!");
347 }
348
349 // Optimize ArmNN network
350 armnn::IOptimizedNetworkPtr optNet(nullptr, nullptr);
351 try
352 {
Sadik Armagan6e36a642020-11-10 21:18:41 +0000353 optNet = armnn::Optimize(*(delegateData.m_Network.get()),
Sadik Armagan62483be2020-10-23 17:14:43 +0100354 delegate->m_Options.GetBackends(),
Narumol Prangnawarat0b51d5a2021-01-20 15:58:29 +0000355 delegate->m_Runtime->GetDeviceSpec(),
356 delegate->m_Options.GetOptimizerOptions());
Sadik Armagan62483be2020-10-23 17:14:43 +0100357 }
358 catch (std::exception &ex)
359 {
360 std::stringstream exMessage;
361 exMessage << "TfLiteArmnnDelegate: Exception (" << ex.what() << ") caught from optimize.";
362 throw armnn::Exception(exMessage.str());
363 }
Sadik Armagan3c24f432020-10-19 17:35:30 +0100364 if (!optNet)
365 {
Sadik Armagan62483be2020-10-23 17:14:43 +0100366 // Optimize failed
Sadik Armagan3c24f432020-10-19 17:35:30 +0100367 throw armnn::Exception("TfLiteArmnnDelegate: Unable to optimize the network!");
368 }
Sadik Armagan62483be2020-10-23 17:14:43 +0100369
Colm Donelan3e32a872021-10-04 22:55:37 +0100370 // If set, we will serialize the optimized model into a dot file.
371 const std::string serializeToDotFile = delegate->m_Options.GetSerializeToDot();
372 if (!serializeToDotFile.empty())
373 {
374 fs::path filename = serializeToDotFile;
375 std::fstream file(filename.c_str(), std::ios_base::out);
376 optNet->SerializeToDot(file);
377 }
378
Sadik Armagan62483be2020-10-23 17:14:43 +0100379 try
380 {
381 // Load graph into runtime
Narumol Prangnawarat0b51d5a2021-01-20 15:58:29 +0000382 std::string errorMessage;
Narumol Prangnawarat74a3cf52021-01-29 15:38:54 +0000383 armnn::Status loadingStatus;
Colm Donelan3e32a872021-10-04 22:55:37 +0100384 armnn::MemorySource memorySource = armnn::MemorySource::Undefined;
Narumol Prangnawarat74a3cf52021-01-29 15:38:54 +0000385 if (delegate->m_Options.GetOptimizerOptions().m_ImportEnabled)
386 {
Colm Donelan3e32a872021-10-04 22:55:37 +0100387 memorySource = armnn::MemorySource::Malloc;
Narumol Prangnawarat74a3cf52021-01-29 15:38:54 +0000388 }
Colm Donelan3e32a872021-10-04 22:55:37 +0100389 armnn::INetworkProperties networkProperties(false,
390 memorySource,
391 memorySource,
392 delegate->m_Options.GetInternalProfilingState(),
393 delegate->m_Options.GetInternalProfilingDetail());
394 loadingStatus = delegate->m_Runtime->LoadNetwork(networkId,
395 std::move(optNet),
396 errorMessage,
397 networkProperties);
Sadik Armagan62483be2020-10-23 17:14:43 +0100398 if (loadingStatus != armnn::Status::Success)
399 {
Colm Donelan45142282021-10-21 23:39:52 +0100400 // Network load failed.
Narumol Prangnawarat0b51d5a2021-01-20 15:58:29 +0000401 throw armnn::Exception("TfLiteArmnnDelegate: Network could not be loaded:" + errorMessage);
Sadik Armagan62483be2020-10-23 17:14:43 +0100402 }
403 }
404 catch (std::exception& ex)
405 {
406 std::stringstream exMessage;
407 exMessage << "TfLiteArmnnDelegate: Exception (" << ex.what() << ") caught from LoadNetwork.";
408 throw armnn::Exception(exMessage.str());
409 }
Sadik Armagan3c24f432020-10-19 17:35:30 +0100410
Narumol Prangnawarat0b51d5a2021-01-20 15:58:29 +0000411 // Register debug callback function
412 if (delegate->m_Options.GetDebugCallbackFunction().has_value())
413 {
414 delegate->m_Runtime->RegisterDebugCallback(networkId, delegate->m_Options.GetDebugCallbackFunction().value());
415 }
416
Sadik Armagan3c24f432020-10-19 17:35:30 +0100417 // Create a new SubGraph with networkId and runtime
Sadik Armagan62483be2020-10-23 17:14:43 +0100418 return new ArmnnSubgraph(networkId, delegate->m_Runtime.get(), inputBindings, outputBindings);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100419}
420
421TfLiteStatus ArmnnSubgraph::Prepare(TfLiteContext* tfLiteContext)
422{
Finn Williams6f9f9902020-11-13 13:23:15 +0000423 armnn::IgnoreUnused(tfLiteContext);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100424 return kTfLiteOk;
425}
426
Sadik Armagan62483be2020-10-23 17:14:43 +0100427TfLiteStatus ArmnnSubgraph::Invoke(TfLiteContext* tfLiteContext, TfLiteNode* tfLiteNode)
Sadik Armagan3c24f432020-10-19 17:35:30 +0100428{
Sadik Armagan62483be2020-10-23 17:14:43 +0100429 // Prepare inputs
430 armnn::InputTensors inputTensors;
431 size_t inputIndex = 0;
432 for (auto inputIdx : tflite::TfLiteIntArrayView(tfLiteNode->inputs))
433 {
434 TfLiteTensor* tensor = &tfLiteContext->tensors[inputIdx];
435 if (tensor->allocation_type != kTfLiteMmapRo)
436 {
437 const armnn::BindingPointInfo& inputBinding = m_InputBindings[inputIndex];
438 const armnn::ConstTensor inputTensor(inputBinding.second, tensor->data.data);
439 inputTensors.emplace_back(inputIdx, inputTensor);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100440
Sadik Armagan62483be2020-10-23 17:14:43 +0100441 ++inputIndex;
442 }
443 }
444
445 // Prepare outputs
446 armnn::OutputTensors outputTensors;
447 size_t outputIndex = 0;
448 for (auto outputIdx : tflite::TfLiteIntArrayView(tfLiteNode->outputs))
449 {
450 const armnn::BindingPointInfo& outputBinding = m_OutputBindings[outputIndex];
451 TfLiteTensor* tensor = &tfLiteContext->tensors[outputIdx];
452 const armnn::Tensor outputTensor(outputBinding.second, tensor->data.data);
453 outputTensors.emplace_back(outputIdx, outputTensor);
454
455 ++outputIndex;
456 }
457
458 // Run graph
459 auto status = m_Runtime->EnqueueWorkload(m_NetworkId, inputTensors, outputTensors);
Colm Donelan45142282021-10-21 23:39:52 +0100460 // The delegate holds its own Arm NN runtime so this is our last chance to print internal profiling data.
461 std::shared_ptr<armnn::IProfiler> profiler = m_Runtime->GetProfiler(m_NetworkId);
462 if (profiler && profiler->IsProfilingEnabled())
463 {
464 profiler->Print(std::cout);
465 }
Sadik Armagan62483be2020-10-23 17:14:43 +0100466 return (status == armnn::Status::Success) ? kTfLiteOk : kTfLiteError;
Sadik Armagan3c24f432020-10-19 17:35:30 +0100467}
468
Sadik Armagan62483be2020-10-23 17:14:43 +0100469TfLiteStatus ArmnnSubgraph::VisitNode(DelegateData& delegateData,
Sadik Armagan3c24f432020-10-19 17:35:30 +0100470 TfLiteContext* tfLiteContext,
471 TfLiteRegistration* tfLiteRegistration,
472 TfLiteNode* tfLiteNode,
473 int nodeIndex)
474{
Sadik Armagan62483be2020-10-23 17:14:43 +0100475 switch (tfLiteRegistration->builtin_code)
476 {
477 case kTfLiteBuiltinAbs:
478 return VisitElementwiseUnaryOperator(delegateData,
479 tfLiteContext,
480 tfLiteNode,
481 nodeIndex,
482 armnn::UnaryOperation::Abs);
483 case kTfLiteBuiltinAdd:
484 return VisitElementwiseBinaryOperator(delegateData,
485 tfLiteContext,
486 tfLiteNode,
487 nodeIndex,
488 kTfLiteBuiltinAdd);
489 case kTfLiteBuiltinArgMax:
490 return VisitArgMinMaxOperator(delegateData,
491 tfLiteContext,
492 tfLiteNode,
493 nodeIndex,
494 kTfLiteBuiltinArgMax);
495 case kTfLiteBuiltinArgMin:
496 return VisitArgMinMaxOperator(delegateData,
497 tfLiteContext,
498 tfLiteNode,
499 nodeIndex,
500 kTfLiteBuiltinArgMin);
501 case kTfLiteBuiltinAveragePool2d:
502 return VisitPoolingOperator(delegateData,
503 tfLiteContext,
504 tfLiteNode,
505 nodeIndex,
506 kTfLiteBuiltinAveragePool2d);
507 case kTfLiteBuiltinBatchToSpaceNd:
508 return VisitBatchToSpaceNdOperator(delegateData,
509 tfLiteContext,
510 tfLiteNode,
511 nodeIndex,
512 kTfLiteBuiltinBatchToSpaceNd);
Sadik Armagan937565b2021-04-21 14:03:28 +0100513 case kTfLiteBuiltinCast:
514 return VisitCastOperator(delegateData,
515 tfLiteContext,
516 tfLiteNode,
517 nodeIndex,
518 kTfLiteBuiltinCast);
Sadik Armagan62483be2020-10-23 17:14:43 +0100519 case kTfLiteBuiltinConcatenation:
520 return VisitControlOperator(delegateData,
521 tfLiteContext,
522 tfLiteNode,
523 nodeIndex,
524 kTfLiteBuiltinConcatenation);
525 case kTfLiteBuiltinConv2d:
526 return VisitConvolutionOperator(delegateData,
527 tfLiteContext,
528 tfLiteNode,
529 nodeIndex,
530 kTfLiteBuiltinConv2d);
Matthew Sloyan81ec9942021-10-12 10:26:30 +0100531// Conv3d is only correctly supported for external delegates from TF Lite v2.6, as there was a breaking bug in v2.5.
532#if defined(ARMNN_POST_TFLITE_2_5)
533 case kTfLiteBuiltinConv3d:
534 return VisitConvolutionOperator(delegateData,
535 tfLiteContext,
536 tfLiteNode,
537 nodeIndex,
538 kTfLiteBuiltinConv3d);
539#endif
Sadik Armagan62483be2020-10-23 17:14:43 +0100540 case kTfLiteBuiltinDepthToSpace:
541 return VisitDepthToSpaceOperator(delegateData,
542 tfLiteContext,
543 tfLiteNode,
544 nodeIndex,
545 kTfLiteBuiltinDepthToSpace);
546 case kTfLiteBuiltinDepthwiseConv2d:
547 return VisitConvolutionOperator(delegateData,
548 tfLiteContext,
549 tfLiteNode,
550 nodeIndex,
551 kTfLiteBuiltinDepthwiseConv2d);
552 case kTfLiteBuiltinDequantize:
553 return VisitDequantizeOperator(delegateData,
554 tfLiteContext,
555 tfLiteNode,
556 nodeIndex,
557 kTfLiteBuiltinDequantize);
558 case kTfLiteBuiltinDiv:
559 return VisitElementwiseBinaryOperator(delegateData,
560 tfLiteContext,
561 tfLiteNode,
562 nodeIndex,
563 kTfLiteBuiltinDiv);
564 case kTfLiteBuiltinElu:
565 return VisitActivationOperator(delegateData,
566 tfLiteContext,
567 tfLiteNode,
568 nodeIndex,
569 kTfLiteBuiltinElu);
570 case kTfLiteBuiltinEqual:
571 return VisitComparisonOperator(delegateData,
572 tfLiteContext,
573 tfLiteNode,
574 nodeIndex,
575 kTfLiteBuiltinEqual);
576 case kTfLiteBuiltinExp:
577 return VisitElementwiseUnaryOperator(delegateData,
578 tfLiteContext,
579 tfLiteNode,
580 nodeIndex,
581 armnn::UnaryOperation::Exp);
582 case kTfLiteBuiltinExpandDims:
583 return VisitExpandDimsOperator(delegateData,
584 tfLiteContext,
585 tfLiteNode,
586 nodeIndex,
587 kTfLiteBuiltinExpandDims);
588 case kTfLiteBuiltinFill:
589 return VisitFillOperator(delegateData,
590 tfLiteContext,
591 tfLiteNode,
592 nodeIndex,
593 kTfLiteBuiltinFill);
594 case kTfLiteBuiltinFloor:
595 return VisitFloorOperator(delegateData,
596 tfLiteContext,
597 tfLiteNode,
598 nodeIndex,
599 kTfLiteBuiltinFloor);
600 case kTfLiteBuiltinFullyConnected:
601 return VisitFullyConnectedOperator(delegateData,
602 tfLiteContext,
603 tfLiteNode,
604 nodeIndex,
605 kTfLiteBuiltinFullyConnected);
606 case kTfLiteBuiltinGather:
607 return VisitGatherOperator(delegateData,
608 tfLiteContext,
609 tfLiteNode,
610 nodeIndex,
611 kTfLiteBuiltinGather);
612 case kTfLiteBuiltinGatherNd:
613 return VisitGatherOperator(delegateData,
614 tfLiteContext,
615 tfLiteNode,
616 nodeIndex,
617 kTfLiteBuiltinGatherNd);
618 case kTfLiteBuiltinGreater:
619 return VisitComparisonOperator(delegateData,
620 tfLiteContext,
621 tfLiteNode,
622 nodeIndex,
623 kTfLiteBuiltinGreater);
624 case kTfLiteBuiltinGreaterEqual:
625 return VisitComparisonOperator(delegateData,
626 tfLiteContext,
627 tfLiteNode,
628 nodeIndex,
629 kTfLiteBuiltinGreaterEqual);
630 case kTfLiteBuiltinHardSwish:
631 return VisitActivationOperator(delegateData,
632 tfLiteContext,
633 tfLiteNode,
634 nodeIndex,
635 kTfLiteBuiltinHardSwish);
636 case kTfLiteBuiltinL2Normalization:
Sadik Armagan4b227bb2021-01-22 10:53:38 +0000637 return VisitL2NormalizationOperator(delegateData,
638 tfLiteContext,
639 tfLiteNode,
640 nodeIndex,
641 kTfLiteBuiltinL2Normalization);
Sadik Armagan62483be2020-10-23 17:14:43 +0100642 case kTfLiteBuiltinL2Pool2d:
643 return VisitPoolingOperator(delegateData,
644 tfLiteContext,
645 tfLiteNode,
646 nodeIndex,
647 kTfLiteBuiltinL2Pool2d);
648 case kTfLiteBuiltinLess:
649 return VisitComparisonOperator(delegateData,
650 tfLiteContext,
651 tfLiteNode,
652 nodeIndex,
653 kTfLiteBuiltinLess);
654 case kTfLiteBuiltinLessEqual:
655 return VisitComparisonOperator(delegateData,
656 tfLiteContext,
657 tfLiteNode,
658 nodeIndex,
659 kTfLiteBuiltinLessEqual);
660 case kTfLiteBuiltinLocalResponseNormalization:
Sadik Armagan4b227bb2021-01-22 10:53:38 +0000661 return VisitLocalResponseNormalizationOperator(delegateData,
662 tfLiteContext,
663 tfLiteNode,
664 nodeIndex,
665 kTfLiteBuiltinLocalResponseNormalization);
Matthew Sloyanc8eb9552020-11-26 10:54:22 +0000666 case kTfLiteBuiltinLogicalAnd:
667 return VisitLogicalBinaryOperator(delegateData,
668 tfLiteContext,
669 tfLiteNode,
670 nodeIndex,
671 kTfLiteBuiltinLogicalAnd,
672 armnn::LogicalBinaryOperation::LogicalAnd);
673 case kTfLiteBuiltinLogicalNot:
674 return VisitElementwiseUnaryOperator(delegateData,
675 tfLiteContext,
676 tfLiteNode,
677 nodeIndex,
678 armnn::UnaryOperation::LogicalNot);
679 case kTfLiteBuiltinLogicalOr:
680 return VisitLogicalBinaryOperator(delegateData,
681 tfLiteContext,
682 tfLiteNode,
683 nodeIndex,
684 kTfLiteBuiltinLogicalOr,
685 armnn::LogicalBinaryOperation::LogicalOr);
Sadik Armagan62483be2020-10-23 17:14:43 +0100686 case kTfLiteBuiltinLogistic:
687 return VisitActivationOperator(delegateData,
688 tfLiteContext,
689 tfLiteNode,
690 nodeIndex,
691 kTfLiteBuiltinLogistic);
692 case kTfLiteBuiltinLogSoftmax:
693 return VisitSoftmaxOperator(delegateData,
694 tfLiteContext,
695 tfLiteNode,
696 nodeIndex,
697 kTfLiteBuiltinLogSoftmax);
698 case kTfLiteBuiltinLstm:
699 return VisitLstmOperator(delegateData,
700 tfLiteContext,
701 tfLiteNode,
702 nodeIndex,
703 kTfLiteBuiltinLstm);
704 case kTfLiteBuiltinMaxPool2d:
705 return VisitPoolingOperator(delegateData,
706 tfLiteContext,
707 tfLiteNode,
708 nodeIndex,
709 kTfLiteBuiltinMaxPool2d);
710 case kTfLiteBuiltinMaximum:
711 return VisitElementwiseBinaryOperator(delegateData,
712 tfLiteContext,
713 tfLiteNode,
714 nodeIndex,
715 kTfLiteBuiltinMaximum);
716 case kTfLiteBuiltinMean:
717 return VisitControlOperator(delegateData,
718 tfLiteContext,
719 tfLiteNode,
720 nodeIndex,
721 kTfLiteBuiltinMean);
722 case kTfLiteBuiltinMinimum:
723 return VisitElementwiseBinaryOperator(delegateData,
724 tfLiteContext,
725 tfLiteNode,
726 nodeIndex,
727 kTfLiteBuiltinMinimum);
728 case kTfLiteBuiltinMul:
729 return VisitElementwiseBinaryOperator(delegateData,
730 tfLiteContext,
731 tfLiteNode,
732 nodeIndex,
733 kTfLiteBuiltinMul);
734 case kTfLiteBuiltinNeg:
735 return VisitElementwiseUnaryOperator(delegateData,
736 tfLiteContext,
737 tfLiteNode,
738 nodeIndex,
739 armnn::UnaryOperation::Neg);
740 case kTfLiteBuiltinNotEqual:
741 return VisitComparisonOperator(delegateData,
742 tfLiteContext,
743 tfLiteNode,
744 nodeIndex,
745 kTfLiteBuiltinNotEqual);
Matthew Sloyana7a12f52021-05-06 10:05:28 +0100746 case kTfLiteBuiltinPack:
747 return VisitPackOperator(delegateData,
748 tfLiteContext,
749 tfLiteNode,
750 nodeIndex,
751 kTfLiteBuiltinPack);
Sadik Armagan62483be2020-10-23 17:14:43 +0100752 case kTfLiteBuiltinPad:
753 return VisitPadOperator(delegateData,
754 tfLiteContext,
755 tfLiteNode,
756 nodeIndex,
757 kTfLiteBuiltinPad);
758 case kTfLiteBuiltinPadv2:
759 return VisitPadOperator(delegateData,
760 tfLiteContext,
761 tfLiteNode,
762 nodeIndex,
763 kTfLiteBuiltinPadv2);
764 case kTfLiteBuiltinPrelu:
James Conroy39825482021-05-27 17:44:50 +0100765 return VisitPreluOperator(delegateData,
766 tfLiteContext,
767 tfLiteNode,
768 nodeIndex,
769 kTfLiteBuiltinPrelu);
Sadik Armagan62483be2020-10-23 17:14:43 +0100770 case kTfLiteBuiltinQuantize:
771 return VisitQuantizeOperator(delegateData,
772 tfLiteContext,
773 tfLiteNode,
774 nodeIndex,
775 kTfLiteBuiltinQuantize);
776 case kTfLiteBuiltinRank:
777 return VisitControlOperator(delegateData,
778 tfLiteContext,
779 tfLiteNode,
780 nodeIndex,
781 kTfLiteBuiltinRank);
Sadik Armagana2747482021-02-09 10:28:54 +0000782 case kTfLiteBuiltinReduceMax:
783 return VisitReduceOperator(delegateData,
784 tfLiteContext,
785 tfLiteNode,
786 nodeIndex,
787 kTfLiteBuiltinReduceMax);
788 case kTfLiteBuiltinReduceMin:
789 return VisitReduceOperator(delegateData,
790 tfLiteContext,
791 tfLiteNode,
792 nodeIndex,
793 kTfLiteBuiltinReduceMin);
Teresa Charlin4e3e8312021-08-05 12:34:37 +0100794 case kTfLiteBuiltinReduceProd:
795 return VisitReduceOperator(delegateData,
796 tfLiteContext,
797 tfLiteNode,
798 nodeIndex,
799 kTfLiteBuiltinReduceProd);
Sadik Armagan62483be2020-10-23 17:14:43 +0100800 case kTfLiteBuiltinRelu:
801 return VisitActivationOperator(delegateData,
802 tfLiteContext,
803 tfLiteNode,
804 nodeIndex,
805 kTfLiteBuiltinRelu);
806 case kTfLiteBuiltinReluN1To1:
807 return VisitActivationOperator(delegateData,
808 tfLiteContext,
809 tfLiteNode,
810 nodeIndex,
811 kTfLiteBuiltinReluN1To1);
812 case kTfLiteBuiltinRelu6:
813 return VisitActivationOperator(delegateData,
814 tfLiteContext,
815 tfLiteNode,
816 nodeIndex,
817 kTfLiteBuiltinRelu6);
818 case kTfLiteBuiltinReshape:
819 return VisitReshapeOperator(delegateData,
820 tfLiteContext,
821 tfLiteNode,
822 nodeIndex,
823 kTfLiteBuiltinReshape);
824 case kTfLiteBuiltinResizeBilinear:
825 return VisitResizeOperator(delegateData,
826 tfLiteContext,
827 tfLiteNode,
828 nodeIndex,
829 kTfLiteBuiltinResizeBilinear);
830 case kTfLiteBuiltinResizeNearestNeighbor:
831 return VisitResizeOperator(delegateData,
832 tfLiteContext,
833 tfLiteNode,
834 nodeIndex,
835 kTfLiteBuiltinResizeNearestNeighbor);
836 case kTfLiteBuiltinRsqrt:
837 return VisitElementwiseUnaryOperator(delegateData,
838 tfLiteContext,
839 tfLiteNode,
840 nodeIndex,
841 armnn::UnaryOperation::Rsqrt);
Keith Davis0176fd82021-06-01 17:36:32 +0100842 case kTfLiteBuiltinShape:
843 return VisitShapeOperator(delegateData,
844 tfLiteContext,
845 tfLiteNode,
846 nodeIndex,
847 kTfLiteBuiltinShape);
Sadik Armagan34fa1bd2020-11-27 12:40:52 +0000848 case kTfLiteBuiltinSplit:
849 return VisitSplitOperator(delegateData,
850 tfLiteContext,
851 tfLiteNode,
852 nodeIndex,
853 kTfLiteBuiltinSplit);
854 case kTfLiteBuiltinSplitV:
855 return VisitSplitVOperator(delegateData,
856 tfLiteContext,
857 tfLiteNode,
858 nodeIndex,
859 kTfLiteBuiltinSplitV);
Sadik Armagan62483be2020-10-23 17:14:43 +0100860 case kTfLiteBuiltinSqrt:
861 return VisitElementwiseUnaryOperator(delegateData,
862 tfLiteContext,
863 tfLiteNode,
864 nodeIndex,
865 armnn::UnaryOperation::Sqrt);
866 case kTfLiteBuiltinSqueeze:
867 return VisitSqueezeOperator(delegateData,
868 tfLiteContext,
869 tfLiteNode,
870 nodeIndex,
871 kTfLiteBuiltinSqueeze);
872 case kTfLiteBuiltinStridedSlice:
873 return VisitSliceOperator(delegateData,
874 tfLiteContext,
875 tfLiteNode,
876 nodeIndex,
877 kTfLiteBuiltinStridedSlice);
Sadik Armagana2747482021-02-09 10:28:54 +0000878 case kTfLiteBuiltinSum:
879 return VisitReduceOperator(delegateData,
880 tfLiteContext,
881 tfLiteNode,
882 nodeIndex,
883 kTfLiteBuiltinSum);
Sadik Armagan62483be2020-10-23 17:14:43 +0100884 case kTfLiteBuiltinTranspose:
885 return VisitTransposeOperator(delegateData,
886 tfLiteContext,
887 tfLiteNode,
888 nodeIndex,
889 kTfLiteBuiltinTranspose);
890 case kTfLiteBuiltinTransposeConv:
891 return VisitConvolutionOperator(delegateData,
892 tfLiteContext,
893 tfLiteNode,
894 nodeIndex,
895 kTfLiteBuiltinTransposeConv);
896 case kTfLiteBuiltinSoftmax:
897 return VisitSoftmaxOperator(delegateData,
898 tfLiteContext,
899 tfLiteNode,
900 nodeIndex,
901 kTfLiteBuiltinSoftmax);
902 case kTfLiteBuiltinSpaceToBatchNd:
903 return VisitSpaceToBatchNdOperator(delegateData,
904 tfLiteContext,
905 tfLiteNode,
906 nodeIndex,
907 kTfLiteBuiltinSpaceToBatchNd);
908 case kTfLiteBuiltinSpaceToDepth:
909 return VisitSpaceToDepthOperator(delegateData,
910 tfLiteContext,
911 tfLiteNode,
912 nodeIndex,
913 kTfLiteBuiltinSpaceToDepth);
914 case kTfLiteBuiltinSub:
915 return VisitElementwiseBinaryOperator(delegateData,
916 tfLiteContext,
917 tfLiteNode,
918 nodeIndex,
919 kTfLiteBuiltinSub);
920 case kTfLiteBuiltinTanh:
921 return VisitActivationOperator(delegateData,
922 tfLiteContext,
923 tfLiteNode,
924 nodeIndex,
925 kTfLiteBuiltinTanh);
Narumol Prangnawarat7684b182021-08-12 14:48:15 +0100926 case kTfLiteBuiltinUnidirectionalSequenceLstm:
927 return VisitUnidirectionalSequenceLstmOperator(delegateData,
928 tfLiteContext,
929 tfLiteNode,
930 nodeIndex,
931 kTfLiteBuiltinUnidirectionalSequenceLstm);
Kevin May8ab2d7a2021-05-07 09:32:51 +0100932 case kTfLiteBuiltinUnpack:
933 return VisitUnpackOperator(delegateData,
934 tfLiteContext,
935 tfLiteNode,
936 nodeIndex,
937 kTfLiteBuiltinUnpack);
Sadik Armagan62483be2020-10-23 17:14:43 +0100938 default:
939 return kTfLiteError;
940 }
Sadik Armagan3c24f432020-10-19 17:35:30 +0100941}
942
943} // armnnDelegate namespace