blob: 18b3745a2e83e38abfc5a57184c4091a5a35bd47 [file] [log] [blame]
David Beck32cbb0c2018-10-09 15:46:08 +01001//
2// Copyright © 2017 Arm Ltd. All rights reserved.
3// SPDX-License-Identifier: MIT
4//
David Beck32cbb0c2018-10-09 15:46:08 +01005
David Beck32cbb0c2018-10-09 15:46:08 +01006#include <armnn/Types.hpp>
Matteo Martincighc601aa62019-10-29 15:03:22 +00007#include <armnn/BackendRegistry.hpp>
David Beck32cbb0c2018-10-09 15:46:08 +01008
Matteo Martincighe5b8eb92019-11-28 15:45:42 +00009#include <armnn/backends/IBackendInternal.hpp>
Jim Flynne1fdd282021-10-26 21:26:10 +010010#include <backendsCommon/memoryOptimizerStrategyLibrary/strategies/ConstantMemoryStrategy.hpp>
Francis Murtagh5dc64fe2021-01-25 10:18:10 +000011#include <reference/RefBackend.hpp>
Aron Virginas-Tarc9cc8042018-11-01 16:15:57 +000012
Sadik Armagan1625efc2021-06-10 18:24:34 +010013#include <doctest/doctest.h>
Aron Virginas-Tarc9cc8042018-11-01 16:15:57 +000014
David Beck32cbb0c2018-10-09 15:46:08 +010015namespace
16{
17
18class SwapRegistryStorage : public armnn::BackendRegistry
19{
20public:
21 SwapRegistryStorage() : armnn::BackendRegistry()
22 {
David Beck3e9e1152018-10-17 14:17:50 +010023 Swap(armnn::BackendRegistryInstance(), m_TempStorage);
David Beck32cbb0c2018-10-09 15:46:08 +010024 }
25
26 ~SwapRegistryStorage()
27 {
David Beck3e9e1152018-10-17 14:17:50 +010028 Swap(armnn::BackendRegistryInstance(),m_TempStorage);
David Beck32cbb0c2018-10-09 15:46:08 +010029 }
30
31private:
David Beck3e9e1152018-10-17 14:17:50 +010032 FactoryStorage m_TempStorage;
David Beck32cbb0c2018-10-09 15:46:08 +010033};
34
35}
36
Sadik Armagan1625efc2021-06-10 18:24:34 +010037TEST_SUITE("BackendRegistryTests")
38{
39TEST_CASE("SwapRegistry")
David Beck32cbb0c2018-10-09 15:46:08 +010040{
David Beck3e9e1152018-10-17 14:17:50 +010041 using namespace armnn;
42 auto nFactories = BackendRegistryInstance().Size();
David Beck32cbb0c2018-10-09 15:46:08 +010043 {
44 SwapRegistryStorage helper;
Sadik Armagan1625efc2021-06-10 18:24:34 +010045 CHECK(BackendRegistryInstance().Size() == 0);
David Beck32cbb0c2018-10-09 15:46:08 +010046 }
Sadik Armagan1625efc2021-06-10 18:24:34 +010047 CHECK(BackendRegistryInstance().Size() == nFactories);
David Beck32cbb0c2018-10-09 15:46:08 +010048}
49
Sadik Armagan1625efc2021-06-10 18:24:34 +010050TEST_CASE("TestRegistryHelper")
David Beck32cbb0c2018-10-09 15:46:08 +010051{
David Beck3e9e1152018-10-17 14:17:50 +010052 using namespace armnn;
David Beck32cbb0c2018-10-09 15:46:08 +010053 SwapRegistryStorage helper;
54
55 bool called = false;
David Beck3e9e1152018-10-17 14:17:50 +010056
David Beck111b5d92018-11-12 14:59:37 +000057 BackendRegistry::StaticRegistryInitializer factoryHelper(
David Beck3e9e1152018-10-17 14:17:50 +010058 BackendRegistryInstance(),
59 "HelloWorld",
David Beck9efb57d2018-11-05 13:40:33 +000060 [&called]()
David Beck3e9e1152018-10-17 14:17:50 +010061 {
62 called = true;
David Beck29c75de2018-10-23 13:35:58 +010063 return armnn::IBackendInternalUniquePtr(nullptr);
David Beck3e9e1152018-10-17 14:17:50 +010064 }
65 );
David Beck32cbb0c2018-10-09 15:46:08 +010066
67 // sanity check: the factory has not been called yet
Sadik Armagan1625efc2021-06-10 18:24:34 +010068 CHECK(called == false);
David Beck32cbb0c2018-10-09 15:46:08 +010069
David Beck3e9e1152018-10-17 14:17:50 +010070 auto factoryFunction = BackendRegistryInstance().GetFactory("HelloWorld");
David Beck32cbb0c2018-10-09 15:46:08 +010071
72 // sanity check: the factory still not called
Sadik Armagan1625efc2021-06-10 18:24:34 +010073 CHECK(called == false);
David Beck32cbb0c2018-10-09 15:46:08 +010074
David Beck9efb57d2018-11-05 13:40:33 +000075 factoryFunction();
Sadik Armagan1625efc2021-06-10 18:24:34 +010076 CHECK(called == true);
David Monahanc1536d62020-02-12 15:52:35 +000077 BackendRegistryInstance().Deregister("HelloWorld");
David Beck32cbb0c2018-10-09 15:46:08 +010078}
79
Sadik Armagan1625efc2021-06-10 18:24:34 +010080TEST_CASE("TestDirectCallToRegistry")
David Beck32cbb0c2018-10-09 15:46:08 +010081{
David Beck3e9e1152018-10-17 14:17:50 +010082 using namespace armnn;
David Beck32cbb0c2018-10-09 15:46:08 +010083 SwapRegistryStorage helper;
84
85 bool called = false;
David Beck3e9e1152018-10-17 14:17:50 +010086 BackendRegistryInstance().Register(
87 "HelloWorld",
David Beck9efb57d2018-11-05 13:40:33 +000088 [&called]()
David Beck3e9e1152018-10-17 14:17:50 +010089 {
90 called = true;
David Beck29c75de2018-10-23 13:35:58 +010091 return armnn::IBackendInternalUniquePtr(nullptr);
David Beck3e9e1152018-10-17 14:17:50 +010092 }
93 );
David Beck32cbb0c2018-10-09 15:46:08 +010094
95 // sanity check: the factory has not been called yet
Sadik Armagan1625efc2021-06-10 18:24:34 +010096 CHECK(called == false);
David Beck32cbb0c2018-10-09 15:46:08 +010097
David Beck3e9e1152018-10-17 14:17:50 +010098 auto factoryFunction = BackendRegistryInstance().GetFactory("HelloWorld");
David Beck32cbb0c2018-10-09 15:46:08 +010099
100 // sanity check: the factory still not called
Sadik Armagan1625efc2021-06-10 18:24:34 +0100101 CHECK(called == false);
David Beck32cbb0c2018-10-09 15:46:08 +0100102
David Beck9efb57d2018-11-05 13:40:33 +0000103 factoryFunction();
Sadik Armagan1625efc2021-06-10 18:24:34 +0100104 CHECK(called == true);
David Monahanc1536d62020-02-12 15:52:35 +0000105 BackendRegistryInstance().Deregister("HelloWorld");
David Beck32cbb0c2018-10-09 15:46:08 +0100106}
107
Francis Murtagh5dc64fe2021-01-25 10:18:10 +0000108// Test that backends can throw exceptions during their factory function to prevent loading in an unsuitable
109// environment. For example Neon Backend loading on armhf device without neon support.
110// In reality the dynamic backend is loaded in during the LoadDynamicBackends(options.m_DynamicBackendsPath)
111// step of runtime constructor, then the factory function is called to check if supported, in case
112// of Neon not being detected the exception is raised and so the backend is not added to the supportedBackends
113// list
114
Sadik Armagan1625efc2021-06-10 18:24:34 +0100115TEST_CASE("ThrowBackendUnavailableException")
Francis Murtagh5dc64fe2021-01-25 10:18:10 +0000116{
117 using namespace armnn;
118
119 const BackendId mockBackendId("MockDynamicBackend");
120
Matthew Benthama369b892021-07-05 09:20:23 +0100121 const std::string exceptionMessage("Mock error message to test unavailable backend");
Francis Murtagh5dc64fe2021-01-25 10:18:10 +0000122
Matthew Benthama369b892021-07-05 09:20:23 +0100123 // Register the mock backend with a factory function lambda that always throws
Francis Murtagh5dc64fe2021-01-25 10:18:10 +0000124 BackendRegistryInstance().Register(mockBackendId,
125 [exceptionMessage]()
126 {
Francis Murtagh5dc64fe2021-01-25 10:18:10 +0000127 throw armnn::BackendUnavailableException(exceptionMessage);
Matthew Benthama369b892021-07-05 09:20:23 +0100128 return IBackendInternalUniquePtr(); // Satisfy return type
Francis Murtagh5dc64fe2021-01-25 10:18:10 +0000129 });
130
131 // Get the factory function of the mock backend
132 auto factoryFunc = BackendRegistryInstance().GetFactory(mockBackendId);
133
134 try
135 {
136 // Call the factory function as done during runtime backend registering
137 auto backend = factoryFunc();
Matthew Benthama369b892021-07-05 09:20:23 +0100138 FAIL("Expected exception to have been thrown");
Francis Murtagh5dc64fe2021-01-25 10:18:10 +0000139 }
140 catch (const BackendUnavailableException& e)
141 {
142 // Caught
Sadik Armagan1625efc2021-06-10 18:24:34 +0100143 CHECK_EQ(e.what(), exceptionMessage);
Francis Murtagh5dc64fe2021-01-25 10:18:10 +0000144 }
Colm Donelan380c1a02021-08-17 00:52:23 +0100145 // Clean up the registry for the next test.
146 BackendRegistryInstance().Deregister(mockBackendId);
Francis Murtagh5dc64fe2021-01-25 10:18:10 +0000147}
148
Sadik Armaganb8a26d82021-10-04 15:13:11 +0100149#if defined(ARMNNREF_ENABLED)
150TEST_CASE("RegisterMemoryOptimizerStrategy")
151{
152 using namespace armnn;
153
154 const BackendId cpuRefBackendId(armnn::Compute::CpuRef);
155 CHECK(BackendRegistryInstance().GetMemoryOptimizerStrategies().empty());
156
157 // Register the memory optimizer
158 std::shared_ptr<IMemoryOptimizerStrategy> memoryOptimizerStrategy =
Jim Flynne1fdd282021-10-26 21:26:10 +0100159 std::make_shared<ConstantMemoryStrategy>();
Sadik Armaganb8a26d82021-10-04 15:13:11 +0100160 BackendRegistryInstance().RegisterMemoryOptimizerStrategy(cpuRefBackendId, memoryOptimizerStrategy);
161 CHECK(!BackendRegistryInstance().GetMemoryOptimizerStrategies().empty());
162 CHECK(BackendRegistryInstance().GetMemoryOptimizerStrategies().size() == 1);
163 // De-register the memory optimizer
164 BackendRegistryInstance().DeregisterMemoryOptimizerStrategy(cpuRefBackendId);
165 CHECK(BackendRegistryInstance().GetMemoryOptimizerStrategies().empty());
166}
167#endif
168
Sadik Armagan1625efc2021-06-10 18:24:34 +0100169}