David Beck | 32cbb0c | 2018-10-09 15:46:08 +0100 | [diff] [blame] | 1 | // |
| 2 | // Copyright © 2017 Arm Ltd. All rights reserved. |
| 3 | // SPDX-License-Identifier: MIT |
| 4 | // |
David Beck | 32cbb0c | 2018-10-09 15:46:08 +0100 | [diff] [blame] | 5 | |
David Beck | 32cbb0c | 2018-10-09 15:46:08 +0100 | [diff] [blame] | 6 | #include <armnn/Types.hpp> |
Matteo Martincigh | c601aa6 | 2019-10-29 15:03:22 +0000 | [diff] [blame] | 7 | #include <armnn/BackendRegistry.hpp> |
David Beck | 32cbb0c | 2018-10-09 15:46:08 +0100 | [diff] [blame] | 8 | |
Matteo Martincigh | e5b8eb9 | 2019-11-28 15:45:42 +0000 | [diff] [blame] | 9 | #include <armnn/backends/IBackendInternal.hpp> |
Jim Flynn | e1fdd28 | 2021-10-26 21:26:10 +0100 | [diff] [blame] | 10 | #include <backendsCommon/memoryOptimizerStrategyLibrary/strategies/ConstantMemoryStrategy.hpp> |
Francis Murtagh | 5dc64fe | 2021-01-25 10:18:10 +0000 | [diff] [blame] | 11 | #include <reference/RefBackend.hpp> |
Aron Virginas-Tar | c9cc804 | 2018-11-01 16:15:57 +0000 | [diff] [blame] | 12 | |
Sadik Armagan | 1625efc | 2021-06-10 18:24:34 +0100 | [diff] [blame] | 13 | #include <doctest/doctest.h> |
Aron Virginas-Tar | c9cc804 | 2018-11-01 16:15:57 +0000 | [diff] [blame] | 14 | |
David Beck | 32cbb0c | 2018-10-09 15:46:08 +0100 | [diff] [blame] | 15 | namespace |
| 16 | { |
| 17 | |
| 18 | class SwapRegistryStorage : public armnn::BackendRegistry |
| 19 | { |
| 20 | public: |
| 21 | SwapRegistryStorage() : armnn::BackendRegistry() |
| 22 | { |
David Beck | 3e9e115 | 2018-10-17 14:17:50 +0100 | [diff] [blame] | 23 | Swap(armnn::BackendRegistryInstance(), m_TempStorage); |
David Beck | 32cbb0c | 2018-10-09 15:46:08 +0100 | [diff] [blame] | 24 | } |
| 25 | |
| 26 | ~SwapRegistryStorage() |
| 27 | { |
David Beck | 3e9e115 | 2018-10-17 14:17:50 +0100 | [diff] [blame] | 28 | Swap(armnn::BackendRegistryInstance(),m_TempStorage); |
David Beck | 32cbb0c | 2018-10-09 15:46:08 +0100 | [diff] [blame] | 29 | } |
| 30 | |
| 31 | private: |
David Beck | 3e9e115 | 2018-10-17 14:17:50 +0100 | [diff] [blame] | 32 | FactoryStorage m_TempStorage; |
David Beck | 32cbb0c | 2018-10-09 15:46:08 +0100 | [diff] [blame] | 33 | }; |
| 34 | |
| 35 | } |
| 36 | |
Sadik Armagan | 1625efc | 2021-06-10 18:24:34 +0100 | [diff] [blame] | 37 | TEST_SUITE("BackendRegistryTests") |
| 38 | { |
| 39 | TEST_CASE("SwapRegistry") |
David Beck | 32cbb0c | 2018-10-09 15:46:08 +0100 | [diff] [blame] | 40 | { |
David Beck | 3e9e115 | 2018-10-17 14:17:50 +0100 | [diff] [blame] | 41 | using namespace armnn; |
| 42 | auto nFactories = BackendRegistryInstance().Size(); |
David Beck | 32cbb0c | 2018-10-09 15:46:08 +0100 | [diff] [blame] | 43 | { |
| 44 | SwapRegistryStorage helper; |
Sadik Armagan | 1625efc | 2021-06-10 18:24:34 +0100 | [diff] [blame] | 45 | CHECK(BackendRegistryInstance().Size() == 0); |
David Beck | 32cbb0c | 2018-10-09 15:46:08 +0100 | [diff] [blame] | 46 | } |
Sadik Armagan | 1625efc | 2021-06-10 18:24:34 +0100 | [diff] [blame] | 47 | CHECK(BackendRegistryInstance().Size() == nFactories); |
David Beck | 32cbb0c | 2018-10-09 15:46:08 +0100 | [diff] [blame] | 48 | } |
| 49 | |
Sadik Armagan | 1625efc | 2021-06-10 18:24:34 +0100 | [diff] [blame] | 50 | TEST_CASE("TestRegistryHelper") |
David Beck | 32cbb0c | 2018-10-09 15:46:08 +0100 | [diff] [blame] | 51 | { |
David Beck | 3e9e115 | 2018-10-17 14:17:50 +0100 | [diff] [blame] | 52 | using namespace armnn; |
David Beck | 32cbb0c | 2018-10-09 15:46:08 +0100 | [diff] [blame] | 53 | SwapRegistryStorage helper; |
| 54 | |
| 55 | bool called = false; |
David Beck | 3e9e115 | 2018-10-17 14:17:50 +0100 | [diff] [blame] | 56 | |
David Beck | 111b5d9 | 2018-11-12 14:59:37 +0000 | [diff] [blame] | 57 | BackendRegistry::StaticRegistryInitializer factoryHelper( |
David Beck | 3e9e115 | 2018-10-17 14:17:50 +0100 | [diff] [blame] | 58 | BackendRegistryInstance(), |
| 59 | "HelloWorld", |
David Beck | 9efb57d | 2018-11-05 13:40:33 +0000 | [diff] [blame] | 60 | [&called]() |
David Beck | 3e9e115 | 2018-10-17 14:17:50 +0100 | [diff] [blame] | 61 | { |
| 62 | called = true; |
David Beck | 29c75de | 2018-10-23 13:35:58 +0100 | [diff] [blame] | 63 | return armnn::IBackendInternalUniquePtr(nullptr); |
David Beck | 3e9e115 | 2018-10-17 14:17:50 +0100 | [diff] [blame] | 64 | } |
| 65 | ); |
David Beck | 32cbb0c | 2018-10-09 15:46:08 +0100 | [diff] [blame] | 66 | |
| 67 | // sanity check: the factory has not been called yet |
Sadik Armagan | 1625efc | 2021-06-10 18:24:34 +0100 | [diff] [blame] | 68 | CHECK(called == false); |
David Beck | 32cbb0c | 2018-10-09 15:46:08 +0100 | [diff] [blame] | 69 | |
David Beck | 3e9e115 | 2018-10-17 14:17:50 +0100 | [diff] [blame] | 70 | auto factoryFunction = BackendRegistryInstance().GetFactory("HelloWorld"); |
David Beck | 32cbb0c | 2018-10-09 15:46:08 +0100 | [diff] [blame] | 71 | |
| 72 | // sanity check: the factory still not called |
Sadik Armagan | 1625efc | 2021-06-10 18:24:34 +0100 | [diff] [blame] | 73 | CHECK(called == false); |
David Beck | 32cbb0c | 2018-10-09 15:46:08 +0100 | [diff] [blame] | 74 | |
David Beck | 9efb57d | 2018-11-05 13:40:33 +0000 | [diff] [blame] | 75 | factoryFunction(); |
Sadik Armagan | 1625efc | 2021-06-10 18:24:34 +0100 | [diff] [blame] | 76 | CHECK(called == true); |
David Monahan | c1536d6 | 2020-02-12 15:52:35 +0000 | [diff] [blame] | 77 | BackendRegistryInstance().Deregister("HelloWorld"); |
David Beck | 32cbb0c | 2018-10-09 15:46:08 +0100 | [diff] [blame] | 78 | } |
| 79 | |
Sadik Armagan | 1625efc | 2021-06-10 18:24:34 +0100 | [diff] [blame] | 80 | TEST_CASE("TestDirectCallToRegistry") |
David Beck | 32cbb0c | 2018-10-09 15:46:08 +0100 | [diff] [blame] | 81 | { |
David Beck | 3e9e115 | 2018-10-17 14:17:50 +0100 | [diff] [blame] | 82 | using namespace armnn; |
David Beck | 32cbb0c | 2018-10-09 15:46:08 +0100 | [diff] [blame] | 83 | SwapRegistryStorage helper; |
| 84 | |
| 85 | bool called = false; |
David Beck | 3e9e115 | 2018-10-17 14:17:50 +0100 | [diff] [blame] | 86 | BackendRegistryInstance().Register( |
| 87 | "HelloWorld", |
David Beck | 9efb57d | 2018-11-05 13:40:33 +0000 | [diff] [blame] | 88 | [&called]() |
David Beck | 3e9e115 | 2018-10-17 14:17:50 +0100 | [diff] [blame] | 89 | { |
| 90 | called = true; |
David Beck | 29c75de | 2018-10-23 13:35:58 +0100 | [diff] [blame] | 91 | return armnn::IBackendInternalUniquePtr(nullptr); |
David Beck | 3e9e115 | 2018-10-17 14:17:50 +0100 | [diff] [blame] | 92 | } |
| 93 | ); |
David Beck | 32cbb0c | 2018-10-09 15:46:08 +0100 | [diff] [blame] | 94 | |
| 95 | // sanity check: the factory has not been called yet |
Sadik Armagan | 1625efc | 2021-06-10 18:24:34 +0100 | [diff] [blame] | 96 | CHECK(called == false); |
David Beck | 32cbb0c | 2018-10-09 15:46:08 +0100 | [diff] [blame] | 97 | |
David Beck | 3e9e115 | 2018-10-17 14:17:50 +0100 | [diff] [blame] | 98 | auto factoryFunction = BackendRegistryInstance().GetFactory("HelloWorld"); |
David Beck | 32cbb0c | 2018-10-09 15:46:08 +0100 | [diff] [blame] | 99 | |
| 100 | // sanity check: the factory still not called |
Sadik Armagan | 1625efc | 2021-06-10 18:24:34 +0100 | [diff] [blame] | 101 | CHECK(called == false); |
David Beck | 32cbb0c | 2018-10-09 15:46:08 +0100 | [diff] [blame] | 102 | |
David Beck | 9efb57d | 2018-11-05 13:40:33 +0000 | [diff] [blame] | 103 | factoryFunction(); |
Sadik Armagan | 1625efc | 2021-06-10 18:24:34 +0100 | [diff] [blame] | 104 | CHECK(called == true); |
David Monahan | c1536d6 | 2020-02-12 15:52:35 +0000 | [diff] [blame] | 105 | BackendRegistryInstance().Deregister("HelloWorld"); |
David Beck | 32cbb0c | 2018-10-09 15:46:08 +0100 | [diff] [blame] | 106 | } |
| 107 | |
Francis Murtagh | 5dc64fe | 2021-01-25 10:18:10 +0000 | [diff] [blame] | 108 | // 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 Armagan | 1625efc | 2021-06-10 18:24:34 +0100 | [diff] [blame] | 115 | TEST_CASE("ThrowBackendUnavailableException") |
Francis Murtagh | 5dc64fe | 2021-01-25 10:18:10 +0000 | [diff] [blame] | 116 | { |
| 117 | using namespace armnn; |
| 118 | |
| 119 | const BackendId mockBackendId("MockDynamicBackend"); |
| 120 | |
Matthew Bentham | a369b89 | 2021-07-05 09:20:23 +0100 | [diff] [blame] | 121 | const std::string exceptionMessage("Mock error message to test unavailable backend"); |
Francis Murtagh | 5dc64fe | 2021-01-25 10:18:10 +0000 | [diff] [blame] | 122 | |
Matthew Bentham | a369b89 | 2021-07-05 09:20:23 +0100 | [diff] [blame] | 123 | // Register the mock backend with a factory function lambda that always throws |
Francis Murtagh | 5dc64fe | 2021-01-25 10:18:10 +0000 | [diff] [blame] | 124 | BackendRegistryInstance().Register(mockBackendId, |
| 125 | [exceptionMessage]() |
| 126 | { |
Francis Murtagh | 5dc64fe | 2021-01-25 10:18:10 +0000 | [diff] [blame] | 127 | throw armnn::BackendUnavailableException(exceptionMessage); |
Matthew Bentham | a369b89 | 2021-07-05 09:20:23 +0100 | [diff] [blame] | 128 | return IBackendInternalUniquePtr(); // Satisfy return type |
Francis Murtagh | 5dc64fe | 2021-01-25 10:18:10 +0000 | [diff] [blame] | 129 | }); |
| 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 Bentham | a369b89 | 2021-07-05 09:20:23 +0100 | [diff] [blame] | 138 | FAIL("Expected exception to have been thrown"); |
Francis Murtagh | 5dc64fe | 2021-01-25 10:18:10 +0000 | [diff] [blame] | 139 | } |
| 140 | catch (const BackendUnavailableException& e) |
| 141 | { |
| 142 | // Caught |
Sadik Armagan | 1625efc | 2021-06-10 18:24:34 +0100 | [diff] [blame] | 143 | CHECK_EQ(e.what(), exceptionMessage); |
Francis Murtagh | 5dc64fe | 2021-01-25 10:18:10 +0000 | [diff] [blame] | 144 | } |
Colm Donelan | 380c1a0 | 2021-08-17 00:52:23 +0100 | [diff] [blame] | 145 | // Clean up the registry for the next test. |
| 146 | BackendRegistryInstance().Deregister(mockBackendId); |
Francis Murtagh | 5dc64fe | 2021-01-25 10:18:10 +0000 | [diff] [blame] | 147 | } |
| 148 | |
Sadik Armagan | b8a26d8 | 2021-10-04 15:13:11 +0100 | [diff] [blame] | 149 | #if defined(ARMNNREF_ENABLED) |
| 150 | TEST_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 Flynn | e1fdd28 | 2021-10-26 21:26:10 +0100 | [diff] [blame] | 159 | std::make_shared<ConstantMemoryStrategy>(); |
Sadik Armagan | b8a26d8 | 2021-10-04 15:13:11 +0100 | [diff] [blame] | 160 | 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 Armagan | 1625efc | 2021-06-10 18:24:34 +0100 | [diff] [blame] | 169 | } |