blob: 2a239866f73ba1d08d27325517fcec15878ad6da [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"
8
telsoa014fcda012018-03-09 14:13:49 +00009#include <armnn/ArmNN.hpp>
10#include <armnn/Tensor.hpp>
11#include <armnn/TypesUtils.hpp>
telsoa014fcda012018-03-09 14:13:49 +000012
Aron Virginas-Tarc9cc8042018-11-01 16:15:57 +000013#include <backendsCommon/CpuTensorHandle.hpp>
14#include <backendsCommon/WorkloadFactory.hpp>
telsoa014fcda012018-03-09 14:13:49 +000015
Aron Virginas-Tarc9cc8042018-11-01 16:15:57 +000016#include <test/TensorHelpers.hpp>
telsoa014fcda012018-03-09 14:13:49 +000017
18#include <algorithm>
19
20template<typename T>
21LayerTestResult<T, 2> SimpleSoftmaxTestImpl(armnn::IWorkloadFactory& workloadFactory, float beta)
22{
23 using std::exp;
24
25 armnn::TensorInfo inputTensorInfo;
26 armnn::TensorInfo outputTensorInfo;
27
28 unsigned int inputShape[] = { 2, 4 };
29
30 inputTensorInfo = armnn::TensorInfo(2, inputShape, armnn::GetDataType<T>());
31 float qScale = 1.f / 256.f;
32 int qOffset = 0;
33 inputTensorInfo.SetQuantizationScale(qScale);
34 inputTensorInfo.SetQuantizationOffset(qOffset);
35
36 outputTensorInfo = armnn::TensorInfo(2, inputShape, armnn::GetDataType<T>());
37 outputTensorInfo.SetQuantizationScale(qScale);
38 outputTensorInfo.SetQuantizationOffset(qOffset);
39
40 LayerTestResult<T, 2> ret(outputTensorInfo);
41
telsoa01c577f2c2018-08-31 09:22:23 +010042 // Each row is independently softmax'd.
telsoa014fcda012018-03-09 14:13:49 +000043 auto input = MakeTensor<T, 2>(inputTensorInfo, std::vector<T>(
44 QuantizedVector<T>(qScale, 0, {
45 0.f, 1.f, 0.f, 0.f,
46 .5f, 0.f, 0.f, 0.f,
47 })));
48
49 std::unique_ptr<armnn::ITensorHandle> inputHandle = workloadFactory.CreateTensorHandle(inputTensorInfo);
50 std::unique_ptr<armnn::ITensorHandle> outputHandle = workloadFactory.CreateTensorHandle(outputTensorInfo);
51
52 armnn::SoftmaxQueueDescriptor data;
53 data.m_Parameters.m_Beta = beta;
54
55 armnn::WorkloadInfo info;
56 AddInputToWorkload(data, info, inputTensorInfo, inputHandle.get());
57 AddOutputToWorkload(data, info, outputTensorInfo, outputHandle.get());
58
59 std::unique_ptr<armnn::IWorkload> workload = workloadFactory.CreateSoftmax(data, info);
60
61 inputHandle->Allocate();
62 outputHandle->Allocate();
63 CopyDataToITensorHandle(inputHandle.get(), &input[0][0]);
64
Aron Virginas-Tar60578952018-10-31 11:04:01 +000065 workloadFactory.Acquire();
telsoa014fcda012018-03-09 14:13:49 +000066 workload->Execute();
Aron Virginas-Tar60578952018-10-31 11:04:01 +000067 workloadFactory.Release();
telsoa014fcda012018-03-09 14:13:49 +000068
69 CopyDataFromITensorHandle(&ret.output[0][0], outputHandle.get());
70
71 float x0[4] = { exp((0.f - 1.0f) * beta), exp((1.0f - 1.0f) * beta),
72 exp((0.0f - 1.0f) * beta), exp((0.0f - 1.0f) * beta) };
73 float sum0 = x0[0] + x0[1] + x0[2] + x0[3];
74 float x1[4] = { exp((0.5f - 0.5f) * beta), exp((0.0f - 0.5f) * beta),
75 exp((0.0f - 0.5f) * beta), exp((0.0f - 0.5f) * beta) };
76 float sum1 = x1[0] + x1[1] + x1[2] + x1[3];
77
78 ret.outputExpected = MakeTensor<T, 2>(outputTensorInfo, std::vector<T>(
79 QuantizedVector<T>(qScale, qOffset, {
80 x0[0] / sum0, x0[1] / sum0, x0[2] / sum0, x0[3] / sum0,
81 x1[0] / sum1, x1[1] / sum1, x1[2] / sum1, x1[3] / sum1
82 })));
83
84 return ret;
85}
86
87template<typename T>
88LayerTestResult<T, 2> CompareSoftmaxTestImpl(armnn::IWorkloadFactory& workloadFactory,
89 armnn::IWorkloadFactory& refWorkloadFactory,
90 float beta)
91{
92
93 const int batchSize = 20;
94 const int channels = 30;
95
96 armnn::TensorInfo inputTensorInfo;
97 armnn::TensorInfo outputTensorInfo;
98
99 unsigned int inputShape[] = { batchSize, channels };
100
101 inputTensorInfo = armnn::TensorInfo(2, inputShape, armnn::GetDataType<T>());
102 outputTensorInfo = armnn::TensorInfo(2, inputShape, armnn::GetDataType<T>());
103 float qScale = 1.f / 256.f;
104 int qOffset = 0;
105 inputTensorInfo.SetQuantizationScale(qScale);
106 inputTensorInfo.SetQuantizationOffset(qOffset);
107 outputTensorInfo.SetQuantizationScale(qScale);
108 outputTensorInfo.SetQuantizationOffset(qOffset);
109
110
111 LayerTestResult<T, 2> ret(outputTensorInfo);
112 auto input = MakeRandomTensor<T, 2>(inputTensorInfo, 0xF00D, 0.0f, 1.0f);
113
114 std::unique_ptr<armnn::ITensorHandle> inputHandle = workloadFactory.CreateTensorHandle(inputTensorInfo);
115 std::unique_ptr<armnn::ITensorHandle> outputHandle = workloadFactory.CreateTensorHandle(outputTensorInfo);
116
117 armnn::SoftmaxQueueDescriptor data;
118 data.m_Parameters.m_Beta = beta;
119
120 armnn::WorkloadInfo info;
121 AddInputToWorkload(data, info, inputTensorInfo, inputHandle.get());
122 AddOutputToWorkload(data, info, outputTensorInfo, outputHandle.get());
123
124 std::unique_ptr<armnn::ITensorHandle> outputHandleRef = refWorkloadFactory.CreateTensorHandle(outputTensorInfo);
125 std::unique_ptr<armnn::ITensorHandle> inputHandleRef = refWorkloadFactory.CreateTensorHandle(inputTensorInfo);
126
127
128 armnn::SoftmaxQueueDescriptor refData = data;
129 armnn::WorkloadInfo refInfo = info;
130 SetWorkloadInput(refData, refInfo, 0, inputTensorInfo, inputHandleRef.get());
131 SetWorkloadOutput(refData, refInfo, 0, outputTensorInfo, outputHandleRef.get());
132
133 std::unique_ptr<armnn::IWorkload> workload = workloadFactory.CreateSoftmax(data, info);
134 std::unique_ptr<armnn::IWorkload> workloadRef = refWorkloadFactory.CreateSoftmax(refData, refInfo);
135
136 outputHandleRef->Allocate();
137 inputHandleRef->Allocate();
138
139 inputHandle->Allocate();
140 outputHandle->Allocate();
141
142 CopyDataToITensorHandle(inputHandle.get(), &input[0][0]);
143 CopyDataToITensorHandle(inputHandleRef.get(), &input[0][0]);
144
Aron Virginas-Tar60578952018-10-31 11:04:01 +0000145 workloadFactory.Acquire();
telsoa014fcda012018-03-09 14:13:49 +0000146 workload->Execute();
Aron Virginas-Tar60578952018-10-31 11:04:01 +0000147 workloadFactory.Release();
148
telsoa014fcda012018-03-09 14:13:49 +0000149 workloadRef->Execute();
150
151 CopyDataFromITensorHandle(&ret.output[0][0], outputHandle.get());
152 CopyDataFromITensorHandle(&ret.outputExpected[0][0], outputHandleRef.get());
153
154 return ret;
surmeh013537c2c2018-05-18 16:31:43 +0100155}