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