ArmNN
 22.05
ICLTensorProxyTests.cpp
Go to the documentation of this file.
1 //
2 // Copyright © 2022 Arm Ltd and Contributors. All rights reserved.
3 // SPDX-License-Identifier: MIT
4 //
5 
6 #include <arm_compute/runtime/CL/functions/CLActivationLayer.h>
7 
9 
12 #include <cl/ClTensorHandle.hpp>
14 #include <cl/ICLTensorProxy.hpp>
17 
18 #include <doctest/doctest.h>
19 
20 using namespace armnn;
21 
22 TEST_SUITE("ICLTensorProxyTests")
23 {
24 
25 TEST_CASE_FIXTURE(ClContextControlFixture, "ICLTensorProxyTest")
26 {
27  ClTensorHandleFactory handleFactory =
28  ClWorkloadFactoryHelper::GetTensorHandleFactory(ClWorkloadFactoryHelper::GetMemoryManager());
29 
30  TensorInfo info({ 1, 3, 4, 1 }, DataType::Float32);
31 
32  // create TensorHandle for memory import
33  auto handle = handleFactory.CreateTensorHandle(info, true);
34 
35  std::vector<float> inputData
36  {
37  -5, -2, 1, 2,
38  3, 10, -20, 8,
39  0, -12, 7, -9
40  };
41 
42  handle->Allocate();
43 
44  CopyDataToITensorHandle(handle.get(), inputData.data());
45 
46  // Get CLtensor
47  arm_compute::CLTensor& tensor = PolymorphicDowncast<ClTensorHandle*>(handle.get())->GetTensor();
48  ICLTensorProxy iclTensorProxy(&tensor);
49 
50  // Check that the ICLTensorProxy get correct information from the delegate tensor
51  CHECK((iclTensorProxy.info() == tensor.info()));
52  CHECK((iclTensorProxy.buffer() == tensor.buffer()));
53  CHECK((iclTensorProxy.cl_buffer() == tensor.cl_buffer()));
54  CHECK((iclTensorProxy.quantization().scale == tensor.quantization().scale));
55  CHECK((iclTensorProxy.quantization().offset == tensor.quantization().offset));
56 }
57 
58 TEST_CASE_FIXTURE(ClContextControlFixture, "ChangeICLTensorProxyExecutionTest")
59 {
60  // Start execution with with copied tensor
61  ClTensorHandleFactory handleFactory =
62  ClWorkloadFactoryHelper::GetTensorHandleFactory(ClWorkloadFactoryHelper::GetMemoryManager());
63 
64  TensorInfo info({ 1, 3, 4, 1 }, DataType::Float32);
65  unsigned int numElements = info.GetNumElements();
66 
67  // create TensorHandle for memory import
68  auto handle = handleFactory.CreateTensorHandle(info, true);
69 
70  std::vector<float> inputData
71  {
72  -5, -2, 1, 2,
73  3, 10, -20, 8,
74  0, -12, 7, -9
75  };
76 
77  std::vector<float> ExpectedOutput
78  {
79  0, 0, 1, 2,
80  3, 10, 0, 8,
81  0, 0, 7, 0
82  };
83 
84  handle->Allocate();
85 
86  CopyDataToITensorHandle(handle.get(), inputData.data());
87 
88  // Get CLtensor
89  arm_compute::CLTensor& tensor = PolymorphicDowncast<ClTensorHandle*>(handle.get())->GetTensor();
90 
91  // Set a proxy tensor to allocated tensor
92  std::unique_ptr<ICLTensorProxy> iclTensorProxy;
93  iclTensorProxy = std::make_unique<ICLTensorProxy>(&tensor);
94 
95  // Create and configure activation function
96  const arm_compute::ActivationLayerInfo act_info(arm_compute::ActivationLayerInfo::ActivationFunction::RELU);
97  arm_compute::CLActivationLayer act_func;
98  act_func.configure(iclTensorProxy.get(), nullptr, act_info);
99 
100  act_func.run();
101  arm_compute::CLScheduler::get().sync();
102 
103  std::vector<float> actualOutput(info.GetNumElements());
104 
105  CopyDataFromITensorHandle(actualOutput.data(), handle.get());
106 
107  // Validate result as expected output
108  for(unsigned int i = 0; i < numElements; ++i)
109  {
110  CHECK((actualOutput[i] == ExpectedOutput[i]));
111  }
112 
113  // Change to execute with imported tensor
114  ClImportTensorHandleFactory importHandleFactory(static_cast<MemorySourceFlags>(MemorySource::Malloc),
115  static_cast<MemorySourceFlags>(MemorySource::Malloc));
116  // create TensorHandle for memory import
117  auto importHandle = importHandleFactory.CreateTensorHandle(info);
118 
119  // Get CLtensor
120  arm_compute::CLTensor& importTensor = PolymorphicDowncast<ClImportTensorHandle*>(importHandle.get())->GetTensor();
121 
122  // Allocate user memory
123  const size_t totalBytes = importTensor.info()->total_size();
124  const size_t alignment =
125  arm_compute::CLKernelLibrary::get().get_device().getInfo<CL_DEVICE_GLOBAL_MEM_CACHELINE_SIZE>();
126  size_t space = totalBytes + alignment + alignment;
127  auto testData = std::make_unique<uint8_t[]>(space);
128  void* alignedPtr = testData.get();
129  CHECK(std::align(alignment, totalBytes, alignedPtr, space));
130 
131  // Import memory
132  CHECK(importHandle->Import(alignedPtr, armnn::MemorySource::Malloc));
133 
134  // Input with negative values
135  auto* typedPtr = reinterpret_cast<float*>(alignedPtr);
136  std::fill_n(typedPtr, numElements, -5.0f);
137 
138  // Set the import Tensor to TensorProxy to change Tensor in the CLActivationLayer without calling configure function
139  iclTensorProxy->set(&importTensor);
140 
141  // Execute function and sync
142  act_func.run();
143  arm_compute::CLScheduler::get().sync();
144 
145  // Validate result by checking that the output has no negative values
146  for(unsigned int i = 0; i < numElements; ++i)
147  {
148  CHECK(typedPtr[i] == 0);
149  }
150 }
151 }
TEST_SUITE("TestConstTensorLayerVisitor")
Copyright (c) 2021 ARM Limited and Contributors.
uint8_t * buffer() const
arm_compute::CLQuantization quantization() const
TEST_CASE_FIXTURE(ClContextControlFixture, "CopyBetweenNeonAndGpu")
std::unique_ptr< ITensorHandle > CreateTensorHandle(const TensorInfo &tensorInfo) const override
void CopyDataFromITensorHandle(void *mem, const armnn::ITensorHandle *tensorHandle)
const cl::Buffer & cl_buffer() const
This factory creates ClImportTensorHandles that refer to imported memory tensors. ...
void CopyDataToITensorHandle(armnn::ITensorHandle *tensorHandle, const void *memory)
arm_compute::ITensorInfo * info() const
std::unique_ptr< ITensorHandle > CreateTensorHandle(const TensorInfo &tensorInfo) const override