blob: 3c8bd678c47f662d2b6c9bbf2cc6357b2a270617 [file] [log] [blame]
David Monahane4a41dc2021-04-14 16:55:36 +01001//
2// Copyright © 2021 Arm Ltd and Contributors. All rights reserved.
3// SPDX-License-Identifier: MIT
4//
5
6#include <arm_compute/runtime/CL/functions/CLActivationLayer.h>
7
8#include <cl/ClImportTensorHandle.hpp>
9#include <cl/ClImportTensorHandleFactory.hpp>
10#include <cl/test/ClContextControlFixture.hpp>
11
12#include <boost/test/unit_test.hpp>
13
Narumol Prangnawarate5f0b242021-05-07 17:52:36 +010014#include <armnn/IRuntime.hpp>
15#include <armnn/INetwork.hpp>
16
David Monahane4a41dc2021-04-14 16:55:36 +010017using namespace armnn;
18
19BOOST_AUTO_TEST_SUITE(ClImportTensorHandleTests)
20
21BOOST_FIXTURE_TEST_CASE(ClMallocImport, ClContextControlFixture)
22{
23 ClImportTensorHandleFactory handleFactory(static_cast<MemorySourceFlags>(MemorySource::Malloc),
24 static_cast<MemorySourceFlags>(MemorySource::Malloc));
25
26 TensorInfo info({ 1, 24, 16, 3 }, DataType::Float32);
27 unsigned int numElements = info.GetNumElements();
28
29 // create TensorHandle for memory import
30 auto handle = handleFactory.CreateTensorHandle(info);
31
32 // Get CLtensor
33 arm_compute::CLTensor& tensor = PolymorphicDowncast<ClImportTensorHandle*>(handle.get())->GetTensor();
34
35 // Create and configure activation function
36 const arm_compute::ActivationLayerInfo act_info(arm_compute::ActivationLayerInfo::ActivationFunction::RELU);
37 arm_compute::CLActivationLayer act_func;
38 act_func.configure(&tensor, nullptr, act_info);
39
40 // Allocate user memory
41 const size_t totalBytes = tensor.info()->total_size();
42 const size_t alignment =
43 arm_compute::CLKernelLibrary::get().get_device().getInfo<CL_DEVICE_GLOBAL_MEM_CACHELINE_SIZE>();
Narumol Prangnawarate5f0b242021-05-07 17:52:36 +010044 size_t space = totalBytes + alignment + alignment;
David Monahane4a41dc2021-04-14 16:55:36 +010045 auto testData = std::make_unique<uint8_t[]>(space);
46 void* alignedPtr = testData.get();
47 BOOST_CHECK(std::align(alignment, totalBytes, alignedPtr, space));
48
49 // Import memory
50 BOOST_CHECK(handle->Import(alignedPtr, armnn::MemorySource::Malloc));
51
52 // Input with negative values
53 auto* typedPtr = reinterpret_cast<float*>(alignedPtr);
54 std::fill_n(typedPtr, numElements, -5.0f);
55
56 // Execute function and sync
57 act_func.run();
58 arm_compute::CLScheduler::get().sync();
59
60 // Validate result by checking that the output has no negative values
61 for(unsigned int i = 0; i < numElements; ++i)
62 {
Narumol Prangnawarate5f0b242021-05-07 17:52:36 +010063 BOOST_TEST(typedPtr[i] >= 0);
David Monahane4a41dc2021-04-14 16:55:36 +010064 }
65}
66
67BOOST_FIXTURE_TEST_CASE(ClIncorrectMemorySourceImport, ClContextControlFixture)
68{
69 ClImportTensorHandleFactory handleFactory(static_cast<MemorySourceFlags>(MemorySource::Malloc),
70 static_cast<MemorySourceFlags>(MemorySource::Malloc));
71
72 TensorInfo info({ 1, 24, 16, 3 }, DataType::Float32);
73
74 // create TensorHandle for memory import
75 auto handle = handleFactory.CreateTensorHandle(info);
76
77 // Get CLtensor
78 arm_compute::CLTensor& tensor = PolymorphicDowncast<ClImportTensorHandle*>(handle.get())->GetTensor();
79
80 // Allocate user memory
81 const size_t totalBytes = tensor.info()->total_size();
82 const size_t alignment =
83 arm_compute::CLKernelLibrary::get().get_device().getInfo<CL_DEVICE_GLOBAL_MEM_CACHELINE_SIZE>();
Narumol Prangnawarate5f0b242021-05-07 17:52:36 +010084 size_t space = totalBytes + alignment + alignment;
David Monahane4a41dc2021-04-14 16:55:36 +010085 auto testData = std::make_unique<uint8_t[]>(space);
86 void* alignedPtr = testData.get();
87 BOOST_CHECK(std::align(alignment, totalBytes, alignedPtr, space));
88
89 // Import memory
90 BOOST_CHECK_THROW(handle->Import(alignedPtr, armnn::MemorySource::Undefined), MemoryImportException);
91}
92
93BOOST_FIXTURE_TEST_CASE(ClInvalidMemorySourceImport, ClContextControlFixture)
94{
95 MemorySource invalidMemSource = static_cast<MemorySource>(256);
96 ClImportTensorHandleFactory handleFactory(static_cast<MemorySourceFlags>(invalidMemSource),
97 static_cast<MemorySourceFlags>(invalidMemSource));
98
99 TensorInfo info({ 1, 2, 2, 1 }, DataType::Float32);
100
101 // create TensorHandle for memory import
102 auto handle = handleFactory.CreateTensorHandle(info);
103
104 // Allocate user memory
105 std::vector<float> inputData
106 {
107 1.0f, 2.0f, 3.0f, 4.0f
108 };
109
110 // Import non-support memory
111 BOOST_CHECK_THROW(handle->Import(inputData.data(), invalidMemSource), MemoryImportException);
112}
113
Narumol Prangnawarate5f0b242021-05-07 17:52:36 +0100114BOOST_FIXTURE_TEST_CASE(ClImportEndToEnd, ClContextControlFixture)
115{
116 // Create runtime in which test will run
117 IRuntime::CreationOptions options;
118 IRuntimePtr runtime(armnn::IRuntime::Create(options));
119
120 // build up the structure of the network
121 INetworkPtr net(INetwork::Create());
122
123 IConnectableLayer* input = net->AddInputLayer(0, "Input");
124
125 ActivationDescriptor descriptor;
126 descriptor.m_Function = ActivationFunction::ReLu;
127 IConnectableLayer* activation = net->AddActivationLayer(descriptor, "Activation");
128
129 IConnectableLayer* output = net->AddOutputLayer(0, "Output");
130
131 input->GetOutputSlot(0).Connect(activation->GetInputSlot(0));
132 activation->GetOutputSlot(0).Connect(output->GetInputSlot(0));
133
134 TensorInfo tensorInfo = TensorInfo({ 1, 24, 16, 3 }, DataType::Float32);
135 unsigned int numElements = tensorInfo.GetNumElements();
136 size_t totalBytes = numElements * sizeof(float);
137
138 input->GetOutputSlot(0).SetTensorInfo(tensorInfo);
139 activation->GetOutputSlot(0).SetTensorInfo(tensorInfo);
140
141 // Optimize the network
142 OptimizerOptions optOptions;
143 optOptions.m_ImportEnabled = true;
144 std::vector<armnn::BackendId> backends = {armnn::Compute::GpuAcc};
145 IOptimizedNetworkPtr optNet = Optimize(*net, backends, runtime->GetDeviceSpec(), optOptions);
146 BOOST_CHECK(optNet);
147
148 // Loads it into the runtime.
149 NetworkId netId;
150 std::string ignoredErrorMessage;
151 // Enable Importing
152 INetworkProperties networkProperties(false, MemorySource::Malloc, MemorySource::Malloc);
153 runtime->LoadNetwork(netId, std::move(optNet), ignoredErrorMessage, networkProperties);
154
155 // Creates structures for input & output
156 const size_t alignment =
157 arm_compute::CLKernelLibrary::get().get_device().getInfo<CL_DEVICE_GLOBAL_MEM_CACHELINE_SIZE>();
158 size_t space = totalBytes + alignment + alignment;
159 auto inputData = std::make_unique<uint8_t[]>(space);
160 void* alignedInputPtr = inputData.get();
161 BOOST_CHECK(std::align(alignment, totalBytes, alignedInputPtr, space));
162
163 // Input with negative values
164 auto* intputPtr = reinterpret_cast<float*>(alignedInputPtr);
165 std::fill_n(intputPtr, numElements, -5.0f);
166
167 auto outputData = std::make_unique<uint8_t[]>(space);
168 void* alignedOutputPtr = outputData.get();
169 BOOST_CHECK(std::align(alignment, totalBytes, alignedOutputPtr, space));
Narumol Prangnawarat878e0f92021-05-11 19:51:14 +0100170 auto* outputPtr = reinterpret_cast<float*>(alignedOutputPtr);
171 std::fill_n(outputPtr, numElements, -10.0f);
Narumol Prangnawarate5f0b242021-05-07 17:52:36 +0100172
173 InputTensors inputTensors
174 {
175 {0,armnn::ConstTensor(runtime->GetInputTensorInfo(netId, 0), alignedInputPtr)},
176 };
177 OutputTensors outputTensors
178 {
179 {0,armnn::Tensor(runtime->GetOutputTensorInfo(netId, 0), alignedOutputPtr)}
180 };
181
182 runtime->GetProfiler(netId)->EnableProfiling(true);
183
184 // Do the inference
185 runtime->EnqueueWorkload(netId, inputTensors, outputTensors);
186
187 // Retrieve the Profiler.Print() output to get the workload execution
188 ProfilerManager& profilerManager = armnn::ProfilerManager::GetInstance();
189 std::stringstream ss;
190 profilerManager.GetProfiler()->Print(ss);;
191 std::string dump = ss.str();
192
193 // Contains ActivationWorkload
194 std::size_t found = dump.find("ActivationWorkload");
195 BOOST_TEST(found != std::string::npos);
196
197 // Contains SyncMemGeneric
198 found = dump.find("SyncMemGeneric");
199 BOOST_TEST(found != std::string::npos);
200
201 // Does not contain CopyMemGeneric
202 found = dump.find("CopyMemGeneric");
203 BOOST_TEST(found == std::string::npos);
204
Narumol Prangnawarat878e0f92021-05-11 19:51:14 +0100205 runtime->UnloadNetwork(netId);
206
Narumol Prangnawarate5f0b242021-05-07 17:52:36 +0100207 // Check output is as expected
208 // Validate result by checking that the output has no negative values
209 auto* outputResult = reinterpret_cast<float*>(alignedOutputPtr);
210 BOOST_TEST(outputResult);
211 for(unsigned int i = 0; i < numElements; ++i)
212 {
213 BOOST_TEST(outputResult[i] >= 0);
214 }
Narumol Prangnawarate5f0b242021-05-07 17:52:36 +0100215}
216
217BOOST_AUTO_TEST_SUITE_END()