blob: 883df6fe4de183199a6a994ab86966b5d4765ffd [file] [log] [blame]
Matthew Bentham7c1603a2019-06-21 17:22:23 +01001//
Colm Donelana98e79a2022-12-06 21:32:29 +00002// Copyright © 2017,2022 Arm Ltd and Contributors. All rights reserved.
Matthew Bentham7c1603a2019-06-21 17:22:23 +01003// SPDX-License-Identifier: MIT
4//
Colm Donelana98e79a2022-12-06 21:32:29 +00005
Matthew Bentham7c1603a2019-06-21 17:22:23 +01006
Sadik Armagan1625efc2021-06-10 18:24:34 +01007#include <doctest/doctest.h>
Colm Donelana98e79a2022-12-06 21:32:29 +00008#include <armnn/BackendId.hpp>
9#include <armnn/INetwork.hpp>
10#include <armnn/Tensor.hpp>
11#include <armnn/Types.hpp>
12#include <armnn/backends/ITensorHandle.hpp>
13#include <armnn/backends/ITensorHandleFactory.hpp>
14#include <armnn/backends/TensorHandle.hpp>
15#include <armnn/utility/Assert.hpp>
16#include <reference/RefTensorHandle.hpp>
17#include <reference/RefTensorHandleFactory.hpp>
18#include <reference/RefMemoryManager.hpp>
19#include <memory>
20#include <vector>
21
22namespace armnn
23{
24class Exception;
25class NullPointerException;
26}
Matthew Bentham7c1603a2019-06-21 17:22:23 +010027
Sadik Armagan1625efc2021-06-10 18:24:34 +010028TEST_SUITE("RefTensorHandleTests")
29{
Matthew Bentham7c1603a2019-06-21 17:22:23 +010030using namespace armnn;
31
Sadik Armagan1625efc2021-06-10 18:24:34 +010032TEST_CASE("AcquireAndRelease")
Matthew Bentham7c1603a2019-06-21 17:22:23 +010033{
34 std::shared_ptr<RefMemoryManager> memoryManager = std::make_shared<RefMemoryManager>();
35
Narumol Prangnawarat3b90af62020-06-26 11:00:21 +010036 TensorInfo info({ 1, 1, 1, 1 }, DataType::Float32);
Matthew Bentham7c1603a2019-06-21 17:22:23 +010037 RefTensorHandle handle(info, memoryManager);
38
39 handle.Manage();
40 handle.Allocate();
41
42 memoryManager->Acquire();
43 {
Narumol Prangnawarat3b90af62020-06-26 11:00:21 +010044 float* buffer = reinterpret_cast<float*>(handle.Map());
Matthew Bentham7c1603a2019-06-21 17:22:23 +010045
Sadik Armagan1625efc2021-06-10 18:24:34 +010046 CHECK(buffer != nullptr); // Yields a valid pointer
Matthew Bentham7c1603a2019-06-21 17:22:23 +010047
48 buffer[0] = 2.5f;
49
Sadik Armagan1625efc2021-06-10 18:24:34 +010050 CHECK(buffer[0] == 2.5f); // Memory is writable and readable
Matthew Bentham7c1603a2019-06-21 17:22:23 +010051
52 }
53 memoryManager->Release();
54
55 memoryManager->Acquire();
56 {
Narumol Prangnawarat3b90af62020-06-26 11:00:21 +010057 float* buffer = reinterpret_cast<float*>(handle.Map());
Matthew Bentham7c1603a2019-06-21 17:22:23 +010058
Sadik Armagan1625efc2021-06-10 18:24:34 +010059 CHECK(buffer != nullptr); // Yields a valid pointer
Matthew Bentham7c1603a2019-06-21 17:22:23 +010060
61 buffer[0] = 3.5f;
62
Sadik Armagan1625efc2021-06-10 18:24:34 +010063 CHECK(buffer[0] == 3.5f); // Memory is writable and readable
Matthew Bentham7c1603a2019-06-21 17:22:23 +010064 }
65 memoryManager->Release();
66}
67
Sadik Armagan1625efc2021-06-10 18:24:34 +010068TEST_CASE("RefTensorHandleFactoryMemoryManaged")
Narumol Prangnawarat3b90af62020-06-26 11:00:21 +010069{
70 std::shared_ptr<RefMemoryManager> memoryManager = std::make_shared<RefMemoryManager>();
71 RefTensorHandleFactory handleFactory(memoryManager);
72 TensorInfo info({ 1, 1, 2, 1 }, DataType::Float32);
73
74 // create TensorHandle with memory managed
75 auto handle = handleFactory.CreateTensorHandle(info, true);
76 handle->Manage();
77 handle->Allocate();
78
79 memoryManager->Acquire();
80 {
81 float* buffer = reinterpret_cast<float*>(handle->Map());
Sadik Armagan1625efc2021-06-10 18:24:34 +010082 CHECK(buffer != nullptr); // Yields a valid pointer
Narumol Prangnawarat3b90af62020-06-26 11:00:21 +010083 buffer[0] = 1.5f;
84 buffer[1] = 2.5f;
Sadik Armagan1625efc2021-06-10 18:24:34 +010085 CHECK(buffer[0] == 1.5f); // Memory is writable and readable
86 CHECK(buffer[1] == 2.5f); // Memory is writable and readable
Narumol Prangnawarat3b90af62020-06-26 11:00:21 +010087 }
88 memoryManager->Release();
89
90 memoryManager->Acquire();
91 {
92 float* buffer = reinterpret_cast<float*>(handle->Map());
Sadik Armagan1625efc2021-06-10 18:24:34 +010093 CHECK(buffer != nullptr); // Yields a valid pointer
Narumol Prangnawarat3b90af62020-06-26 11:00:21 +010094 buffer[0] = 3.5f;
95 buffer[1] = 4.5f;
Sadik Armagan1625efc2021-06-10 18:24:34 +010096 CHECK(buffer[0] == 3.5f); // Memory is writable and readable
97 CHECK(buffer[1] == 4.5f); // Memory is writable and readable
Narumol Prangnawarat3b90af62020-06-26 11:00:21 +010098 }
99 memoryManager->Release();
100
101 float testPtr[2] = { 2.5f, 5.5f };
Matthew Bentham6b5f6742022-11-23 18:17:48 +0000102 // Check import overlays contents
103 CHECK(handle->Import(static_cast<void*>(testPtr), MemorySource::Malloc));
104 {
105 float* buffer = reinterpret_cast<float*>(handle->Map());
106 CHECK(buffer != nullptr); // Yields a valid pointer
107 CHECK(buffer[0] == 2.5f); // Memory is writable and readable
108 CHECK(buffer[1] == 5.5f); // Memory is writable and readable
109 }
Narumol Prangnawarat3b90af62020-06-26 11:00:21 +0100110}
111
Sadik Armagan1625efc2021-06-10 18:24:34 +0100112TEST_CASE("RefTensorHandleFactoryImport")
Narumol Prangnawarat3b90af62020-06-26 11:00:21 +0100113{
114 std::shared_ptr<RefMemoryManager> memoryManager = std::make_shared<RefMemoryManager>();
115 RefTensorHandleFactory handleFactory(memoryManager);
116 TensorInfo info({ 1, 1, 2, 1 }, DataType::Float32);
117
118 // create TensorHandle without memory managed
119 auto handle = handleFactory.CreateTensorHandle(info, false);
120 handle->Manage();
121 handle->Allocate();
122 memoryManager->Acquire();
123
Matthew Bentham6b5f6742022-11-23 18:17:48 +0000124 // Check storage has been allocated
125 void* unmanagedStorage = handle->Map();
126 CHECK(unmanagedStorage != nullptr);
Narumol Prangnawarat3b90af62020-06-26 11:00:21 +0100127
Matthew Bentham6b5f6742022-11-23 18:17:48 +0000128 // Check importing overlays the storage
Narumol Prangnawarat3b90af62020-06-26 11:00:21 +0100129 float testPtr[2] = { 2.5f, 5.5f };
Sadik Armagan1625efc2021-06-10 18:24:34 +0100130 CHECK(handle->Import(static_cast<void*>(testPtr), MemorySource::Malloc));
Narumol Prangnawarat3b90af62020-06-26 11:00:21 +0100131 float* buffer = reinterpret_cast<float*>(handle->Map());
Sadik Armagan1625efc2021-06-10 18:24:34 +0100132 CHECK(buffer != nullptr); // Yields a valid pointer after import
133 CHECK(buffer == testPtr); // buffer is pointing to testPtr
Narumol Prangnawarat3b90af62020-06-26 11:00:21 +0100134 // Memory is writable and readable with correct value
Sadik Armagan1625efc2021-06-10 18:24:34 +0100135 CHECK(buffer[0] == 2.5f);
136 CHECK(buffer[1] == 5.5f);
Narumol Prangnawarat3b90af62020-06-26 11:00:21 +0100137 buffer[0] = 3.5f;
138 buffer[1] = 10.0f;
Sadik Armagan1625efc2021-06-10 18:24:34 +0100139 CHECK(buffer[0] == 3.5f);
140 CHECK(buffer[1] == 10.0f);
Narumol Prangnawarat3b90af62020-06-26 11:00:21 +0100141 memoryManager->Release();
142}
143
Sadik Armagan1625efc2021-06-10 18:24:34 +0100144TEST_CASE("RefTensorHandleImport")
Narumol Prangnawarat3b90af62020-06-26 11:00:21 +0100145{
146 TensorInfo info({ 1, 1, 2, 1 }, DataType::Float32);
Matthew Benthamc30abd82022-11-23 12:11:32 +0000147 RefTensorHandle handle(info);
Narumol Prangnawarat3b90af62020-06-26 11:00:21 +0100148
149 handle.Manage();
150 handle.Allocate();
151
Matthew Bentham6b5f6742022-11-23 18:17:48 +0000152 // Check unmanaged memory allocated
153 CHECK(handle.Map());
Narumol Prangnawarat3b90af62020-06-26 11:00:21 +0100154
155 float testPtr[2] = { 2.5f, 5.5f };
Matthew Bentham6b5f6742022-11-23 18:17:48 +0000156 // Check imoport overlays the unamaged memory
Sadik Armagan1625efc2021-06-10 18:24:34 +0100157 CHECK(handle.Import(static_cast<void*>(testPtr), MemorySource::Malloc));
Narumol Prangnawarat3b90af62020-06-26 11:00:21 +0100158 float* buffer = reinterpret_cast<float*>(handle.Map());
Sadik Armagan1625efc2021-06-10 18:24:34 +0100159 CHECK(buffer != nullptr); // Yields a valid pointer after import
160 CHECK(buffer == testPtr); // buffer is pointing to testPtr
Narumol Prangnawarat3b90af62020-06-26 11:00:21 +0100161 // Memory is writable and readable with correct value
Sadik Armagan1625efc2021-06-10 18:24:34 +0100162 CHECK(buffer[0] == 2.5f);
163 CHECK(buffer[1] == 5.5f);
Narumol Prangnawarat3b90af62020-06-26 11:00:21 +0100164 buffer[0] = 3.5f;
165 buffer[1] = 10.0f;
Sadik Armagan1625efc2021-06-10 18:24:34 +0100166 CHECK(buffer[0] == 3.5f);
167 CHECK(buffer[1] == 10.0f);
Narumol Prangnawarat3b90af62020-06-26 11:00:21 +0100168}
169
Sadik Armagan1625efc2021-06-10 18:24:34 +0100170TEST_CASE("RefTensorHandleGetCapabilities")
Narumol Prangnawaratd6568772020-07-22 12:46:51 +0100171{
172 std::shared_ptr<RefMemoryManager> memoryManager = std::make_shared<RefMemoryManager>();
173 RefTensorHandleFactory handleFactory(memoryManager);
174
175 // Builds up the structure of the network.
176 INetworkPtr net(INetwork::Create());
177 IConnectableLayer* input = net->AddInputLayer(0);
178 IConnectableLayer* output = net->AddOutputLayer(0);
179 input->GetOutputSlot(0).Connect(output->GetInputSlot(0));
180
181 std::vector<Capability> capabilities = handleFactory.GetCapabilities(input,
182 output,
183 CapabilityClass::PaddingRequired);
Sadik Armagan1625efc2021-06-10 18:24:34 +0100184 CHECK(capabilities.empty());
Narumol Prangnawaratd6568772020-07-22 12:46:51 +0100185}
186
Sadik Armagan1625efc2021-06-10 18:24:34 +0100187TEST_CASE("RefTensorHandleSupportsInPlaceComputation")
Sadik Armaganab3bd4d2020-08-25 11:48:00 +0100188{
189 std::shared_ptr<RefMemoryManager> memoryManager = std::make_shared<RefMemoryManager>();
190 RefTensorHandleFactory handleFactory(memoryManager);
191
192 // RefTensorHandleFactory does not support InPlaceComputation
193 ARMNN_ASSERT(!(handleFactory.SupportsInPlaceComputation()));
194}
195
Sadik Armagan1625efc2021-06-10 18:24:34 +0100196TEST_CASE("TestManagedConstTensorHandle")
Francis Murtagh4af56162021-04-20 16:37:55 +0100197{
198 // Initialize arguments
199 void* mem = nullptr;
200 TensorInfo info;
201
James Conroy1f58f032021-04-27 17:13:27 +0100202 // Use PassthroughTensor as others are abstract
203 auto passThroughHandle = std::make_shared<PassthroughTensorHandle>(info, mem);
Francis Murtagh4af56162021-04-20 16:37:55 +0100204
205 // Test managed handle is initialized with m_Mapped unset and once Map() called its set
206 ManagedConstTensorHandle managedHandle(passThroughHandle);
Sadik Armagan1625efc2021-06-10 18:24:34 +0100207 CHECK(!managedHandle.IsMapped());
Francis Murtagh4af56162021-04-20 16:37:55 +0100208 managedHandle.Map();
Sadik Armagan1625efc2021-06-10 18:24:34 +0100209 CHECK(managedHandle.IsMapped());
Francis Murtagh4af56162021-04-20 16:37:55 +0100210
211 // Test it can then be unmapped
212 managedHandle.Unmap();
Sadik Armagan1625efc2021-06-10 18:24:34 +0100213 CHECK(!managedHandle.IsMapped());
Francis Murtagh4af56162021-04-20 16:37:55 +0100214
215 // Test member function
Sadik Armagan1625efc2021-06-10 18:24:34 +0100216 CHECK(managedHandle.GetTensorInfo() == info);
Francis Murtagh4af56162021-04-20 16:37:55 +0100217
218 // Test that nullptr tensor handle doesn't get mapped
219 ManagedConstTensorHandle managedHandleNull(nullptr);
Sadik Armagan1625efc2021-06-10 18:24:34 +0100220 CHECK(!managedHandleNull.IsMapped());
221 CHECK_THROWS_AS(managedHandleNull.Map(), armnn::Exception);
222 CHECK(!managedHandleNull.IsMapped());
Francis Murtagh4af56162021-04-20 16:37:55 +0100223
224 // Check Unmap() when m_Mapped already false
225 managedHandleNull.Unmap();
Sadik Armagan1625efc2021-06-10 18:24:34 +0100226 CHECK(!managedHandleNull.IsMapped());
Francis Murtagh4af56162021-04-20 16:37:55 +0100227}
228
Ferran Balaguerc33882d2019-08-21 13:59:13 +0100229#if !defined(__ANDROID__)
230// Only run these tests on non Android platforms
Sadik Armagan1625efc2021-06-10 18:24:34 +0100231TEST_CASE("CheckSourceType")
Ferran Balaguerbfeb2712019-08-07 15:14:56 +0100232{
Ferran Balaguerbfeb2712019-08-07 15:14:56 +0100233 TensorInfo info({1}, DataType::Float32);
Matthew Benthamc30abd82022-11-23 12:11:32 +0000234 RefTensorHandle handle(info);
Ferran Balaguerbfeb2712019-08-07 15:14:56 +0100235
Ferran Balaguerbfeb2712019-08-07 15:14:56 +0100236 int* testPtr = new int(4);
237
238 // Not supported
Sadik Armagan1625efc2021-06-10 18:24:34 +0100239 CHECK(!handle.Import(static_cast<void *>(testPtr), MemorySource::DmaBuf));
Ferran Balaguerbfeb2712019-08-07 15:14:56 +0100240
241 // Not supported
Sadik Armagan1625efc2021-06-10 18:24:34 +0100242 CHECK(!handle.Import(static_cast<void *>(testPtr), MemorySource::DmaBufProtected));
Ferran Balaguerbfeb2712019-08-07 15:14:56 +0100243
244 // Supported
Sadik Armagan1625efc2021-06-10 18:24:34 +0100245 CHECK(handle.Import(static_cast<void *>(testPtr), MemorySource::Malloc));
Ferran Balaguer1cd451c2019-08-22 14:09:44 +0100246
247 delete testPtr;
Ferran Balaguerbfeb2712019-08-07 15:14:56 +0100248}
249
Sadik Armagan1625efc2021-06-10 18:24:34 +0100250TEST_CASE("ReusePointer")
Ferran Balaguerbfeb2712019-08-07 15:14:56 +0100251{
Ferran Balaguerbfeb2712019-08-07 15:14:56 +0100252 TensorInfo info({1}, DataType::Float32);
Matthew Benthamc30abd82022-11-23 12:11:32 +0000253 RefTensorHandle handle(info);
Ferran Balaguerbfeb2712019-08-07 15:14:56 +0100254
Ferran Balaguerbfeb2712019-08-07 15:14:56 +0100255 int* testPtr = new int(4);
256
257 handle.Import(static_cast<void *>(testPtr), MemorySource::Malloc);
258
259 // Reusing previously Imported pointer
Sadik Armagan1625efc2021-06-10 18:24:34 +0100260 CHECK(handle.Import(static_cast<void *>(testPtr), MemorySource::Malloc));
Ferran Balaguer1cd451c2019-08-22 14:09:44 +0100261
262 delete testPtr;
Ferran Balaguerbfeb2712019-08-07 15:14:56 +0100263}
264
Sadik Armagan1625efc2021-06-10 18:24:34 +0100265TEST_CASE("MisalignedPointer")
Ferran Balaguerbfeb2712019-08-07 15:14:56 +0100266{
Ferran Balaguerbfeb2712019-08-07 15:14:56 +0100267 TensorInfo info({2}, DataType::Float32);
Matthew Benthamc30abd82022-11-23 12:11:32 +0000268 RefTensorHandle handle(info);
Ferran Balaguerbfeb2712019-08-07 15:14:56 +0100269
Aron Virginas-Tard9f7c8b2019-09-13 13:37:03 +0100270 // Allocate a 2 int array
Ferran Balaguerbfeb2712019-08-07 15:14:56 +0100271 int* testPtr = new int[2];
Ferran Balaguerbfeb2712019-08-07 15:14:56 +0100272
Aron Virginas-Tard9f7c8b2019-09-13 13:37:03 +0100273 // Increment pointer by 1 byte
274 void* misalignedPtr = static_cast<void*>(reinterpret_cast<char*>(testPtr) + 1);
275
Sadik Armagan1625efc2021-06-10 18:24:34 +0100276 CHECK(!handle.Import(misalignedPtr, MemorySource::Malloc));
Ferran Balaguerbfeb2712019-08-07 15:14:56 +0100277
278 delete[] testPtr;
279}
280
Nikhil Raj53e06592022-01-05 16:04:08 +0000281TEST_CASE("CheckCanBeImported")
282{
283 TensorInfo info({1}, DataType::Float32);
Matthew Benthamc30abd82022-11-23 12:11:32 +0000284 RefTensorHandle handle(info);
Nikhil Raj53e06592022-01-05 16:04:08 +0000285
286 int* testPtr = new int(4);
287
288 // Not supported
289 CHECK(!handle.CanBeImported(static_cast<void *>(testPtr), MemorySource::DmaBuf));
290
291 // Supported
292 CHECK(handle.CanBeImported(static_cast<void *>(testPtr), MemorySource::Malloc));
293
294 delete testPtr;
295
296}
297
298TEST_CASE("MisalignedCanBeImported")
299{
300 TensorInfo info({2}, DataType::Float32);
Matthew Benthamc30abd82022-11-23 12:11:32 +0000301 RefTensorHandle handle(info);
Nikhil Raj53e06592022-01-05 16:04:08 +0000302
303 // Allocate a 2 int array
304 int* testPtr = new int[2];
305
306 // Increment pointer by 1 byte
307 void* misalignedPtr = static_cast<void*>(reinterpret_cast<char*>(testPtr) + 1);
308
309 CHECK(!handle.Import(misalignedPtr, MemorySource::Malloc));
310
311 delete[] testPtr;
312}
313
Ferran Balaguerc33882d2019-08-21 13:59:13 +0100314#endif
315
Sadik Armagan1625efc2021-06-10 18:24:34 +0100316}