xref: /aosp_15_r20/external/armnn/src/backends/README.md (revision 89c4ff92f2867872bb9e2354d150bf0c8c502810)
1*89c4ff92SAndroid Build Coastguard Worker# Backend developer guide
2*89c4ff92SAndroid Build Coastguard Worker
3*89c4ff92SAndroid Build Coastguard WorkerArm NN allows adding new backends through the 'Pluggable Backend' mechanism.
4*89c4ff92SAndroid Build Coastguard Worker
5*89c4ff92SAndroid Build Coastguard Worker## How to add a new backend
6*89c4ff92SAndroid Build Coastguard Worker
7*89c4ff92SAndroid Build Coastguard WorkerBackends reside under [src/backends](./), in separate subfolders. For Linux builds they must have a ```backend.cmake``` file,
8*89c4ff92SAndroid Build Coastguard Workerwhich is read automatically by [src/backends/backends.cmake](backends.cmake). The ```backend.cmake``` file
9*89c4ff92SAndroid Build Coastguard Workerunder the backend-specific folder is then included by the main CMakeLists.txt file at the root of the
10*89c4ff92SAndroid Build Coastguard WorkerArm NN source tree.
11*89c4ff92SAndroid Build Coastguard Worker
12*89c4ff92SAndroid Build Coastguard Worker### The backend.cmake file
13*89c4ff92SAndroid Build Coastguard Worker
14*89c4ff92SAndroid Build Coastguard WorkerThe ```backend.cmake``` has three main purposes:
15*89c4ff92SAndroid Build Coastguard Worker
16*89c4ff92SAndroid Build Coastguard Worker1. It makes sure the artifact (a cmake OBJECT library) is linked into the Arm NN shared library by appending the name of the library to the ```armnnLibraries``` list.
17*89c4ff92SAndroid Build Coastguard Worker2. It makes sure that the subdirectory where backend sources reside gets included into the build.
18*89c4ff92SAndroid Build Coastguard Worker3. To include backend-specific unit tests, the object library for the unit tests needs to be added to the ```armnnUnitTestLibraries``` list.
19*89c4ff92SAndroid Build Coastguard Worker
20*89c4ff92SAndroid Build Coastguard WorkerExample ```backend.cmake``` file taken from [reference/backend.cmake](reference/backend.cmake):
21*89c4ff92SAndroid Build Coastguard Worker
22*89c4ff92SAndroid Build Coastguard Worker```cmake
23*89c4ff92SAndroid Build Coastguard Worker#
24*89c4ff92SAndroid Build Coastguard Worker# Make sure the reference backend is included in the build.
25*89c4ff92SAndroid Build Coastguard Worker# By adding the subdirectory, cmake requires the presence of CMakeLists.txt
26*89c4ff92SAndroid Build Coastguard Worker# in the reference (backend) folder.
27*89c4ff92SAndroid Build Coastguard Worker#
28*89c4ff92SAndroid Build Coastguard Workeradd_subdirectory(${PROJECT_SOURCE_DIR}/src/backends/reference)
29*89c4ff92SAndroid Build Coastguard Worker
30*89c4ff92SAndroid Build Coastguard Worker#
31*89c4ff92SAndroid Build Coastguard Worker# Add the cmake OBJECT libraries built by the reference backend to the
32*89c4ff92SAndroid Build Coastguard Worker# list of libraries linked against the Arm NN shared library.
33*89c4ff92SAndroid Build Coastguard Worker#
34*89c4ff92SAndroid Build Coastguard Workerlist(APPEND armnnLibraries armnnRefBackend armnnRefBackendWorkloads)
35*89c4ff92SAndroid Build Coastguard Worker
36*89c4ff92SAndroid Build Coastguard Worker#
37*89c4ff92SAndroid Build Coastguard Worker# Backend specific unit tests can be integrated through the
38*89c4ff92SAndroid Build Coastguard Worker# armnnUnitTestLibraries variable. This makes sure that the
39*89c4ff92SAndroid Build Coastguard Worker# UnitTests executable can run the backend-specific unit
40*89c4ff92SAndroid Build Coastguard Worker# tests.
41*89c4ff92SAndroid Build Coastguard Worker#
42*89c4ff92SAndroid Build Coastguard Workerlist(APPEND armnnUnitTestLibraries armnnRefBackendUnitTests)
43*89c4ff92SAndroid Build Coastguard Worker```
44*89c4ff92SAndroid Build Coastguard Worker
45*89c4ff92SAndroid Build Coastguard Worker### The CMakeLists.txt file
46*89c4ff92SAndroid Build Coastguard Worker
47*89c4ff92SAndroid Build Coastguard WorkerAs described in the previous section, adding a new backend will require creating a ```CMakeLists.txt``` in
48*89c4ff92SAndroid Build Coastguard Workerthe backend folder. This follows the standard cmake conventions, and is required to build a static cmake OBJECT library
49*89c4ff92SAndroid Build Coastguard Workerto be linked into the Arm NN shared library. As with any cmake build, the code can be structured into
50*89c4ff92SAndroid Build Coastguard Workersubfolders and modules as the developer sees fit.
51*89c4ff92SAndroid Build Coastguard Worker
52*89c4ff92SAndroid Build Coastguard WorkerExample can be found under [reference/CMakeLists.txt](reference/CMakeLists.txt).
53*89c4ff92SAndroid Build Coastguard Worker
54*89c4ff92SAndroid Build Coastguard Worker### The backend.mk file
55*89c4ff92SAndroid Build Coastguard Worker
56*89c4ff92SAndroid Build Coastguard WorkerArm NN on Android uses the native Android build system. New backends are integrated by creating a
57*89c4ff92SAndroid Build Coastguard Worker```backend.mk``` file, which has a single variable called ```BACKEND_SOURCES``` listing all cpp
58*89c4ff92SAndroid Build Coastguard Workerfiles to be built by the Android build system for the Arm NN shared library.
59*89c4ff92SAndroid Build Coastguard Worker
60*89c4ff92SAndroid Build Coastguard WorkerOptionally, backend-specific unit tests can be added similarly, by
61*89c4ff92SAndroid Build Coastguard Workerappending the list of cpp files to the ```BACKEND_TEST_SOURCES``` variable.
62*89c4ff92SAndroid Build Coastguard Worker
63*89c4ff92SAndroid Build Coastguard WorkerExample taken from [reference/backend.mk](reference/backend.mk):
64*89c4ff92SAndroid Build Coastguard Worker
65*89c4ff92SAndroid Build Coastguard Worker```make
66*89c4ff92SAndroid Build Coastguard WorkerBACKEND_SOURCES := \
67*89c4ff92SAndroid Build Coastguard Worker        RefLayerSupport.cpp \
68*89c4ff92SAndroid Build Coastguard Worker        RefWorkloadFactory.cpp \
69*89c4ff92SAndroid Build Coastguard Worker        workloads/Activation.cpp \
70*89c4ff92SAndroid Build Coastguard Worker        workloads/ElementwiseFunction.cpp \
71*89c4ff92SAndroid Build Coastguard Worker        workloads/Broadcast.cpp \
72*89c4ff92SAndroid Build Coastguard Worker        ...
73*89c4ff92SAndroid Build Coastguard Worker
74*89c4ff92SAndroid Build Coastguard WorkerBACKEND_TEST_SOURCES := \
75*89c4ff92SAndroid Build Coastguard Worker        test/RefCreateWorkloadTests.cpp \
76*89c4ff92SAndroid Build Coastguard Worker        test/RefEndToEndTests.cpp \
77*89c4ff92SAndroid Build Coastguard Worker        test/RefJsonPrinterTests.cpp \
78*89c4ff92SAndroid Build Coastguard Worker        ...
79*89c4ff92SAndroid Build Coastguard Worker```
80*89c4ff92SAndroid Build Coastguard Worker
81*89c4ff92SAndroid Build Coastguard Worker## How to add common code across backends
82*89c4ff92SAndroid Build Coastguard Worker
83*89c4ff92SAndroid Build Coastguard WorkerFor multiple backends that need common code, there is support for including them in the build
84*89c4ff92SAndroid Build Coastguard Workersimilarly to the backend code. This requires adding three files under a subfolder at the same level
85*89c4ff92SAndroid Build Coastguard Workeras the backends folders. These are:
86*89c4ff92SAndroid Build Coastguard Worker
87*89c4ff92SAndroid Build Coastguard Worker1. common.cmake
88*89c4ff92SAndroid Build Coastguard Worker2. common.mk
89*89c4ff92SAndroid Build Coastguard Worker3. CMakeLists.txt
90*89c4ff92SAndroid Build Coastguard Worker
91*89c4ff92SAndroid Build Coastguard WorkerThey work the same way as the backend files. The only difference between them is that
92*89c4ff92SAndroid Build Coastguard Workercommon code is built first, so the backend code can depend on them.
93*89c4ff92SAndroid Build Coastguard Worker
94*89c4ff92SAndroid Build Coastguard Worker[aclCommon](aclCommon) is an example for this concept and you can find the corresponding files:
95*89c4ff92SAndroid Build Coastguard Worker
96*89c4ff92SAndroid Build Coastguard Worker1. [aclCommon/common.cmake](aclCommon/common.cmake)
97*89c4ff92SAndroid Build Coastguard Worker2. [aclCommon/common.mk](aclCommon/common.mk)
98*89c4ff92SAndroid Build Coastguard Worker3. [aclCommon/CMakeLists.txt](aclCommon/CMakeLists.txt)
99*89c4ff92SAndroid Build Coastguard Worker
100*89c4ff92SAndroid Build Coastguard Worker## Identifying backends
101*89c4ff92SAndroid Build Coastguard Worker
102*89c4ff92SAndroid Build Coastguard WorkerBackends are identified by a string that must be unique across backends. This string is
103*89c4ff92SAndroid Build Coastguard Workerwrapped in the [BackendId](../../include/armnn/BackendId.hpp) object for backward compatibility
104*89c4ff92SAndroid Build Coastguard Workerwith previous Arm NN versions.
105*89c4ff92SAndroid Build Coastguard Worker
106*89c4ff92SAndroid Build Coastguard Worker## The IBackendInternal interface
107*89c4ff92SAndroid Build Coastguard Worker
108*89c4ff92SAndroid Build Coastguard WorkerAll backends need to implement the [IBackendInternal](../../include/armnn/backends/IBackendInternal.hpp) interface.
109*89c4ff92SAndroid Build Coastguard WorkerThe interface functions to be implemented are:
110*89c4ff92SAndroid Build Coastguard Worker
111*89c4ff92SAndroid Build Coastguard Worker```c++
112*89c4ff92SAndroid Build Coastguard Worker    virtual IMemoryManagerUniquePtr CreateMemoryManager() const = 0;
113*89c4ff92SAndroid Build Coastguard Worker    virtual IWorkloadFactoryPtr CreateWorkloadFactory(
114*89c4ff92SAndroid Build Coastguard Worker            const IMemoryManagerSharedPtr& memoryManager = nullptr) const = 0;
115*89c4ff92SAndroid Build Coastguard Worker    virtual IBackendContextPtr CreateBackendContext(const IRuntime::CreationOptions&) const = 0;
116*89c4ff92SAndroid Build Coastguard Worker    virtual IBackendProfilingContextPtr CreateBackendProfilingContext(const IRuntime::CreationOptions& creationOptions,
117*89c4ff92SAndroid Build Coastguard Worker            arm::pipe::IBackendProfiling& backendProfiling) const = 0;
118*89c4ff92SAndroid Build Coastguard Worker    virtual ILayerSupportSharedPtr GetLayerSupport() const = 0;
119*89c4ff92SAndroid Build Coastguard Worker    virtual Optimizations GetOptimizations() const = 0;
120*89c4ff92SAndroid Build Coastguard Worker    virtual SubgraphUniquePtr OptimizeSubgraph(const SubgraphView& subgraph, bool& optimizationAttempted) const;
121*89c4ff92SAndroid Build Coastguard Worker    virtual OptimizationViews OptimizeSubgraphView(const SubgraphView& subgraph) const;
122*89c4ff92SAndroid Build Coastguard Worker```
123*89c4ff92SAndroid Build Coastguard Worker
124*89c4ff92SAndroid Build Coastguard WorkerNote that ```GetOptimizations()``` and ```SubgraphViewUniquePtr OptimizeSubgraphView(const SubgraphView& subgraph, bool& optimizationAttempted)```
125*89c4ff92SAndroid Build Coastguard Workerhave been deprecated.
126*89c4ff92SAndroid Build Coastguard WorkerThe method ```OptimizationViews OptimizeSubgraph(const SubgraphView& subgraph)``` should be used instead to
127*89c4ff92SAndroid Build Coastguard Workerapply specific optimizations to a given sub-graph.
128*89c4ff92SAndroid Build Coastguard Worker
129*89c4ff92SAndroid Build Coastguard WorkerThe Arm NN framework then creates instances of the IBackendInternal interface with the help of the
130*89c4ff92SAndroid Build Coastguard Worker[BackendRegistry](../../include/armnn/BackendRegistry.hpp) singleton.
131*89c4ff92SAndroid Build Coastguard Worker
132*89c4ff92SAndroid Build Coastguard Worker**Important:** the ```IBackendInternal``` object is not guaranteed to have a longer lifetime than
133*89c4ff92SAndroid Build Coastguard Workerthe objects it creates. It is only intended to be a single entry point for the factory functions it has.
134*89c4ff92SAndroid Build Coastguard WorkerThe best use of this is to be a lightweight, stateless object and make no assumptions between
135*89c4ff92SAndroid Build Coastguard Workerits lifetime and the lifetime of the objects it creates.
136*89c4ff92SAndroid Build Coastguard Worker
137*89c4ff92SAndroid Build Coastguard WorkerFor each backend one needs to register a factory function that can
138*89c4ff92SAndroid Build Coastguard Workerbe retrieved using a [BackendId](../../include/armnn/BackendId.hpp).
139*89c4ff92SAndroid Build Coastguard WorkerThe Arm NN framework creates the backend interfaces dynamically when
140*89c4ff92SAndroid Build Coastguard Workerit sees fit and it keeps these objects for a short period of time. Examples:
141*89c4ff92SAndroid Build Coastguard Worker
142*89c4ff92SAndroid Build Coastguard Worker* During optimization Arm NN needs to decide which layers are supported by the backend.
143*89c4ff92SAndroid Build Coastguard Worker  To do this, it creates a backends and calls the ```GetLayerSupport()``` function and creates
144*89c4ff92SAndroid Build Coastguard Worker  an ```ILayerSupport``` object to help deciding this.
145*89c4ff92SAndroid Build Coastguard Worker* During optimization Arm NN can run backend-specific optimizations. After splitting the graph into
146*89c4ff92SAndroid Build Coastguard Worker  sub-graphs based on backends, it calls the ```OptimizeSubgraphView()``` function on each of them and, if possible,
147*89c4ff92SAndroid Build Coastguard Worker  substitutes the corresponding sub-graph in the original graph with its optimized version.
148*89c4ff92SAndroid Build Coastguard Worker* When the Runtime is initialized it creates an optional ```IBackendContext``` object and keeps this context alive
149*89c4ff92SAndroid Build Coastguard Worker  for the Runtime's lifetime. It notifies this context object before and after a network is loaded or unloaded.
150*89c4ff92SAndroid Build Coastguard Worker* When the LoadedNetwork creates the backend-specific workloads for the layers, it creates a backend
151*89c4ff92SAndroid Build Coastguard Worker  specific workload factory and calls this to create the workloads.
152*89c4ff92SAndroid Build Coastguard Worker
153*89c4ff92SAndroid Build Coastguard Worker## The BackendRegistry
154*89c4ff92SAndroid Build Coastguard Worker
155*89c4ff92SAndroid Build Coastguard WorkerAs mentioned above, all backends need to be registered through the BackendRegistry so Arm NN knows
156*89c4ff92SAndroid Build Coastguard Workerabout them. Registration requires a unique backend ID string and a lambda function that
157*89c4ff92SAndroid Build Coastguard Workerreturns a unique pointer to the [IBackendInternal interface](../../include/armnn/backends/IBackendInternal.hpp).
158*89c4ff92SAndroid Build Coastguard Worker
159*89c4ff92SAndroid Build Coastguard WorkerFor registering a backend only this lambda function needs to exist, not the actual backend. This
160*89c4ff92SAndroid Build Coastguard Workerallows dynamically creating the backend objects when they are needed.
161*89c4ff92SAndroid Build Coastguard Worker
162*89c4ff92SAndroid Build Coastguard WorkerThe BackendRegistry has a few convenience functions, like we can query the registered backends and
163*89c4ff92SAndroid Build Coastguard Workerare able to tell if a given backend is registered or not.
164*89c4ff92SAndroid Build Coastguard Worker
165*89c4ff92SAndroid Build Coastguard WorkerDynamic backends are registered during the runtime creation.
166*89c4ff92SAndroid Build Coastguard Worker
167*89c4ff92SAndroid Build Coastguard Worker## The ILayerSupport interface
168*89c4ff92SAndroid Build Coastguard Worker
169*89c4ff92SAndroid Build Coastguard WorkerArm NN uses the [ILayerSupport](../../include/armnn/backends/ILayerSupport.hpp) interface to decide if a layer
170*89c4ff92SAndroid Build Coastguard Workerwith a set of parameters (i.e. input and output tensors, descriptor, weights, filter, kernel if any) are
171*89c4ff92SAndroid Build Coastguard Workersupported on a given backend. The backends need a way to communicate this information by implementing
172*89c4ff92SAndroid Build Coastguard Workerthe ```GetLayerSupport()``` function on the ```IBackendInternal``` interface.
173*89c4ff92SAndroid Build Coastguard Worker
174*89c4ff92SAndroid Build Coastguard WorkerExamples of this can be found in the [RefLayerSupport header](reference/RefLayerSupport.hpp)
175*89c4ff92SAndroid Build Coastguard Workerand the [RefLayerSupport implementation](reference/RefLayerSupport.cpp).
176*89c4ff92SAndroid Build Coastguard Worker
177*89c4ff92SAndroid Build Coastguard Worker## The IWorkloadFactory interface
178*89c4ff92SAndroid Build Coastguard Worker
179*89c4ff92SAndroid Build Coastguard WorkerThe [IWorkloadFactory interface](backendsCommon/WorkloadFactory.hpp) is used for creating the backend
180*89c4ff92SAndroid Build Coastguard Workerspecific workloads. The factory function that creates the IWorkloadFactory object in the IBackendInterface
181*89c4ff92SAndroid Build Coastguard Workertakes an IMemoryManager object.
182*89c4ff92SAndroid Build Coastguard Worker
183*89c4ff92SAndroid Build Coastguard WorkerTo create a workload object the ```IWorkloadFactory``` takes a ```WorkloadInfo``` object that holds
184*89c4ff92SAndroid Build Coastguard Workerthe input and output tensor information and a workload specific queue descriptor.
185*89c4ff92SAndroid Build Coastguard Worker
186*89c4ff92SAndroid Build Coastguard Worker## The IMemoryManager interface
187*89c4ff92SAndroid Build Coastguard Worker
188*89c4ff92SAndroid Build Coastguard WorkerBackends may choose to implement custom memory management. Arm NN supports this concept through the following
189*89c4ff92SAndroid Build Coastguard Workermechanism:
190*89c4ff92SAndroid Build Coastguard Worker
191*89c4ff92SAndroid Build Coastguard Worker* the ```IBackendInternal``` interface has a ```CreateMemoryManager()``` function, which is called before
192*89c4ff92SAndroid Build Coastguard Worker  creating the workload factory
193*89c4ff92SAndroid Build Coastguard Worker* the memory manager is passed to the ```CreateWorkloadFactory(...)``` function so the workload factory can
194*89c4ff92SAndroid Build Coastguard Worker  use it for creating the backend-specific workloads
195*89c4ff92SAndroid Build Coastguard Worker* the LoadedNetwork calls ```Acquire()``` on the memory manager before it starts executing the network and
196*89c4ff92SAndroid Build Coastguard Worker  it calls ```Release()``` in its destructor
197*89c4ff92SAndroid Build Coastguard Worker
198*89c4ff92SAndroid Build Coastguard Worker## The Optimizations
199*89c4ff92SAndroid Build Coastguard Worker
200*89c4ff92SAndroid Build Coastguard WorkerThe backends may choose to implement backend-specific optimizations.
201*89c4ff92SAndroid Build Coastguard WorkerThis is supported through the method ```OptimizationViews OptimizeSubgraph(const SubgraphView& subgraph)``` of
202*89c4ff92SAndroid Build Coastguard Workerthe backend interface that allows the backends to apply their specific optimizations to a given sub-graph.
203*89c4ff92SAndroid Build Coastguard Worker
204*89c4ff92SAndroid Build Coastguard WorkerThe ```OptimizeSubgraph(...)``` method returns an OptimizationViews object containing three lists:
205*89c4ff92SAndroid Build Coastguard Worker
206*89c4ff92SAndroid Build Coastguard Worker* A list of the sub-graph substitutions: a "substitution" is a pair of sub-graphs, the first is the "substitutable" sub-graph,
207*89c4ff92SAndroid Build Coastguard Worker  representing the part of the original graph that has been optimized by the backend, while the second is the "replacement" sub-graph,
208*89c4ff92SAndroid Build Coastguard Worker  containing the actual optimized layers that will be replaced in the original graph correspondingly to the "substitutable" sub-graph
209*89c4ff92SAndroid Build Coastguard Worker* A list of the failed sub-graphs: these are the parts of the original sub-graph that are not supported by the backend,
210*89c4ff92SAndroid Build Coastguard Worker  thus have been rejected. Arm NN will try to re-allocate these parts on other backends if available.
211*89c4ff92SAndroid Build Coastguard Worker* A list of the untouched sub-graphs: these are the parts of the original sub-graph that have not been optimized,
212*89c4ff92SAndroid Build Coastguard Worker  but that can run (unoptimized) on the backend.
213*89c4ff92SAndroid Build Coastguard Worker
214*89c4ff92SAndroid Build Coastguard WorkerThe previous way backends had to provide a list optimizations to the Optimizer (through the ```GetOptimizations()``` method)
215*89c4ff92SAndroid Build Coastguard Workeris still in place for backward compatibility, but it's now considered deprecated and will be remove in a future release.
216*89c4ff92SAndroid Build Coastguard Worker
217*89c4ff92SAndroid Build Coastguard Worker## The IBackendContext interface
218*89c4ff92SAndroid Build Coastguard Worker
219*89c4ff92SAndroid Build Coastguard WorkerBackends may need to be notified whenever a network is loaded or unloaded. To support that, one can implement the optional
220*89c4ff92SAndroid Build Coastguard Worker[IBackendContext](../../include/armnn/backends/IBackendContext.hpp) interface. The framework calls the ```CreateBackendContext(...)```
221*89c4ff92SAndroid Build Coastguard Workermethod for each backend in the Runtime. If the backend returns a valid unique pointer to a backend context, then the
222*89c4ff92SAndroid Build Coastguard Workerruntime will hold this for its entire lifetime. It then calls the following interface functions for each stored context:
223*89c4ff92SAndroid Build Coastguard Worker
224*89c4ff92SAndroid Build Coastguard Worker* ```BeforeLoadNetwork(NetworkId networkId)```
225*89c4ff92SAndroid Build Coastguard Worker* ```AfterLoadNetwork(NetworkId networkId)```
226*89c4ff92SAndroid Build Coastguard Worker* ```BeforeUnloadNetwork(NetworkId networkId)```
227*89c4ff92SAndroid Build Coastguard Worker* ```AfterUnloadNetwork(NetworkId networkId)```
228*89c4ff92SAndroid Build Coastguard Worker
229*89c4ff92SAndroid Build Coastguard Worker## The UseCustomMemoryAllocator interface
230*89c4ff92SAndroid Build Coastguard Worker
231*89c4ff92SAndroid Build Coastguard WorkerBackends can also have an associated CustomMemoryAllocator registered with them that ArmNN will use to allocate
232*89c4ff92SAndroid Build Coastguard Workerintra/inter-layer memory. This particular feature is required if you want a backend to use ProtectedContentAllocation.
233*89c4ff92SAndroid Build Coastguard WorkerTo support this on your own backend you must implement the UseCustomMemoryAllocator interface.
234*89c4ff92SAndroid Build Coastguard Worker
235*89c4ff92SAndroid Build Coastguard WorkerThis interface returns a boolean value which indicates if the provided allocator is supported by
236*89c4ff92SAndroid Build Coastguard Workerthe backend. This interface is also used by the lambda function returned by the Backend Registry to configure
237*89c4ff92SAndroid Build Coastguard Workerthe CustomMemoryAllocator. Within the backend itself there should be a wrapper class to convert the generic
238*89c4ff92SAndroid Build Coastguard WorkerCustomMemoryAllocator provided by the interface into something that is more suitable for your own backend.
239*89c4ff92SAndroid Build Coastguard Worker
240*89c4ff92SAndroid Build Coastguard WorkerExamples of how this can be done are in the [ClBackend header](cl/ClBackend.hpp) and the
241*89c4ff92SAndroid Build Coastguard Worker[ClRegistryInitializer header](cl/ClRegistryInitializer.cpp)
242*89c4ff92SAndroid Build Coastguard Worker
243*89c4ff92SAndroid Build Coastguard Worker## The GetCapabilities interface
244*89c4ff92SAndroid Build Coastguard Worker
245*89c4ff92SAndroid Build Coastguard WorkerThis is a list of BackendCapabilities currently supported by the backend. It consists of a constant list of
246*89c4ff92SAndroid Build Coastguard WorkerName/Value pairs, each containing a string name, and a boolean value to indicate support. For example to
247*89c4ff92SAndroid Build Coastguard Workerindicate support for ProtectedContentAllocation you would return {"ProtectedContentAllocation", true}
248*89c4ff92SAndroid Build Coastguard Worker
249*89c4ff92SAndroid Build Coastguard WorkerAn example can be found at the top of [ClBackend header](cl/ClBackend.hpp)
250*89c4ff92SAndroid Build Coastguard Worker
251*89c4ff92SAndroid Build Coastguard Worker## Dynamic backends
252*89c4ff92SAndroid Build Coastguard Worker
253*89c4ff92SAndroid Build Coastguard WorkerBackends can also be loaded by Arm NN dynamically at runtime.
254*89c4ff92SAndroid Build Coastguard WorkerTo be properly loaded and used, the backend instances must comply to the standard interface for dynamic backends and to the versioning
255*89c4ff92SAndroid Build Coastguard Workerrules that enforce ABI compatibility.
256*89c4ff92SAndroid Build Coastguard Worker
257*89c4ff92SAndroid Build Coastguard Worker## Dynamic backends base interface
258*89c4ff92SAndroid Build Coastguard Worker
259*89c4ff92SAndroid Build Coastguard WorkerThe dynamic backend shared object must expose the following interface for Arm NN to handle it correctly:
260*89c4ff92SAndroid Build Coastguard Worker
261*89c4ff92SAndroid Build Coastguard Worker```c++
262*89c4ff92SAndroid Build Coastguard Workerextern "C"
263*89c4ff92SAndroid Build Coastguard Worker{
264*89c4ff92SAndroid Build Coastguard Workerconst char* GetBackendId();
265*89c4ff92SAndroid Build Coastguard Workervoid GetVersion(uint32_t* outMajor, uint32_t* outMinor);
266*89c4ff92SAndroid Build Coastguard Workervoid* BackendFactory();
267*89c4ff92SAndroid Build Coastguard Worker}
268*89c4ff92SAndroid Build Coastguard Worker```
269*89c4ff92SAndroid Build Coastguard Worker
270*89c4ff92SAndroid Build Coastguard WorkerInterface details:
271*89c4ff92SAndroid Build Coastguard Worker
272*89c4ff92SAndroid Build Coastguard Worker* ```extern "C"``` is needed to use avoid C++ name mangling, necessary to allow Arm NN to dynamically load the symbols.
273*89c4ff92SAndroid Build Coastguard Worker* ```GetBackendId()```: must return the unique id of the dynamic backends.
274*89c4ff92SAndroid Build Coastguard Worker  If at the time of the loading the id already exists in the internal Arm NN's backend registry, the backend will be skipped and
275*89c4ff92SAndroid Build Coastguard Worker  not loaded in Arm NN
276*89c4ff92SAndroid Build Coastguard Worker* ```GetVersion()```: must return the version of the dynamic backend.
277*89c4ff92SAndroid Build Coastguard Worker  The version must indicate the version of the Backend API the dynamic backend has been built with.
278*89c4ff92SAndroid Build Coastguard Worker  The current Backend API version can be found by inspecting the IBackendInternal interface.
279*89c4ff92SAndroid Build Coastguard Worker  At the time of loading, the version of the backend will be checked against the version of the Backend API Arm NN is built with.
280*89c4ff92SAndroid Build Coastguard Worker  If the backend version is not compatible with the current Backend API, the backend will not be loaded as it will be assumed that
281*89c4ff92SAndroid Build Coastguard Worker  it is not ABI compatible with the current Arm NN build.
282*89c4ff92SAndroid Build Coastguard Worker* ```BackendFactory()```: must return a valid instance of the backend.
283*89c4ff92SAndroid Build Coastguard Worker  The backend instance is an object that must inherit from the version of the IBackendInternal interface declared by GetVersion().
284*89c4ff92SAndroid Build Coastguard Worker  It is the backend developer's responsibility to ensure that the backend implementation correctly reflects the version declared by
285*89c4ff92SAndroid Build Coastguard Worker  GetVersion(), and that the object returned by the BackendFactory() function is a valid and well-formed instance of the IBackendInternal
286*89c4ff92SAndroid Build Coastguard Worker  interface.
287*89c4ff92SAndroid Build Coastguard Worker
288*89c4ff92SAndroid Build Coastguard Worker## Dynamic backend versioning and ABI compatibility
289*89c4ff92SAndroid Build Coastguard Worker
290*89c4ff92SAndroid Build Coastguard WorkerDynamic backend versioning policy:
291*89c4ff92SAndroid Build Coastguard Worker
292*89c4ff92SAndroid Build Coastguard WorkerUpdates to Arm NN's Backend API follow these rules: changes to the Backend API (the IBackendInternal interface) that break
293*89c4ff92SAndroid Build Coastguard WorkerABI compatibility with the previous API version will be indicated by a change of the API's major version, while changes
294*89c4ff92SAndroid Build Coastguard Workerthat guarantee ABI compatibility with the previous API version will be indicated by a change in API's the minor version.
295*89c4ff92SAndroid Build Coastguard Worker
296*89c4ff92SAndroid Build Coastguard WorkerFor example:
297*89c4ff92SAndroid Build Coastguard Worker
298*89c4ff92SAndroid Build Coastguard Worker* Dynamic backend version 2.4 (i.e. built with Backend API version 2.4) is compatible with Arm NN's Backend API version 2.4
299*89c4ff92SAndroid Build Coastguard Worker  (same version, backend built against the same Backend API)
300*89c4ff92SAndroid Build Coastguard Worker* Dynamic backend version 2.1 (i.e. built with Backend API version 2.1) is compatible with Arm NN's Backend API version 2.4
301*89c4ff92SAndroid Build Coastguard Worker  (same major version, backend built against earlier compatible API)
302*89c4ff92SAndroid Build Coastguard Worker* Dynamic backend version 2.5 (i.e. built with Backend API version 2.5) is not compatible with Arm NN's Backend API version 2.4
303*89c4ff92SAndroid Build Coastguard Worker  (same major version, backend built against later incompatible API, backend might require update to the latest compatible backend API)
304*89c4ff92SAndroid Build Coastguard Worker* Dynamic backend version 2.0 (i.e. built with Backend API version 2.0) is not compatible with Arm NN's Backend API version 1.0
305*89c4ff92SAndroid Build Coastguard Worker  (backend requires a completely new API version)
306*89c4ff92SAndroid Build Coastguard Worker* Dynamic backend version 2.0 (i.e. built with Backend API version 2.0) is not compatible with Arm NN's Backend API version 3.0
307*89c4ff92SAndroid Build Coastguard Worker  (backward compatibility in the Backend API is broken)
308*89c4ff92SAndroid Build Coastguard Worker
309*89c4ff92SAndroid Build Coastguard Worker## Dynamic backend loading paths
310*89c4ff92SAndroid Build Coastguard Worker
311*89c4ff92SAndroid Build Coastguard WorkerDuring the creation of the Runtime, Arm NN will scan a given set of paths searching for suitable dynamic backend objects to load.
312*89c4ff92SAndroid Build Coastguard WorkerA list of (absolute) paths can be specified at compile-time by setting a define named ```DYNAMIC_BACKEND_PATHS``` in the form of a colon-separated list of strings.
313*89c4ff92SAndroid Build Coastguard Worker
314*89c4ff92SAndroid Build Coastguard Worker```shell
315*89c4ff92SAndroid Build Coastguard Worker-DDYNAMIC_BACKEND_PATHS="PATH_1:PATH_2...:PATH_N"
316*89c4ff92SAndroid Build Coastguard Worker```
317*89c4ff92SAndroid Build Coastguard Worker
318*89c4ff92SAndroid Build Coastguard WorkerThe paths will be processed in the same order as they are indicated in the macro.
319*89c4ff92SAndroid Build Coastguard Worker
320*89c4ff92SAndroid Build Coastguard WorkerIt is also possible to override those paths at runtime when creating the Runtime object by setting the value of the ```m_DynamicBackendsPath``` member in the CreationOptions class.
321*89c4ff92SAndroid Build Coastguard WorkerOnly one path is allowed for the override via the CreationOptions class.
322*89c4ff92SAndroid Build Coastguard WorkerBy setting the value of the ```m_DynamicBackendsPath``` to a path in the filesystem, Arm NN will entirely ignore the list of paths passed via the
323*89c4ff92SAndroid Build Coastguard Worker```DYNAMIC_BACKEND_PATHS``` compiler directive.
324*89c4ff92SAndroid Build Coastguard Worker
325*89c4ff92SAndroid Build Coastguard WorkerAll the specified paths are validated before processing (they must exist, must be directories, and must be absolute paths),
326*89c4ff92SAndroid Build Coastguard Workerin case of error a warning message will be added to the log, but Arm NN's execution will not be stopped.
327*89c4ff92SAndroid Build Coastguard WorkerIf all paths are not valid, then no dynamic backends will be loaded in the Arm NN's runtime.
328*89c4ff92SAndroid Build Coastguard Worker
329*89c4ff92SAndroid Build Coastguard WorkerPassing an empty list of paths at compile-time and providing no path override at runtime will effectively disable the
330*89c4ff92SAndroid Build Coastguard Workerdynamic backend loading feature, and no dynamic backends will be loaded into Arm NN's runtime.
331*89c4ff92SAndroid Build Coastguard Worker
332*89c4ff92SAndroid Build Coastguard Worker## Dynamic backend file naming convention
333*89c4ff92SAndroid Build Coastguard Worker
334*89c4ff92SAndroid Build Coastguard WorkerDuring the creation of a Runtime object, Arm NN will scan the paths specified for dynamic backend loading searching for suitable backend objects.
335*89c4ff92SAndroid Build Coastguard WorkerArm NN will try to load only the files that match the following accepted naming scheme:
336*89c4ff92SAndroid Build Coastguard Worker
337*89c4ff92SAndroid Build Coastguard Worker```shell
338*89c4ff92SAndroid Build Coastguard Worker<vendor>_<name>_backend.so[<version>] (e.g. "Arm_GpuAcc_backend.so" or "Arm_GpuAcc_backend.so.1.2.3")
339*89c4ff92SAndroid Build Coastguard Worker```
340*89c4ff92SAndroid Build Coastguard Worker
341*89c4ff92SAndroid Build Coastguard WorkerOnly alphanumeric characters are allowed for both the `<vendor>` and the `<name>` fields, namely lowercase and/or uppercase characters,
342*89c4ff92SAndroid Build Coastguard Workerand/or numerical digits (see the table below for examples).
343*89c4ff92SAndroid Build Coastguard WorkerOnly dots and numbers are allowed for the optional `<version>` field.
344*89c4ff92SAndroid Build Coastguard Worker
345*89c4ff92SAndroid Build Coastguard WorkerSymlinks to other files are allowed to support the standard linux shared object versioning:
346*89c4ff92SAndroid Build Coastguard Worker
347*89c4ff92SAndroid Build Coastguard Worker```shell
348*89c4ff92SAndroid Build Coastguard WorkerArm_GpuAcc_backend.so -> Arm_GpuAcc_backend.so.1.2.3
349*89c4ff92SAndroid Build Coastguard WorkerArm_GpuAcc_backend.so.1 -> Arm_GpuAcc_backend.so.1.2.3
350*89c4ff92SAndroid Build Coastguard WorkerArm_GpuAcc_backend.so.1.2 -> Arm_GpuAcc_backend.so.1.2.3
351*89c4ff92SAndroid Build Coastguard WorkerArm_GpuAcc_backend.so.1.2.3
352*89c4ff92SAndroid Build Coastguard Worker```
353*89c4ff92SAndroid Build Coastguard Worker
354*89c4ff92SAndroid Build Coastguard WorkerFiles are identified by their full canonical path, so it is allowed to have files with the same name in different directories.
355*89c4ff92SAndroid Build Coastguard WorkerHowever, if those are actually the same dynamic backend, only the first in order of parsing will be loaded.
356*89c4ff92SAndroid Build Coastguard Worker
357*89c4ff92SAndroid Build Coastguard WorkerExamples:
358*89c4ff92SAndroid Build Coastguard Worker
359*89c4ff92SAndroid Build Coastguard Worker| Filename                                                 | Description                                       |
360*89c4ff92SAndroid Build Coastguard Worker| -------------------------------------------------------- | ------------------------------------------------- |
361*89c4ff92SAndroid Build Coastguard Worker| Arm_GpuAcc_backend.so                                    | valid: basic backend name                         |
362*89c4ff92SAndroid Build Coastguard Worker| Arm_GpuAcc_backend.so.1                                  | valid: single field version number                |
363*89c4ff92SAndroid Build Coastguard Worker| Arm_GpuAcc_backend.so.1.2                                | valid: multiple field version number              |
364*89c4ff92SAndroid Build Coastguard Worker| Arm_GpuAcc_backend.so.1.2.3                              | valid: multiple field version number              |
365*89c4ff92SAndroid Build Coastguard Worker| Arm_GpuAcc_backend.so.10.1.27                            | valid: Multiple digit version                     |
366*89c4ff92SAndroid Build Coastguard Worker| Arm_GpuAcc_backend.so.10.1.33.                           | not valid: dot not followed by version number     |
367*89c4ff92SAndroid Build Coastguard Worker| Arm_GpuAcc_backend.so.3.4..5                             | not valid: dot not followed by version number     |
368*89c4ff92SAndroid Build Coastguard Worker| Arm_GpuAcc_backend.so.1,1.1                              | not valid: comma instead of dot in the version    |
369*89c4ff92SAndroid Build Coastguard Worker| Arm123_GpuAcc_backend.so                                 | valid: digits in vendor name are allowed          |
370*89c4ff92SAndroid Build Coastguard Worker| Arm_GpuAcc456_backend.so                                 | valid: digits in backend id are allowed           |
371*89c4ff92SAndroid Build Coastguard Worker| Arm%Co_GpuAcc_backend.so                                 | not valid: invalid character in vendor name       |
372*89c4ff92SAndroid Build Coastguard Worker| Arm_Gpu.Acc_backend.so                                   | not valid: invalid character in backend id        |
373*89c4ff92SAndroid Build Coastguard Worker| GpuAcc_backend.so                                        | not valid: missing vendor name                    |
374*89c4ff92SAndroid Build Coastguard Worker| _GpuAcc_backend.so                                       | not valid: missing vendor name                    |
375*89c4ff92SAndroid Build Coastguard Worker| Arm__backend.so                                          | not valid: missing backend id                     |
376*89c4ff92SAndroid Build Coastguard Worker| Arm_GpuAcc.so                                            | not valid: missing "backend" at the end           |
377*89c4ff92SAndroid Build Coastguard Worker| __backend.so                                             | not valid: missing vendor name and backend id     |
378*89c4ff92SAndroid Build Coastguard Worker| __.so                                                    | not valid: missing all fields                     |
379*89c4ff92SAndroid Build Coastguard Worker| Arm_GpuAcc_backend                                       | not valid: missing at least ".so" at the end      |
380*89c4ff92SAndroid Build Coastguard Worker| Arm_GpuAcc_backend_v1.2.so                               | not valid: extra version info at the end          |
381*89c4ff92SAndroid Build Coastguard Worker| Arm_CpuAcc_backend.so                                    | valid: basic backend name                         |
382*89c4ff92SAndroid Build Coastguard Worker| Arm_CpuAcc_backend.so.1 -> Arm_CpuAcc_backend.so         | valid: symlink to valid backend file              |
383*89c4ff92SAndroid Build Coastguard Worker| Arm_CpuAcc_backend.so.1.2 -> Arm_CpuAcc_backend.so.1     | valid: symlink to valid symlink                   |
384*89c4ff92SAndroid Build Coastguard Worker| Arm_CpuAcc_backend.so.1.2.3 -> Arm_CpuAcc_backend.so.1.2 | valid: symlink to valid symlink                   |
385*89c4ff92SAndroid Build Coastguard Worker| Arm_no_backend.so -> nothing                             | not valid: symlink resolves to non-existent file  |
386*89c4ff92SAndroid Build Coastguard Worker| pathA/Arm_GpuAcc_backend.so                              | valid: basic backend name                         |
387*89c4ff92SAndroid Build Coastguard Worker| pathB/Arm_GpuAcc_backend.so                              | valid: but duplicated from pathA/                 |
388*89c4ff92SAndroid Build Coastguard Worker
389*89c4ff92SAndroid Build Coastguard WorkerArm NN will try to load the dynamic backends in the same order as they are parsed from the filesystem.
390*89c4ff92SAndroid Build Coastguard Worker
391*89c4ff92SAndroid Build Coastguard Worker## Dynamic backend examples
392*89c4ff92SAndroid Build Coastguard Worker
393*89c4ff92SAndroid Build Coastguard WorkerThe source code includes an example that is used to generate some mock dynamic backends for testing purposes. The source files are:
394*89c4ff92SAndroid Build Coastguard Worker
395*89c4ff92SAndroid Build Coastguard Worker[TestDynamicBackend.hpp](backendsCommon/test/TestDynamicBackend.hpp)
396*89c4ff92SAndroid Build Coastguard Worker[TestDynamicBackend.cpp](backendsCommon/test/TestDynamicBackend.cpp)
397*89c4ff92SAndroid Build Coastguard Worker
398*89c4ff92SAndroid Build Coastguard WorkerThis example is useful for going through all the use cases that constitute an invalid dynamic backend object, such as
399*89c4ff92SAndroid Build Coastguard Workeran invalid/malformed implementation of the shared object interface, or an invalid value returned by any of the interface methods
400*89c4ff92SAndroid Build Coastguard Workerthat would prevent Arm NN from making use of the dynamic backend.
401*89c4ff92SAndroid Build Coastguard Worker
402*89c4ff92SAndroid Build Coastguard WorkerA dynamic implementation of the reference backend is also provided. The source files are:
403*89c4ff92SAndroid Build Coastguard Worker
404*89c4ff92SAndroid Build Coastguard Worker[RefDynamicBackend.hpp](dynamic/reference/RefDynamicBackend.hpp)
405*89c4ff92SAndroid Build Coastguard Worker[RefDynamicBackend.cpp](dynamic/reference/RefDynamicBackend.cpp)
406*89c4ff92SAndroid Build Coastguard Worker
407*89c4ff92SAndroid Build Coastguard WorkerThe implementation itself is quite simple and straightforward. Since an implementation of this particular backend was already available,
408*89c4ff92SAndroid Build Coastguard Workerthe dynamic version is just a wrapper around the original code that simply returns the backend id, version and an instance of the
409*89c4ff92SAndroid Build Coastguard Workerbackend itself via the factory function.
410*89c4ff92SAndroid Build Coastguard WorkerFor the sake of the example, the source code of the reference backend is used to build the dynamic version (as you would for any new
411*89c4ff92SAndroid Build Coastguard Workerdynamic backend), while all the other symbols needed are provided by linking the dynamic backend against Arm NN.
412*89c4ff92SAndroid Build Coastguard Worker
413*89c4ff92SAndroid Build Coastguard WorkerThe makefile used for building the reference dynamic backend is also provided: [CMakeLists.txt](dynamic/reference/CMakeLists.txt)
414*89c4ff92SAndroid Build Coastguard Worker
415*89c4ff92SAndroid Build Coastguard WorkerA unit test that loads the reference backend dynamically and that exercises it is also included in the file
416*89c4ff92SAndroid Build Coastguard Worker[DynamicBackendTests.cpp](dynamic/backendsCommon/test/DynamicBackendTests.cpp), by the test case ```CreateReferenceDynamicBackend```.
417*89c4ff92SAndroid Build Coastguard WorkerIn the test, a path on the filesystem is scanned for valid dynamic backend files (using the override option in ```CreationOptions```)
418*89c4ff92SAndroid Build Coastguard Workerwhere only the reference dynamic backend is.
419*89c4ff92SAndroid Build Coastguard WorkerIn this example the file is named ```Arm_CpuRef_backend.so```, which is compliant with the expected naming scheme for dynamic backends.
420*89c4ff92SAndroid Build Coastguard WorkerA ```DynamicBackend``` is created in the runtime to represent the newly loaded backend, then the backend is registered in the Backend
421*89c4ff92SAndroid Build Coastguard WorkerRegistry with the id "CpuRef" (returned by ```GetBackendId()```).
422*89c4ff92SAndroid Build Coastguard WorkerThe unit test makes sure that the backend is actually registered in Arm NN, before trying to create an instance of the backend by
423*89c4ff92SAndroid Build Coastguard Workercalling the factory function provided through the shared object interface (```BackendFactory()```).
424*89c4ff92SAndroid Build Coastguard WorkerThe backend instance is used to verify that everything is in order, testing basic 2D convolution support by making use of the
425*89c4ff92SAndroid Build Coastguard WorkerLayer Support API and the Workload Factory.
426*89c4ff92SAndroid Build Coastguard WorkerAt the end of test, the runtime object goes out of scope and the dynamic backend instance is automatically destroyed, and the handle to
427*89c4ff92SAndroid Build Coastguard Workerthe shared object is closed.
428