11 #include <doctest/doctest.h> 15 using namespace armnn;
24 struct Workload0 :
BaseWorkload<ElementwiseUnaryQueueDescriptor>
37 int* inVals =
static_cast<int*
>(m_Data.m_Inputs[0][0].Map());
38 int* outVals =
static_cast<int*
>(m_Data.m_Outputs[0][0].Map());
40 for (
unsigned int i = 0;
41 i < m_Data.m_Inputs[0][0].GetShape().GetNumElements();
44 outVals[i] = inVals[i] * outVals[i];
45 inVals[i] = outVals[i];
52 int* inVals =
static_cast<int*
>(workingMemDescriptor->
m_Inputs[0][0].Map());
53 int* outVals =
static_cast<int*
>(workingMemDescriptor->
m_Outputs[0][0].Map());
55 for (
unsigned int i = 0;
56 i < workingMemDescriptor->
m_Inputs[0][0].GetShape().GetNumElements();
59 outVals[i] = inVals[i] + outVals[i];
60 inVals[i] = outVals[i];
70 struct Workload1 :
BaseWorkload<ElementwiseUnaryQueueDescriptor>
79 int* inVals =
static_cast<int*
>(m_Data.m_Inputs[0][0].Map());
80 int* outVals =
static_cast<int*
>(m_Data.m_Outputs[0][0].Map());
82 for (
unsigned int i = 0;
83 i < m_Data.m_Inputs[0][0].GetShape().GetNumElements();
86 outVals[i] = inVals[i] * outVals[i];
87 inVals[i] = outVals[i];
92 void ValidateTensor(
ITensorHandle* tensorHandle,
int expectedValue)
94 int* actualOutput =
static_cast<int*
>(tensorHandle->
Map());
96 bool allValuesCorrect =
true;
97 for (
unsigned int i = 0;
101 if (actualOutput[i] != expectedValue)
103 allValuesCorrect =
false;
107 CHECK(allValuesCorrect);
110 template<
typename Workload>
118 elementwiseUnaryQueueDescriptor.
m_Inputs = std::vector<ITensorHandle*>{inputTensor};
119 elementwiseUnaryQueueDescriptor.
m_Outputs = std::vector<ITensorHandle*>{outputTensor};
121 return std::make_unique<Workload>(elementwiseUnaryQueueDescriptor, workloadInfo);
124 TEST_CASE(
"TestAsyncExecute")
128 int inVals[5]{2, 2, 2, 2, 2};
129 int outVals[5]{1, 1, 1, 1, 1};
131 int expectedExecuteval = 2;
132 int expectedExecuteAsyncval = 3;
140 std::unique_ptr<Workload0> workload0 = CreateWorkload<Workload0>(
info, &syncInput0, &syncOutput0);
142 workload0.get()->Execute();
148 workingMemDescriptor0.
m_Inputs = std::vector<ITensorHandle*>{&asyncInput0};
149 workingMemDescriptor0.
m_Outputs = std::vector<ITensorHandle*>{&asyncOutput0};
152 executionData.
m_Data = &workingMemDescriptor0;
154 workload0.get()->ExecuteAsync(executionData);
157 ValidateTensor(workingMemDescriptor0.
m_Outputs[0], expectedExecuteAsyncval);
158 ValidateTensor(workingMemDescriptor0.
m_Inputs[0], expectedExecuteAsyncval);
160 ValidateTensor(&workload0.get()->GetQueueDescriptor()->m_Outputs[0][0], expectedExecuteval);
161 ValidateTensor(&workload0.get()->GetQueueDescriptor()->m_Inputs[0][0], expectedExecuteval);
164 TEST_CASE(
"TestDefaultAsyncExecute")
168 std::vector<int> inVals{2, 2, 2, 2, 2};
169 std::vector<int> outVals{1, 1, 1, 1, 1};
170 std::vector<int> defaultVals{0, 0, 0, 0, 0};
172 int expectedExecuteval = 2;
181 std::unique_ptr<Workload1> workload1 = CreateWorkload<Workload1>(
info, &defaultInput, &defaultOutput);
187 workingMemDescriptor.
m_Inputs = std::vector<ITensorHandle*>{&asyncInput};
188 workingMemDescriptor.
m_Outputs = std::vector<ITensorHandle*>{&asyncOutput};
191 executionData.
m_Data = &workingMemDescriptor;
193 workload1.get()->ExecuteAsync(executionData);
197 ValidateTensor(workingMemDescriptor.
m_Outputs[0], expectedExecuteval);
198 ValidateTensor(workingMemDescriptor.
m_Inputs[0], expectedExecuteval);
201 TEST_CASE(
"TestDefaultAsyncExeuteWithThreads")
204 unsigned int vecSize = 1000;
207 std::vector<int> inVals1(vecSize, 2);
208 std::vector<int> outVals1(vecSize, 1);
209 std::vector<int> inVals2(vecSize, 5);
210 std::vector<int> outVals2(vecSize, -1);
212 std::vector<int> defaultVals(vecSize, 0);
214 int expectedExecuteval1 = 4;
215 int expectedExecuteval2 = 25;
222 ConstTensor defaultTensor(info, defaultVals.data());
226 std::unique_ptr<Workload1> workload = CreateWorkload<Workload1>(
info, &defaultInput, &defaultOutput);
232 workingMemDescriptor1.
m_Inputs = std::vector<ITensorHandle*>{&asyncInput1};
233 workingMemDescriptor1.
m_Outputs = std::vector<ITensorHandle*>{&asyncOutput1};
236 executionData1.
m_Data = &workingMemDescriptor1;
242 workingMemDescriptor2.
m_Inputs = std::vector<ITensorHandle*>{&asyncInput2};
243 workingMemDescriptor2.
m_Outputs = std::vector<ITensorHandle*>{&asyncOutput2};
246 executionData2.
m_Data = &workingMemDescriptor2;
248 std::thread thread1 = std::thread([&]()
250 workload.get()->ExecuteAsync(executionData1);
251 workload.get()->ExecuteAsync(executionData1);
254 std::thread thread2 = std::thread([&]()
256 workload.get()->ExecuteAsync(executionData2);
257 workload.get()->ExecuteAsync(executionData2);
263 ValidateTensor(workingMemDescriptor1.
m_Outputs[0], expectedExecuteval1);
264 ValidateTensor(workingMemDescriptor1.
m_Inputs[0], expectedExecuteval1);
266 ValidateTensor(workingMemDescriptor2.
m_Outputs[0], expectedExecuteval2);
267 ValidateTensor(workingMemDescriptor2.
m_Inputs[0], expectedExecuteval2);
TEST_SUITE("TestConstTensorLayerVisitor")
unsigned int GetNumElements() const
Function that calculates the tensor elements by multiplying all dimension size which are Specified...
std::unique_ptr< armnn::IWorkload > CreateWorkload(const armnn::IWorkloadFactory &workloadFactory, const armnn::WorkloadInfo &info, const DescriptorType &descriptor)
Copyright (c) 2021 ARM Limited and Contributors.
std::vector< ITensorHandle * > m_Inputs
std::vector< TensorInfo > m_InputTensorInfos
A tensor defined by a TensorInfo (shape and data type) and an immutable backing store.
std::vector< TensorInfo > m_OutputTensorInfos
virtual TensorShape GetShape() const =0
Get the number of elements for each dimension ordered from slowest iterating dimension to fastest ite...
virtual const void * Map(bool blocking=true) const =0
Map the tensor data for access.
std::vector< ITensorHandle * > m_Outputs
std::vector< ITensorHandle * > m_Outputs
Contains information about TensorInfos of a layer.
std::vector< ITensorHandle * > m_Inputs