blob: 983a53be9c9e750b8e080f5cc45a59497a8c0c9b [file] [log] [blame]
telsoa014fcda012018-03-09 14:13:49 +00001//
2// Copyright © 2017 Arm Ltd. All rights reserved.
David Beckecb56cd2018-09-05 12:52:57 +01003// SPDX-License-Identifier: MIT
telsoa014fcda012018-03-09 14:13:49 +00004//
5#pragma once
6
Aron Virginas-Tarc9cc8042018-11-01 16:15:57 +00007#include "QuantizeHelper.hpp"
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +00008#include "WorkloadTestUtils.hpp"
Aron Virginas-Tarc9cc8042018-11-01 16:15:57 +00009
telsoa014fcda012018-03-09 14:13:49 +000010#include <armnn/ArmNN.hpp>
11#include <armnn/Tensor.hpp>
12#include <armnn/TypesUtils.hpp>
telsoa014fcda012018-03-09 14:13:49 +000013
Aron Virginas-Tarc9cc8042018-11-01 16:15:57 +000014#include <backendsCommon/CpuTensorHandle.hpp>
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +000015#include <backendsCommon/IBackendInternal.hpp>
Aron Virginas-Tarc9cc8042018-11-01 16:15:57 +000016#include <backendsCommon/WorkloadFactory.hpp>
telsoa014fcda012018-03-09 14:13:49 +000017
Aron Virginas-Tarc9cc8042018-11-01 16:15:57 +000018#include <test/TensorHelpers.hpp>
telsoa014fcda012018-03-09 14:13:49 +000019
20#include <algorithm>
21
Narumol Prangnawarat65d30962019-03-14 11:55:03 +000022template<armnn::DataType ArmnnType, std::size_t n, typename T = armnn::ResolveType<ArmnnType>>
23LayerTestResult<T, n> SimpleSoftmaxBaseTestImpl(
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +000024 armnn::IWorkloadFactory& workloadFactory,
25 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
Narumol Prangnawarat65d30962019-03-14 11:55:03 +000026 float beta,
27 const armnn::TensorShape& inputShape,
Francis Murtagh07f21212019-07-23 09:50:50 +010028 const std::vector<float>& outputData,
29 const std::vector<float>& inputData,
30 int axis = 1)
telsoa014fcda012018-03-09 14:13:49 +000031{
32 using std::exp;
33
Narumol Prangnawarat65d30962019-03-14 11:55:03 +000034 const float qScale = 1.f / 256.f;
35 const int qOffset = 0;
36
telsoa014fcda012018-03-09 14:13:49 +000037 armnn::TensorInfo inputTensorInfo;
38 armnn::TensorInfo outputTensorInfo;
39
Narumol Prangnawarat65d30962019-03-14 11:55:03 +000040 inputTensorInfo = armnn::TensorInfo(inputShape, ArmnnType);
telsoa014fcda012018-03-09 14:13:49 +000041 inputTensorInfo.SetQuantizationScale(qScale);
42 inputTensorInfo.SetQuantizationOffset(qOffset);
43
Narumol Prangnawarat65d30962019-03-14 11:55:03 +000044 outputTensorInfo = armnn::TensorInfo(inputShape, ArmnnType);
telsoa014fcda012018-03-09 14:13:49 +000045 outputTensorInfo.SetQuantizationScale(qScale);
46 outputTensorInfo.SetQuantizationOffset(qOffset);
47
Narumol Prangnawarat65d30962019-03-14 11:55:03 +000048 LayerTestResult<T, n> ret(outputTensorInfo);
telsoa014fcda012018-03-09 14:13:49 +000049
telsoa01c577f2c2018-08-31 09:22:23 +010050 // Each row is independently softmax'd.
Narumol Prangnawarat65d30962019-03-14 11:55:03 +000051 auto input = MakeTensor<T, n>(inputTensorInfo, std::vector<T>(
Francis Murtagh07f21212019-07-23 09:50:50 +010052 QuantizedVector<T>(qScale, qOffset, inputData)));
telsoa014fcda012018-03-09 14:13:49 +000053
54 std::unique_ptr<armnn::ITensorHandle> inputHandle = workloadFactory.CreateTensorHandle(inputTensorInfo);
55 std::unique_ptr<armnn::ITensorHandle> outputHandle = workloadFactory.CreateTensorHandle(outputTensorInfo);
56
57 armnn::SoftmaxQueueDescriptor data;
58 data.m_Parameters.m_Beta = beta;
Francis Murtagh07f21212019-07-23 09:50:50 +010059 data.m_Parameters.m_Axis = axis;
telsoa014fcda012018-03-09 14:13:49 +000060
61 armnn::WorkloadInfo info;
62 AddInputToWorkload(data, info, inputTensorInfo, inputHandle.get());
63 AddOutputToWorkload(data, info, outputTensorInfo, outputHandle.get());
64
65 std::unique_ptr<armnn::IWorkload> workload = workloadFactory.CreateSoftmax(data, info);
66
67 inputHandle->Allocate();
68 outputHandle->Allocate();
Narumol Prangnawarat65d30962019-03-14 11:55:03 +000069 CopyDataToITensorHandle(inputHandle.get(), input.origin());
70
71 BOOST_ASSERT(workload);
telsoa014fcda012018-03-09 14:13:49 +000072
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +000073 ExecuteWorkload(*workload, memoryManager);
telsoa014fcda012018-03-09 14:13:49 +000074
Narumol Prangnawarat65d30962019-03-14 11:55:03 +000075 CopyDataFromITensorHandle(ret.output.origin(), outputHandle.get());
telsoa014fcda012018-03-09 14:13:49 +000076
Narumol Prangnawarat65d30962019-03-14 11:55:03 +000077 std::vector<T> expectedOutput = std::vector<T>(
78 QuantizedVector<T>(qScale, qOffset, outputData));
79 ret.outputExpected = MakeTensor<T, n>(outputTensorInfo, expectedOutput);
telsoa014fcda012018-03-09 14:13:49 +000080
81 return ret;
82}
83
Nattapat Chaimanowong649dd952019-01-22 16:10:44 +000084template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
Narumol Prangnawarat65d30962019-03-14 11:55:03 +000085LayerTestResult<T, 2> SimpleSoftmaxTestImpl(
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +000086 armnn::IWorkloadFactory& workloadFactory,
87 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
telsoa014fcda012018-03-09 14:13:49 +000088 float beta)
89{
Narumol Prangnawarat65d30962019-03-14 11:55:03 +000090 using std::exp;
91 const armnn::TensorShape inputShape{ 2, 4 };
92
93 float x0[4] = { exp((0.f - 1.0f) * beta), exp((1.0f - 1.0f) * beta),
94 exp((0.0f - 1.0f) * beta), exp((0.0f - 1.0f) * beta) };
95 float sum0 = x0[0] + x0[1] + x0[2] + x0[3];
96 float x1[4] = { exp((0.5f - 0.5f) * beta), exp((0.0f - 0.5f) * beta),
97 exp((0.0f - 0.5f) * beta), exp((0.0f - 0.5f) * beta) };
98 float sum1 = x1[0] + x1[1] + x1[2] + x1[3];
99
100 const std::vector<float> outputData = { x0[0] / sum0, x0[1] / sum0, x0[2] / sum0, x0[3] / sum0,
101 x1[0] / sum1, x1[1] / sum1, x1[2] / sum1, x1[3] / sum1 };
102
Francis Murtagh07f21212019-07-23 09:50:50 +0100103 const std::vector<float> inputData =
104 {
105 0.f, 1.f, 0.f, 0.f,
106 .5f, 0.f, 0.f, 0.f,
107 };
108
109 return SimpleSoftmaxBaseTestImpl<ArmnnType, 2>(workloadFactory, memoryManager, beta,
110 inputShape, outputData, inputData);
111}
112
113template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
114LayerTestResult<T, 2> SimpleSoftmaxTestImpl(
115 armnn::IWorkloadFactory& workloadFactory,
116 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
117 float beta,
118 int axis)
119{
120 armnn::TensorShape inputShape;
121 std::vector<float> inputData;
122 std::vector<float> outputData;
123 switch (axis)
124 {
125 case -2:
126 case 0:
127 {
128 inputShape = {5, 2};
129
130 inputData =
131 {
132 17.0f, -1.0f, 16.0f, -2.0f, 15.0f, -3.0f, 14.0f, -4.0f, 1.0f, -17.0f
133 };
134
135 outputData =
136 {
137 0.643914213228014f, 0.643914213228014f, 0.236882800924671f, 0.236882800924671f,
138 0.087144312427294f,
139 0.087144312427294f, 0.032058600957022f, 0.032058600957022f, 7.246299848982885e-08f,
140 7.246299848982885e-08f
141 };
142 break;
143 }
144 case -1:
145 case 1:
146 {
147 inputShape = {2, 5};
148
149 inputData =
150 {
151 17.0f, 16.0f, 15.0f, 14.0f, 1.0f, -1.0f, -2.0f, -3.0f, -4.0f, -17.0f
152 };
153
154 outputData =
155 {
156 0.643914213228014f, 0.236882800924671f, 0.087144312427294f, 0.032058600957022f,
157 7.246299848982885e-08f,
158 0.643914213228014f, 0.236882800924671f, 0.087144312427294f, 0.032058600957022f,
159 7.246299848982885e-08f
160 };
161 break;
162 }
163 }
164 return SimpleSoftmaxBaseTestImpl<ArmnnType, 2>(workloadFactory, memoryManager, beta,
165 inputShape, outputData, inputData, axis);
Narumol Prangnawarat65d30962019-03-14 11:55:03 +0000166}
167
168template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
169LayerTestResult<T, 3> Simple3dSoftmaxTestImpl(
170 armnn::IWorkloadFactory& workloadFactory,
171 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
Francis Murtagh07f21212019-07-23 09:50:50 +0100172 float beta,
173 const armnn::TensorShape& inputShape,
174 const std::vector<float>& outputData,
175 const std::vector<float>& inputData,
176 int axis = 1)
Narumol Prangnawarat65d30962019-03-14 11:55:03 +0000177{
Francis Murtagh07f21212019-07-23 09:50:50 +0100178 return SimpleSoftmaxBaseTestImpl<ArmnnType, 3>(workloadFactory, memoryManager, beta,
179 inputShape, outputData, inputData, axis);
Narumol Prangnawarat65d30962019-03-14 11:55:03 +0000180}
181
182template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
183LayerTestResult<T, 4> Simple4dSoftmaxTestImpl(
184 armnn::IWorkloadFactory& workloadFactory,
185 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
Francis Murtagh07f21212019-07-23 09:50:50 +0100186 float beta,
187 const armnn::TensorShape& inputShape,
188 const std::vector<float>& outputData,
189 const std::vector<float>& inputData,
190 int axis = 1)
Narumol Prangnawarat65d30962019-03-14 11:55:03 +0000191{
Narumol Prangnawarat65d30962019-03-14 11:55:03 +0000192
Francis Murtagh07f21212019-07-23 09:50:50 +0100193 return SimpleSoftmaxBaseTestImpl<ArmnnType, 4>(workloadFactory, memoryManager, beta,
194 inputShape, outputData, inputData, axis);
Narumol Prangnawarat65d30962019-03-14 11:55:03 +0000195}
196
197template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
198LayerTestResult<T, 2> CompareSoftmaxTestImpl(
199 armnn::IWorkloadFactory& workloadFactory,
200 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
201 armnn::IWorkloadFactory& refWorkloadFactory,
202 float beta)
203{
telsoa014fcda012018-03-09 14:13:49 +0000204
205 const int batchSize = 20;
206 const int channels = 30;
207
208 armnn::TensorInfo inputTensorInfo;
209 armnn::TensorInfo outputTensorInfo;
210
211 unsigned int inputShape[] = { batchSize, channels };
212
Nattapat Chaimanowong649dd952019-01-22 16:10:44 +0000213 inputTensorInfo = armnn::TensorInfo(2, inputShape, ArmnnType);
214 outputTensorInfo = armnn::TensorInfo(2, inputShape, ArmnnType);
telsoa014fcda012018-03-09 14:13:49 +0000215 float qScale = 1.f / 256.f;
216 int qOffset = 0;
217 inputTensorInfo.SetQuantizationScale(qScale);
218 inputTensorInfo.SetQuantizationOffset(qOffset);
219 outputTensorInfo.SetQuantizationScale(qScale);
220 outputTensorInfo.SetQuantizationOffset(qOffset);
221
222
223 LayerTestResult<T, 2> ret(outputTensorInfo);
224 auto input = MakeRandomTensor<T, 2>(inputTensorInfo, 0xF00D, 0.0f, 1.0f);
225
226 std::unique_ptr<armnn::ITensorHandle> inputHandle = workloadFactory.CreateTensorHandle(inputTensorInfo);
227 std::unique_ptr<armnn::ITensorHandle> outputHandle = workloadFactory.CreateTensorHandle(outputTensorInfo);
228
229 armnn::SoftmaxQueueDescriptor data;
230 data.m_Parameters.m_Beta = beta;
231
232 armnn::WorkloadInfo info;
233 AddInputToWorkload(data, info, inputTensorInfo, inputHandle.get());
234 AddOutputToWorkload(data, info, outputTensorInfo, outputHandle.get());
235
236 std::unique_ptr<armnn::ITensorHandle> outputHandleRef = refWorkloadFactory.CreateTensorHandle(outputTensorInfo);
237 std::unique_ptr<armnn::ITensorHandle> inputHandleRef = refWorkloadFactory.CreateTensorHandle(inputTensorInfo);
238
239
240 armnn::SoftmaxQueueDescriptor refData = data;
241 armnn::WorkloadInfo refInfo = info;
242 SetWorkloadInput(refData, refInfo, 0, inputTensorInfo, inputHandleRef.get());
243 SetWorkloadOutput(refData, refInfo, 0, outputTensorInfo, outputHandleRef.get());
244
245 std::unique_ptr<armnn::IWorkload> workload = workloadFactory.CreateSoftmax(data, info);
246 std::unique_ptr<armnn::IWorkload> workloadRef = refWorkloadFactory.CreateSoftmax(refData, refInfo);
247
248 outputHandleRef->Allocate();
249 inputHandleRef->Allocate();
250
251 inputHandle->Allocate();
252 outputHandle->Allocate();
253
254 CopyDataToITensorHandle(inputHandle.get(), &input[0][0]);
255 CopyDataToITensorHandle(inputHandleRef.get(), &input[0][0]);
256
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +0000257 ExecuteWorkload(*workload, memoryManager);
Aron Virginas-Tar60578952018-10-31 11:04:01 +0000258
telsoa014fcda012018-03-09 14:13:49 +0000259 workloadRef->Execute();
260
261 CopyDataFromITensorHandle(&ret.output[0][0], outputHandle.get());
262 CopyDataFromITensorHandle(&ret.outputExpected[0][0], outputHandleRef.get());
263
264 return ret;
surmeh013537c2c2018-05-18 16:31:43 +0100265}