blob: 53b17256af85f16d9a94e377d574fee6fa849acb [file] [log] [blame]
Jan Eilers2cd18472020-12-15 10:42:38 +00001//
2// Copyright © 2020 Arm Ltd and Contributors. All rights reserved.
3// SPDX-License-Identifier: MIT
4//
5#include "armnn_delegate.hpp"
6#include <armnn/Logging.hpp>
7
8#include <iostream>
9#include <tensorflow/lite/minimal_logging.h>
10
11namespace tflite
12{
13
14/**
15 * This file defines two symbols that need to be exported to use the TFLite external delegate provider. This is a plugin
16 * that can be used for fast integration of delegates into benchmark tests and other tools. It allows loading of
17 * a dynamic delegate library at runtime.
18 *
19 * The external delegate also has Tensorflow Lite Python bindings. Therefore the dynamic external delegate
20 * can be directly used with Tensorflow Lite Python APIs.
21 *
22 * See tensorflow/lite/delegates/external for details or visit the tensorflow guide
23 * [here](https://www.tensorflow.org/lite/performance/implementing_delegate#option_2_leverage_external_delegate)
24 */
25
26extern "C"
27{
28std::vector<std::string> gpu_options {"gpu-tuning-level",
29 "gpu-tuning-file",
30 "gpu-kernel-profiling-enabled"};
31
32
33/**
34 * Create an ArmNN delegate plugin
35 *
36 * Available options:
37 *
38 * Option key: "backends" \n
39 * Possible values: ["EthosNPU"/"GpuAcc"/"CpuAcc"/"CpuRef"] \n
40 * Descriptions: A comma separated list without whitespaces of
41 * backends which should be used for execution. Falls
42 * back to next backend in list if previous doesn't
43 * provide support for operation. e.g. "GpuAcc,CpuAcc"
44 *
45 * Option key: "logging-severity" \n
46 * Possible values: ["trace"/"debug"/"info"/"warning"/"error"/"fatal"] \n
47 * Description: Sets the logging severity level for ArmNN. Logging
48 * is turned off if this option is not provided.
49 *
50 * Option key: "gpu-tuning-level" \n
51 * Possible values: ["0"/"1"/"2"/"3"] \n
52 * Description: 0=UseOnly(default), 1=RapidTuning, 2=NormalTuning,
53 * 3=ExhaustiveTuning. Requires option gpu-tuning-file.
54 * 1,2 and 3 will create a tuning-file, 0 will apply the
55 * tunings from an existing file
56 *
57 * Option key: "gpu-tuning-file" \n
58 * Possible values: [filenameString] \n
59 * Description: File name for the tuning file.
60 *
61 * Option key: "gpu-kernel-profiling-enabled" \n
62 * Possible values: ["true"/"false"] \n
63 * Description: Enables GPU kernel profiling
64 *
65 *
66 * @param[in] option_keys Delegate option names
67 * @param[in] options_values Delegate option values
68 * @param[in] num_options Number of delegate options
69 * @param[in,out] report_error Error callback function
70 *
71 * @return An ArmNN delegate if it succeeds else NULL
72 */
73TfLiteDelegate* tflite_plugin_create_delegate(char** options_keys,
74 char** options_values,
75 size_t num_options,
76 void (*report_error)(const char*))
77{
78 // Returning null indicates an error during delegate creation so we initialize with that
79 TfLiteDelegate* delegate = nullptr;
80 try
81 {
82 // (Initializes with CpuRef backend)
83 armnnDelegate::DelegateOptions options = armnnDelegate::TfLiteArmnnDelegateOptionsDefault();
84 for (size_t i = 0; i < num_options; ++i)
85 {
86 // Process backends
87 if (std::string(options_keys[i]) == std::string("backends"))
88 {
89 // The backend option is a comma separated string of backendIDs that needs to be split
90 std::vector<armnn::BackendId> backends;
91 char* pch;
92 pch = strtok(options_values[i],",");
93 while (pch != NULL)
94 {
95 backends.push_back(pch);
96 pch = strtok (NULL, ",");
97 }
98 options.SetBackends(backends);
99 }
100 // Process logging level
101 else if (std::string(options_keys[i]) == std::string("logging-severity"))
102 {
103 options.SetLoggingSeverity(options_values[i]);
104 }
105 // Process GPU backend options
106 else if (std::string(options_keys[i]) == std::string("gpu-tuning-level"))
107 {
108 armnn::BackendOptions option("GpuAcc", {{"TuningLevel", atoi(options_values[i])}});
109 options.AddBackendOption(option);
110 }
111 else if (std::string(options_keys[i]) == std::string("gpu-tuning-file"))
112 {
113 armnn::BackendOptions option("GpuAcc", {{"TuningFile", std::string(options_values[i])}});
114 options.AddBackendOption(option);
115 }
116 else if (std::string(options_keys[i]) == std::string("gpu-kernel-profiling-enabled"))
117 {
118 armnn::BackendOptions option("GpuAcc", {{"KernelProfilingEnabled", (*options_values[i] != '0')}});
119 options.AddBackendOption(option);
120 }
121 else
122 {
123 throw armnn::Exception("Unknown option for the ArmNN Delegate given: " + std::string(options_keys[i]));
124 }
125 }
126 delegate = TfLiteArmnnDelegateCreate(options);
127 }
128 catch (const std::exception& ex)
129 {
130 if(report_error)
131 {
132 report_error(ex.what());
133 }
134 }
135 return delegate;
136}
137
138/** Destroy a given delegate plugin
139 *
140 * @param[in] delegate Delegate to destruct
141 */
142void tflite_plugin_destroy_delegate(TfLiteDelegate* delegate)
143{
144 armnnDelegate::TfLiteArmnnDelegateDelete(delegate);
145}
146
147} // extern "C"
148} // namespace tflite