ArmNN
 21.05
ClImportTensorHandleTests.cpp
Go to the documentation of this file.
1 //
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 
11 
12 #include <boost/test/unit_test.hpp>
13 
14 #include <armnn/IRuntime.hpp>
15 #include <armnn/INetwork.hpp>
16 
17 using namespace armnn;
18 
19 BOOST_AUTO_TEST_SUITE(ClImportTensorHandleTests)
20 
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>();
44  size_t space = totalBytes + alignment + alignment;
45  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  {
63  BOOST_TEST(typedPtr[i] >= 0);
64  }
65 }
66 
67 BOOST_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>();
84  size_t space = totalBytes + alignment + alignment;
85  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 
93 BOOST_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 
115 {
116  // Create runtime in which test will run
118  IRuntimePtr runtime(armnn::IRuntime::Create(options));
119 
120  // build up the structure of the network
122 
123  IConnectableLayer* input = net->AddInputLayer(0, "Input");
124 
125  ActivationDescriptor descriptor;
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
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));
170 
171  InputTensors inputTensors
172  {
173  {0,armnn::ConstTensor(runtime->GetInputTensorInfo(netId, 0), alignedInputPtr)},
174  };
175  OutputTensors outputTensors
176  {
177  {0,armnn::Tensor(runtime->GetOutputTensorInfo(netId, 0), alignedOutputPtr)}
178  };
179 
180  runtime->GetProfiler(netId)->EnableProfiling(true);
181 
182  // Do the inference
183  runtime->EnqueueWorkload(netId, inputTensors, outputTensors);
184 
185  // Retrieve the Profiler.Print() output to get the workload execution
187  std::stringstream ss;
188  profilerManager.GetProfiler()->Print(ss);;
189  std::string dump = ss.str();
190 
191  // Contains ActivationWorkload
192  std::size_t found = dump.find("ActivationWorkload");
193  BOOST_TEST(found != std::string::npos);
194 
195  // Contains SyncMemGeneric
196  found = dump.find("SyncMemGeneric");
197  BOOST_TEST(found != std::string::npos);
198 
199  // Does not contain CopyMemGeneric
200  found = dump.find("CopyMemGeneric");
201  BOOST_TEST(found == std::string::npos);
202 
203  // Check output is as expected
204  // Validate result by checking that the output has no negative values
205  auto* outputResult = reinterpret_cast<float*>(alignedOutputPtr);
206  BOOST_TEST(outputResult);
207  for(unsigned int i = 0; i < numElements; ++i)
208  {
209  BOOST_TEST(outputResult[i] >= 0);
210  }
211 
212  runtime->UnloadNetwork(netId);
213 }
214 
BOOST_AUTO_TEST_SUITE(TensorflowLiteParser)
static IRuntimePtr Create(const CreationOptions &options)
Definition: Runtime.cpp:37
Interface for a layer that is connectable to other layers via InputSlots and OutputSlots.
Definition: INetwork.hpp:62
static ProfilerManager & GetInstance()
Definition: Profiling.cpp:489
std::unique_ptr< IRuntime, void(*)(IRuntime *runtime)> IRuntimePtr
Definition: IRuntime.hpp:28
void Print(std::ostream &outStream) const
Print stats for events in JSON Format to the given output stream.
Definition: Profiling.cpp:522
std::vector< std::pair< LayerBindingId, class ConstTensor > > InputTensors
Definition: Tensor.hpp:340
Copyright (c) 2021 ARM Limited and Contributors.
virtual void SetTensorInfo(const TensorInfo &tensorInfo)=0
IProfiler * GetProfiler()
Definition: Profiling.cpp:501
A tensor defined by a TensorInfo (shape and data type) and a mutable backing store.
Definition: Tensor.hpp:306
IOptimizedNetworkPtr Optimize(const INetwork &network, const std::vector< BackendId > &backendPreferences, const IDeviceSpec &deviceSpec, const OptimizerOptions &options=OptimizerOptions(), Optional< std::vector< std::string > &> messages=EmptyOptional())
Create an optimized version of the network.
Definition: Network.cpp:1568
BOOST_FIXTURE_TEST_CASE(ClMallocImport, ClContextControlFixture)
int NetworkId
Definition: IRuntime.hpp:22
A tensor defined by a TensorInfo (shape and data type) and an immutable backing store.
Definition: Tensor.hpp:314
std::vector< std::pair< LayerBindingId, class Tensor > > OutputTensors
Definition: Tensor.hpp:341
std::unique_ptr< IOptimizedNetwork, void(*)(IOptimizedNetwork *network)> IOptimizedNetworkPtr
Definition: INetwork.hpp:174
GPU Execution: OpenCL: ArmCompute.
An ActivationDescriptor for the ActivationLayer.
Definition: Descriptors.hpp:25
This factory creates ClImportTensorHandles that refer to imported memory tensors. ...
BOOST_AUTO_TEST_SUITE_END()
MemorySource
Define the Memory Source to reduce copies.
Definition: Types.hpp:197
virtual const IInputSlot & GetInputSlot(unsigned int index) const =0
Get a const input slot handle by slot index.
virtual const IOutputSlot & GetOutputSlot(unsigned int index) const =0
Get the const output slot handle by slot index.
std::unique_ptr< INetwork, void(*)(INetwork *network)> INetworkPtr
Definition: INetwork.hpp:173
virtual int Connect(IInputSlot &destination)=0
std::unique_ptr< ITensorHandle > CreateTensorHandle(const TensorInfo &tensorInfo) const override
static INetworkPtr Create(NetworkOptions networkOptions={})
Definition: Network.cpp:529
ActivationFunction m_Function
The activation function to use (Sigmoid, TanH, Linear, ReLu, BoundedReLu, SoftReLu, LeakyReLu, Abs, Sqrt, Square, Elu).
Definition: Descriptors.hpp:48
unsigned int GetNumElements() const
Definition: Tensor.hpp:192