blob: 8081950ab835c9469e55027662ab67c27302b184 [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,
28 const std::vector<float>& outputData)
telsoa014fcda012018-03-09 14:13:49 +000029{
30 using std::exp;
31
Narumol Prangnawarat65d30962019-03-14 11:55:03 +000032 const float qScale = 1.f / 256.f;
33 const int qOffset = 0;
34
telsoa014fcda012018-03-09 14:13:49 +000035 armnn::TensorInfo inputTensorInfo;
36 armnn::TensorInfo outputTensorInfo;
37
Narumol Prangnawarat65d30962019-03-14 11:55:03 +000038 inputTensorInfo = armnn::TensorInfo(inputShape, ArmnnType);
telsoa014fcda012018-03-09 14:13:49 +000039 inputTensorInfo.SetQuantizationScale(qScale);
40 inputTensorInfo.SetQuantizationOffset(qOffset);
41
Narumol Prangnawarat65d30962019-03-14 11:55:03 +000042 outputTensorInfo = armnn::TensorInfo(inputShape, ArmnnType);
telsoa014fcda012018-03-09 14:13:49 +000043 outputTensorInfo.SetQuantizationScale(qScale);
44 outputTensorInfo.SetQuantizationOffset(qOffset);
45
Narumol Prangnawarat65d30962019-03-14 11:55:03 +000046 LayerTestResult<T, n> ret(outputTensorInfo);
telsoa014fcda012018-03-09 14:13:49 +000047
telsoa01c577f2c2018-08-31 09:22:23 +010048 // Each row is independently softmax'd.
Narumol Prangnawarat65d30962019-03-14 11:55:03 +000049 auto input = MakeTensor<T, n>(inputTensorInfo, std::vector<T>(
50 QuantizedVector<T>(qScale, qOffset, {
telsoa014fcda012018-03-09 14:13:49 +000051 0.f, 1.f, 0.f, 0.f,
52 .5f, 0.f, 0.f, 0.f,
53 })));
54
55 std::unique_ptr<armnn::ITensorHandle> inputHandle = workloadFactory.CreateTensorHandle(inputTensorInfo);
56 std::unique_ptr<armnn::ITensorHandle> outputHandle = workloadFactory.CreateTensorHandle(outputTensorInfo);
57
58 armnn::SoftmaxQueueDescriptor data;
59 data.m_Parameters.m_Beta = beta;
60
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
103 return SimpleSoftmaxBaseTestImpl<ArmnnType, 2>(workloadFactory, memoryManager, beta, inputShape, outputData);
104}
105
106template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
107LayerTestResult<T, 3> Simple3dSoftmaxTestImpl(
108 armnn::IWorkloadFactory& workloadFactory,
109 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
110 float beta)
111{
112 const armnn::TensorShape inputShape{ 1, 8, 1 };
113 const std::vector<float> outputData = { 0.0964599f, 0.26220518f, 0.0964599f, 0.0964599f,
114 0.15903549f, 0.0964599f, 0.0964599f, 0.0964599f };
115
116 return SimpleSoftmaxBaseTestImpl<ArmnnType, 3>(workloadFactory, memoryManager, beta, inputShape, outputData);
117}
118
119template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
120LayerTestResult<T, 4> Simple4dSoftmaxTestImpl(
121 armnn::IWorkloadFactory& workloadFactory,
122 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
123 float beta)
124{
125 const armnn::TensorShape inputShape{ 1, 8, 1, 1 };
126 const std::vector<float> outputData = { 0.0964599f, 0.26220518f, 0.0964599f, 0.0964599f,
127 0.15903549f, 0.0964599f, 0.0964599f, 0.0964599f };
128
129 return SimpleSoftmaxBaseTestImpl<ArmnnType, 4>(workloadFactory, memoryManager, beta, inputShape, outputData);
130}
131
132template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
133LayerTestResult<T, 2> CompareSoftmaxTestImpl(
134 armnn::IWorkloadFactory& workloadFactory,
135 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
136 armnn::IWorkloadFactory& refWorkloadFactory,
137 float beta)
138{
telsoa014fcda012018-03-09 14:13:49 +0000139
140 const int batchSize = 20;
141 const int channels = 30;
142
143 armnn::TensorInfo inputTensorInfo;
144 armnn::TensorInfo outputTensorInfo;
145
146 unsigned int inputShape[] = { batchSize, channels };
147
Nattapat Chaimanowong649dd952019-01-22 16:10:44 +0000148 inputTensorInfo = armnn::TensorInfo(2, inputShape, ArmnnType);
149 outputTensorInfo = armnn::TensorInfo(2, inputShape, ArmnnType);
telsoa014fcda012018-03-09 14:13:49 +0000150 float qScale = 1.f / 256.f;
151 int qOffset = 0;
152 inputTensorInfo.SetQuantizationScale(qScale);
153 inputTensorInfo.SetQuantizationOffset(qOffset);
154 outputTensorInfo.SetQuantizationScale(qScale);
155 outputTensorInfo.SetQuantizationOffset(qOffset);
156
157
158 LayerTestResult<T, 2> ret(outputTensorInfo);
159 auto input = MakeRandomTensor<T, 2>(inputTensorInfo, 0xF00D, 0.0f, 1.0f);
160
161 std::unique_ptr<armnn::ITensorHandle> inputHandle = workloadFactory.CreateTensorHandle(inputTensorInfo);
162 std::unique_ptr<armnn::ITensorHandle> outputHandle = workloadFactory.CreateTensorHandle(outputTensorInfo);
163
164 armnn::SoftmaxQueueDescriptor data;
165 data.m_Parameters.m_Beta = beta;
166
167 armnn::WorkloadInfo info;
168 AddInputToWorkload(data, info, inputTensorInfo, inputHandle.get());
169 AddOutputToWorkload(data, info, outputTensorInfo, outputHandle.get());
170
171 std::unique_ptr<armnn::ITensorHandle> outputHandleRef = refWorkloadFactory.CreateTensorHandle(outputTensorInfo);
172 std::unique_ptr<armnn::ITensorHandle> inputHandleRef = refWorkloadFactory.CreateTensorHandle(inputTensorInfo);
173
174
175 armnn::SoftmaxQueueDescriptor refData = data;
176 armnn::WorkloadInfo refInfo = info;
177 SetWorkloadInput(refData, refInfo, 0, inputTensorInfo, inputHandleRef.get());
178 SetWorkloadOutput(refData, refInfo, 0, outputTensorInfo, outputHandleRef.get());
179
180 std::unique_ptr<armnn::IWorkload> workload = workloadFactory.CreateSoftmax(data, info);
181 std::unique_ptr<armnn::IWorkload> workloadRef = refWorkloadFactory.CreateSoftmax(refData, refInfo);
182
183 outputHandleRef->Allocate();
184 inputHandleRef->Allocate();
185
186 inputHandle->Allocate();
187 outputHandle->Allocate();
188
189 CopyDataToITensorHandle(inputHandle.get(), &input[0][0]);
190 CopyDataToITensorHandle(inputHandleRef.get(), &input[0][0]);
191
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +0000192 ExecuteWorkload(*workload, memoryManager);
Aron Virginas-Tar60578952018-10-31 11:04:01 +0000193
telsoa014fcda012018-03-09 14:13:49 +0000194 workloadRef->Execute();
195
196 CopyDataFromITensorHandle(&ret.output[0][0], outputHandle.get());
197 CopyDataFromITensorHandle(&ret.outputExpected[0][0], outputHandleRef.get());
198
199 return ret;
surmeh013537c2c2018-05-18 16:31:43 +0100200}