blob: 21b3951fe4b82bc7f8945a468a47f149486c4f14 [file] [log] [blame]
//
// Copyright © 2017, 2023-2024 Arm Ltd and Contributors. All rights reserved.
// SPDX-License-Identifier: MIT
//
#include "ActivationTestImpl.hpp"
#include <armnnUtils/QuantizeHelper.hpp>
#include <ResolveType.hpp>
#include <backendsCommon/test/ActivationFixture.hpp>
#include <armnnTestUtils/TensorCopyUtils.hpp>
#include <armnnTestUtils/WorkloadTestUtils.hpp>
#include <reference/test/RefWorkloadFactoryHelper.hpp>
#include <armnn/utility/NumericCast.hpp>
#include <armnnTestUtils/TensorHelpers.hpp>
#include <algorithm>
template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
LayerTestResult<T, 4> BoundedReLuTestCommon(
armnn::IWorkloadFactory& workloadFactory,
const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
const armnn::ITensorHandleFactory& tensorHandleFactory,
float upperBound,
float lowerBound,
float inputScale,
int32_t inputOffset,
float outputScale,
int32_t outputOffset,
const std::vector<T>& inputData,
const std::vector<T>& outputExpectedData,
unsigned int inputWidth,
unsigned int inputHeight,
unsigned int inputChannels,
unsigned int inputBatchSize)
{
IgnoreUnused(memoryManager);
unsigned int outputWidth = inputWidth;
unsigned int outputHeight = inputHeight;
unsigned int outputChannels = inputChannels;
unsigned int outputBatchSize = inputBatchSize;
armnn::TensorInfo inputTensorInfo({ inputBatchSize, inputChannels, inputHeight, inputWidth }, ArmnnType);
armnn::TensorInfo outputTensorInfo({ outputBatchSize, outputChannels, outputHeight, outputWidth }, ArmnnType);
if(armnn::IsQuantizedType<T>())
{
inputTensorInfo.SetQuantizationScale(inputScale);
inputTensorInfo.SetQuantizationOffset(inputOffset);
outputTensorInfo.SetQuantizationScale(outputScale);
outputTensorInfo.SetQuantizationOffset(outputOffset);
}
std::vector<T> actualOutput(outputTensorInfo.GetNumElements());
std::unique_ptr<armnn::ITensorHandle> inputHandle = tensorHandleFactory.CreateTensorHandle(inputTensorInfo);
std::unique_ptr<armnn::ITensorHandle> outputHandle = tensorHandleFactory.CreateTensorHandle(outputTensorInfo);
// Setup bounded ReLu.
armnn::ActivationQueueDescriptor descriptor;
armnn::WorkloadInfo workloadInfo;
AddInputToWorkload(descriptor, workloadInfo, inputTensorInfo, inputHandle.get());
AddOutputToWorkload(descriptor, workloadInfo, outputTensorInfo, outputHandle.get());
descriptor.m_Parameters.m_Function = armnn::ActivationFunction::BoundedReLu;
descriptor.m_Parameters.m_A = upperBound;
descriptor.m_Parameters.m_B = lowerBound;
std::unique_ptr<armnn::IWorkload> workload = workloadFactory.CreateWorkload(armnn::LayerType::Activation,
descriptor, workloadInfo);
inputHandle->Allocate();
outputHandle->Allocate();
CopyDataToITensorHandle(inputHandle.get(), inputData.data());
workload->Execute();
CopyDataFromITensorHandle(actualOutput.data(), outputHandle.get());
return LayerTestResult<T, 4>(actualOutput,
outputExpectedData,
outputHandle->GetShape(),
outputTensorInfo.GetShape());
}
LayerTestResult<float, 4> BoundedReLuUpperAndLowerBoundTest(
armnn::IWorkloadFactory& workloadFactory,
const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
const armnn::ITensorHandleFactory& tensorHandleFactory)
{
unsigned int inputWidth = 4u;
unsigned int inputHeight = 5u;
unsigned int inputChannels = 1u;
unsigned int inputBatchSize = 1;
std::vector<float> input = std::vector<float>{
-2.0f, 0.1f, 0.5f, 1.25f,
0.786f, 0.9875f, -1.5f, 0.384f,
1.0001f, 3.5f, 7.5f, 0.896f,
2.126f, 2.0f, 0.3f, 0.15f,
0.999f, 1.2f, 0.89f, 6.1f,
};
// Calculated manually.
std::vector<float> output = std::vector<float>{
-1.0f, 0.1f, 0.5f, 1.0f,
0.786f, 0.9875f, -1.0f, 0.384f,
1.0f, 1.0f, 1.0f, 0.896f,
1.0f, 1.0f, 0.3f, 0.15f,
0.999f, 1.0f, 0.89f, 1.0f,
};
return BoundedReLuTestCommon<armnn::DataType::Float32>(
workloadFactory, memoryManager, tensorHandleFactory, 1.0f, -1.0f, 1.0f, 0, 1.0f, 0, input, output,
inputWidth, inputHeight, inputChannels, inputBatchSize);
}
LayerTestResult<float, 4> BoundedReLuUpperBoundOnlyTest(
armnn::IWorkloadFactory& workloadFactory,
const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
const armnn::ITensorHandleFactory& tensorHandleFactory)
{
unsigned int inputWidth = 4u;
unsigned int inputHeight = 5u;
unsigned int inputChannels = 1u;
unsigned int inputBatchSize = 1;
std::vector<float> input = std::vector<float>{
-1.0f, 0.1f, 0.5f, 6.25f,
0.786f, 5.9875f, -0.5f, 0.384f,
6.0001f, 3.5f, 7.5f, 0.896f,
2.126f, 12.0f, 0.3f, 0.15f,
0.999f, 1.2f, 0.89f, 6.1f,
};
// Calculated manually.
std::vector<float> output = std::vector<float>{
0.0f, 0.1f, 0.5f, 6.0f,
0.786f, 5.9875f, 0.0f, 0.384f,
6.0f, 3.5f, 6.0f, 0.896f,
2.126f, 6.0f, 0.3f, 0.15f,
0.999f, 1.2f, 0.89f, 6.0f,
};
return BoundedReLuTestCommon<armnn::DataType::Float32>(
workloadFactory, memoryManager, tensorHandleFactory, 6.0f, 0.0f, 1.0f, 0, 1.0f, 0, input, output,
inputWidth, inputHeight, inputChannels, inputBatchSize);
}
LayerTestResult<uint8_t, 4> BoundedReLuUint8UpperBoundOnlyTest(
armnn::IWorkloadFactory& workloadFactory,
const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
const armnn::ITensorHandleFactory& tensorHandleFactory)
{
unsigned int inputWidth = 3u;
unsigned int inputHeight = 2u;
unsigned int inputChannels = 1u;
unsigned int inputBatchSize = 1;
std::vector<uint8_t> input = std::vector<uint8_t>{
51, 124, 28,
251, 8, 92
};
// Calculated manually.
std::vector<uint8_t> output = std::vector<uint8_t>{
0, 122, 0,
255, 0, 58
};
float inputScale = 12.0f / 255.0f;
int32_t inputOffset = 63;
float outputScale = 6.0f / 255.0f;
int32_t outputOffset = 0;
return BoundedReLuTestCommon<armnn::DataType::QAsymmU8>(
workloadFactory, memoryManager, tensorHandleFactory, 6.0f, 0.0f,
inputScale, inputOffset, outputScale, outputOffset,
input, output, inputWidth, inputHeight, inputChannels, inputBatchSize);
}
LayerTestResult<uint8_t, 4> BoundedReLuUint8UpperAndLowerBoundTest(
armnn::IWorkloadFactory& workloadFactory,
const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
const armnn::ITensorHandleFactory& tensorHandleFactory)
{
unsigned int inputWidth = 3u;
unsigned int inputHeight = 2u;
unsigned int inputChannels = 1u;
unsigned int inputBatchSize = 1;
std::vector<uint8_t> input = std::vector<uint8_t>{
51, 230, 28,
251, 8, 92
};
// Calculated manually.
std::vector<uint8_t> output = std::vector<uint8_t>{
51, 192, 32,
192, 32, 92
};
int32_t inputOffset = 112;
float inputScale = 0.0125f;
return BoundedReLuTestCommon<armnn::DataType::QAsymmU8>(
workloadFactory, memoryManager, tensorHandleFactory, 1.0f, -1.0f,
inputScale, inputOffset, inputScale, inputOffset, // Input/output scale & offset same.
input, output, inputWidth, inputHeight, inputChannels, inputBatchSize);
}
namespace
{
struct BoundedReLuRandomInputTestTraits
{
constexpr static unsigned int inputHeight = 31u;
constexpr static unsigned int inputWidth = 19u;
constexpr static unsigned int inputChannels = 4u;
constexpr static unsigned int inputBatchSize = 2;
constexpr static unsigned int outputHeight = inputHeight;
constexpr static unsigned int outputWidth = inputWidth;
constexpr static unsigned int outputChannels = inputChannels;
constexpr static unsigned int outputBatchSize = inputBatchSize;
static armnn::TensorInfo GetInputTensorInfo()
{
return armnn::TensorInfo({ inputBatchSize, inputChannels, inputHeight, inputWidth },
armnn::DataType::Float32);
}
static armnn::TensorInfo GetOutputTensorInfo()
{
return armnn::TensorInfo({ outputBatchSize, outputChannels, outputHeight, outputWidth },
armnn::DataType::Float32);
}
};
std::vector<float> BoundedReLuRandomInputTest(
armnn::IWorkloadFactory& workloadFactory,
const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
const armnn::ITensorHandleFactory& tensorHandleFactory,
float lowerBound,
float upperBound,
const armnn::ActivationDescriptor& activationDescriptor)
{
IgnoreUnused(memoryManager);
const armnn::TensorInfo inputTensorInfo = BoundedReLuRandomInputTestTraits::GetInputTensorInfo();
const armnn::TensorInfo outputTensorInfo = BoundedReLuRandomInputTestTraits::GetOutputTensorInfo();
// Min/max random values passed to MakeRandomTensor are purposely outside of the ReLu
// range [lowerBound, upperBound].
std::vector<float> input = MakeRandomTensor<float>(inputTensorInfo, 4605828, lowerBound - 5.0f, upperBound * 2.0f);
std::vector<float> actualOutput(outputTensorInfo.GetNumElements());
std::unique_ptr<armnn::ITensorHandle> inputHandle = tensorHandleFactory.CreateTensorHandle(inputTensorInfo);
std::unique_ptr<armnn::ITensorHandle> outputHandle = tensorHandleFactory.CreateTensorHandle(outputTensorInfo);
// Set up bounded ReLu.
armnn::ActivationQueueDescriptor descriptor;
armnn::WorkloadInfo workloadInfo;
AddInputToWorkload(descriptor, workloadInfo, inputTensorInfo, inputHandle.get());
AddOutputToWorkload(descriptor, workloadInfo, outputTensorInfo, outputHandle.get());
descriptor.m_Parameters = activationDescriptor;
std::unique_ptr<armnn::IWorkload> workload = workloadFactory.CreateWorkload(armnn::LayerType::Activation,
descriptor, workloadInfo);
inputHandle->Allocate();
outputHandle->Allocate();
CopyDataToITensorHandle(inputHandle.get(), input.data());
workload->Execute();
CopyDataFromITensorHandle(actualOutput.data(), outputHandle.get());
return actualOutput;
}
} // namespace
LayerTestResult<float, 4> CompareBoundedReLuTest(
armnn::IWorkloadFactory& workloadFactory,
const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
armnn::IWorkloadFactory& refWorkloadFactory,
const armnn::ITensorHandleFactory& tensorHandleFactory,
const armnn::ITensorHandleFactory& refTensorHandleFactory,
float upperBound,
float lowerBound)
{
LayerTestResult<float, 4> result(BoundedReLuRandomInputTestTraits::GetOutputTensorInfo());
armnn::ActivationDescriptor activationDescriptor;
activationDescriptor.m_Function = armnn::ActivationFunction::BoundedReLu;
activationDescriptor.m_A = upperBound;
activationDescriptor.m_B = lowerBound;
result.m_ActualData = BoundedReLuRandomInputTest(
workloadFactory, memoryManager, tensorHandleFactory, 0.0f, upperBound, activationDescriptor);
result.m_ExpectedData = BoundedReLuRandomInputTest(
refWorkloadFactory, nullptr, refTensorHandleFactory, 0.0f, upperBound, activationDescriptor);
return result;
}
template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
LayerTestResult<T, 4> ConstantLinearActivationTestCommon(
armnn::IWorkloadFactory& workloadFactory,
const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
const armnn::ITensorHandleFactory& tensorHandleFactory,
float qScale = 1.0f,
int32_t qOffset = 0)
{
IgnoreUnused(memoryManager);
unsigned int inputHeight = 20;
unsigned int inputWidth = 17;
unsigned int inputChannels = 3;
unsigned int batchSize = 5;
armnn::TensorInfo inputTensorInfo;
armnn::TensorInfo outputTensorInfo;
unsigned int shape[] = {batchSize, inputChannels, inputHeight, inputWidth};
inputTensorInfo = armnn::TensorInfo(4, shape, ArmnnType);
outputTensorInfo = armnn::TensorInfo(4, shape, ArmnnType);
// Set quantization parameters if the requested type is a quantized type.
if(armnn::IsQuantizedType<T>())
{
inputTensorInfo.SetQuantizationScale(qScale);
inputTensorInfo.SetQuantizationOffset(qOffset);
outputTensorInfo.SetQuantizationScale(qScale);
outputTensorInfo.SetQuantizationOffset(qOffset);
}
std::unique_ptr<armnn::ITensorHandle> inputHandle = tensorHandleFactory.CreateTensorHandle(inputTensorInfo);
std::unique_ptr<armnn::ITensorHandle> outputHandle = tensorHandleFactory.CreateTensorHandle(outputTensorInfo);
// Do linear activation that should leave the tensor unchanged.
armnn::ActivationQueueDescriptor data;
armnn::WorkloadInfo info;
AddInputToWorkload(data, info, inputTensorInfo, inputHandle.get());
AddOutputToWorkload(data, info, outputTensorInfo, outputHandle.get());
data.m_Parameters.m_A = 1.0f;
data.m_Parameters.m_B = 0.0f;
data.m_Parameters.m_Function = armnn::ActivationFunction::Linear;
std::unique_ptr<armnn::IWorkload> workload = workloadFactory.CreateWorkload(armnn::LayerType::Activation,
data, info);
inputHandle->Allocate();
outputHandle->Allocate();
std::vector<T> input = MakeRandomTensor<T>(inputTensorInfo, 7123561);
std::vector<T> actualOutput(outputTensorInfo.GetNumElements());
CopyDataToITensorHandle(inputHandle.get(), input.data());
workload->Execute();
CopyDataFromITensorHandle(actualOutput.data(), outputHandle.get());
// Use input as ExpectedData as tensor doesn't change.
return LayerTestResult<T, 4>(actualOutput,
input,
outputHandle->GetShape(),
outputTensorInfo.GetShape());
}
LayerTestResult<float, 4> ConstantLinearActivationTest(
armnn::IWorkloadFactory& workloadFactory,
const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
const armnn::ITensorHandleFactory& tensorHandleFactory)
{
return ConstantLinearActivationTestCommon<armnn::DataType::Float32>(workloadFactory,
memoryManager,
tensorHandleFactory);
}
LayerTestResult<uint8_t, 4> ConstantLinearActivationUint8Test(
armnn::IWorkloadFactory& workloadFactory,
const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
const armnn::ITensorHandleFactory& tensorHandleFactory)
{
return ConstantLinearActivationTestCommon<armnn::DataType::QAsymmU8>(
workloadFactory, memoryManager, tensorHandleFactory, 4.0f, 3);
}
LayerTestResult<int16_t, 4> ConstantLinearActivationInt16Test(
armnn::IWorkloadFactory& workloadFactory,
const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
const armnn::ITensorHandleFactory& tensorHandleFactory)
{
return ConstantLinearActivationTestCommon<armnn::DataType::QSymmS16>(
workloadFactory, memoryManager, tensorHandleFactory, 0.1f, 0);
}
template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
LayerTestResult<T, 4> SimpleActivationTest(
armnn::IWorkloadFactory& workloadFactory,
const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
const armnn::ITensorHandleFactory& tensorHandleFactory,
armnn::ActivationFunction activationFunction,
float activationParameterA,
float activationParameterB,
float scale,
int32_t offset,
const std::vector<float>& inputData,
float outScale,
int32_t outOffset,
const std::vector<float>& outputExpectedData)
{
IgnoreUnused(memoryManager);
constexpr static unsigned int inputWidth = 16u;
constexpr static unsigned int inputHeight = 1u;
constexpr static unsigned int inputChannels = 1u;
constexpr static unsigned int inputBatchSize = 1u;
constexpr static unsigned int outputWidth = inputWidth;
constexpr static unsigned int outputHeight = inputHeight;
constexpr static unsigned int outputChannels = inputChannels;
constexpr static unsigned int outputBatchSize = inputBatchSize;
armnn::TensorInfo inputTensorInfo({ inputBatchSize, inputChannels, inputHeight, inputWidth }, ArmnnType);
armnn::TensorInfo outputTensorInfo({ outputBatchSize, outputChannels, outputHeight, outputWidth }, ArmnnType);
// Set quantization parameters if the requested type is a quantized type.
if(armnn::IsQuantizedType<T>())
{
inputTensorInfo.SetQuantizationScale(scale);
inputTensorInfo.SetQuantizationOffset(offset);
outputTensorInfo.SetQuantizationScale(outScale);
outputTensorInfo.SetQuantizationOffset(outOffset);
}
std::vector<T> input = armnnUtils::QuantizedVector<T>(inputData, scale, offset);
// Calculated outputExpected manually.
std::vector<T> actualOutput(outputTensorInfo.GetNumElements());
std::vector<T> outputExpected = armnnUtils::QuantizedVector<T>(outputExpectedData, outScale, outOffset);
std::unique_ptr<armnn::ITensorHandle> inputHandle = tensorHandleFactory.CreateTensorHandle(inputTensorInfo);
std::unique_ptr<armnn::ITensorHandle> outputHandle = tensorHandleFactory.CreateTensorHandle(outputTensorInfo);
// Setup bounded ReLu.
armnn::ActivationQueueDescriptor descriptor;
armnn::WorkloadInfo workloadInfo;
AddInputToWorkload(descriptor, workloadInfo, inputTensorInfo, inputHandle.get());
AddOutputToWorkload(descriptor, workloadInfo, outputTensorInfo, outputHandle.get());
descriptor.m_Parameters.m_Function = activationFunction;
descriptor.m_Parameters.m_A = activationParameterA;
descriptor.m_Parameters.m_B = activationParameterB;
std::unique_ptr<armnn::IWorkload> workload = workloadFactory.CreateWorkload(armnn::LayerType::Activation,
descriptor, workloadInfo);
inputHandle->Allocate();
outputHandle->Allocate();
CopyDataToITensorHandle(inputHandle.get(), input.data());
workload->Execute();
CopyDataFromITensorHandle(actualOutput.data(), outputHandle.get());
return LayerTestResult<T, 4>(actualOutput,
outputExpected,
outputHandle->GetShape(),
outputTensorInfo.GetShape());
}
template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
LayerTestResult<T, 4> SimpleSigmoidTestCommon(
armnn::IWorkloadFactory& workloadFactory,
const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
const armnn::ITensorHandleFactory& tensorHandleFactory,
float qScale,
int32_t qOffset)
{
std::vector<float> inputData =
{
-0.1f, -0.2f, -0.3f, -0.4f,
0.1f, 0.2f, 0.3f, 0.4f,
-1.0f, -2.0f, -3.0f, -4.0f,
1.0f, 2.0f, 3.0f, 4.0f
};
// Calculate output values for input.
auto f = [](float value)
{
return 1.0f / (1.0f + std::exp(-value));
};
std::vector<float> m_OutputExpected(inputData.size());
std::transform(inputData.begin(), inputData.end(), m_OutputExpected.begin(), f);
return SimpleActivationTest<ArmnnType>(workloadFactory,
memoryManager,
tensorHandleFactory,
armnn::ActivationFunction::Sigmoid,
0.f,
0.f,
qScale,
qOffset,
inputData,
1.f / 256.f,
0,
m_OutputExpected);
}
LayerTestResult<float, 4> SimpleSigmoidTest(
armnn::IWorkloadFactory& workloadFactory,
const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
const armnn::ITensorHandleFactory& tensorHandleFactory)
{
return SimpleSigmoidTestCommon<armnn::DataType::Float32>(workloadFactory, memoryManager,
tensorHandleFactory, 0.0f, 0);
}
LayerTestResult<uint8_t, 4> SimpleSigmoidUint8Test(
armnn::IWorkloadFactory& workloadFactory,
const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
const armnn::ITensorHandleFactory& tensorHandleFactory)
{
return SimpleSigmoidTestCommon<armnn::DataType::QAsymmU8>(workloadFactory, memoryManager,
tensorHandleFactory, 0.1f, 50);
}
LayerTestResult<int16_t, 4> SimpleSigmoidInt16Test(
armnn::IWorkloadFactory& workloadFactory,
const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
const armnn::ITensorHandleFactory& tensorHandleFactory)
{
return SimpleSigmoidTestCommon<armnn::DataType::QSymmS16>(workloadFactory, memoryManager,
tensorHandleFactory, 0.1f, 0);
}
template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
LayerTestResult<T, 4> ReLuTestCommon(
armnn::IWorkloadFactory& workloadFactory,
const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
const armnn::ITensorHandleFactory& tensorHandleFactory,
float qScale,
int32_t qOffset)
{
std::vector<float> inputData = {
-0.1f, -0.2f, -0.3f, -0.4f,
0.1f, 0.2f, 0.3f, 0.4f,
-1.0f, -2.0f, -3.0f, -4.0f,
1.0f, 2.0f, 3.0f, 4.0f
};
// Calculate output values for input.
auto f = [](float value)
{
return std::fmax(0.0f, value);
};
std::vector<float> outputExpected(inputData.size());
std::transform(inputData.begin(), inputData.end(), outputExpected.begin(), f);
return SimpleActivationTest<ArmnnType>(workloadFactory,
memoryManager,
tensorHandleFactory,
armnn::ActivationFunction::ReLu,
0.f,
0.f,
qScale,
qOffset,
inputData,
qScale,
qOffset,
outputExpected);
}
LayerTestResult<int16_t, 4> ReLuInt16Test(
armnn::IWorkloadFactory& workloadFactory,
const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
const armnn::ITensorHandleFactory& tensorHandleFactory)
{
return ReLuTestCommon<armnn::DataType::QSymmS16>(workloadFactory, memoryManager, tensorHandleFactory, 0.1f, 0);
}
LayerTestResult<uint8_t, 4> ReLuUint8Test(
armnn::IWorkloadFactory& workloadFactory,
const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
const armnn::ITensorHandleFactory& tensorHandleFactory)
{
return ReLuTestCommon<armnn::DataType::QAsymmU8>(workloadFactory, memoryManager, tensorHandleFactory, 0.1f, 0);
}
LayerTestResult<float, 4> ReLuTest(
armnn::IWorkloadFactory& workloadFactory,
const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
const armnn::ITensorHandleFactory& tensorHandleFactory)
{
return ReLuTestCommon<armnn::DataType::Float32>(workloadFactory, memoryManager, tensorHandleFactory, 0.1f, 0);
}
template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
LayerTestResult<T, 4> BoundedReLuTestCommon(
armnn::IWorkloadFactory& workloadFactory,
const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
const armnn::ITensorHandleFactory& tensorHandleFactory,
float qScale,
int32_t qOffset)
{
std::vector<float> inputData = {
-0.1f, -0.2f, -0.3f, -0.4f,
0.1f, 0.2f, 0.3f, 0.4f,
-1.0f, -2.0f, -3.0f, -4.0f,
1.0f, 2.0f, 3.0f, 4.0f
};
const float a = 1.0f;
const float b = -1.0f;
// Calculate output values for input.
auto f = [a, b](float value)
{
return std::min(a, std::max(b, value));
};
std::vector<float> outputExpected(inputData.size());
std::transform(inputData.begin(), inputData.end(), outputExpected.begin(), f);
return SimpleActivationTest<ArmnnType>(workloadFactory,
memoryManager,
tensorHandleFactory,
armnn::ActivationFunction::BoundedReLu,
a,
b,
qScale,
qOffset,
inputData,
qScale,
qOffset,
outputExpected);
}
LayerTestResult<int16_t, 4> BoundedReLuInt16Test(
armnn::IWorkloadFactory& workloadFactory,
const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
const armnn::ITensorHandleFactory& tensorHandleFactory)
{
return ReLuTestCommon<armnn::DataType::QSymmS16>(workloadFactory, memoryManager, tensorHandleFactory, 0.1f, 0);
}
template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
LayerTestResult<T, 4> SoftReLuTestCommon(
armnn::IWorkloadFactory& workloadFactory,
const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
const armnn::ITensorHandleFactory& tensorHandleFactory,
float qScale,
int32_t qOffset)
{
std::vector<float> inputData = {
-0.1f, -0.2f, -0.3f, -0.4f,
0.1f, 0.2f, 0.3f, 0.4f,
-1.0f, -2.0f, -3.0f, -4.0f,
1.0f, 2.0f, 3.0f, 4.0f
};
// Calculate output values for input.
auto f = [](float value)
{
return std::log(1.0f + std::exp(value));
};
std::vector<float> outputExpected(inputData.size());
std::transform(inputData.begin(), inputData.end(), outputExpected.begin(), f);
return SimpleActivationTest<ArmnnType>(workloadFactory,
memoryManager,
tensorHandleFactory,
armnn::ActivationFunction::SoftReLu,
0.f,
0.f,
qScale,
qOffset,
inputData,
qScale,
qOffset,
outputExpected);
}
LayerTestResult<float, 4> SoftReLuTest(
armnn::IWorkloadFactory& workloadFactory,
const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
const armnn::ITensorHandleFactory& tensorHandleFactory)
{
return SoftReLuTestCommon<armnn::DataType::Float32>(workloadFactory, memoryManager, tensorHandleFactory, 0.1f, 0);
}
LayerTestResult<uint8_t, 4> SoftReLuUint8Test(
armnn::IWorkloadFactory& workloadFactory,
const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
const armnn::ITensorHandleFactory& tensorHandleFactory)
{
return SoftReLuTestCommon<armnn::DataType::QAsymmU8>(workloadFactory, memoryManager,
tensorHandleFactory, 0.0625f, 64);
}
LayerTestResult<int16_t, 4> SoftReLuInt16Test(
armnn::IWorkloadFactory& workloadFactory,
const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
const armnn::ITensorHandleFactory& tensorHandleFactory)
{
return SoftReLuTestCommon<armnn::DataType::QSymmS16>(workloadFactory, memoryManager, tensorHandleFactory, 0.1f, 0);
}
template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
LayerTestResult<T, 4> LeakyReLuTestCommon(
armnn::IWorkloadFactory& workloadFactory,
const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
const armnn::ITensorHandleFactory& tensorHandleFactory,
float qScale,
int32_t qOffset)
{
std::vector<float> inputData = {
-0.1f, -0.2f, -0.3f, -0.4f,
0.1f, 0.2f, 0.3f, 0.4f,
-1.0f, -2.0f, -3.0f, -4.0f,
1.0f, 2.0f, 3.0f, 4.0f
};
const float a = 0.01f;
// Calculate output values for input.
auto f = [a](float value)
{
return value > 0.0f ? value : (value * a);
};
std::vector<float> outputExpected(inputData.size());
std::transform(inputData.begin(), inputData.end(), outputExpected.begin(), f);
return SimpleActivationTest<ArmnnType>(workloadFactory,
memoryManager,
tensorHandleFactory,
armnn::ActivationFunction::LeakyReLu,
a,
0.f,
qScale,
qOffset,
inputData,
qScale,
qOffset,
outputExpected);
}
LayerTestResult<float, 4> LeakyReLuTest(
armnn::IWorkloadFactory& workloadFactory,
const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
const armnn::ITensorHandleFactory& tensorHandleFactory)
{
return LeakyReLuTestCommon<armnn::DataType::Float32>(workloadFactory, memoryManager, tensorHandleFactory, 0.1f, 0);
}
LayerTestResult<uint8_t, 4> LeakyReLuUint8Test(
armnn::IWorkloadFactory& workloadFactory,
const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
const armnn::ITensorHandleFactory& tensorHandleFactory)
{
return LeakyReLuTestCommon<armnn::DataType::QAsymmU8>(workloadFactory, memoryManager,
tensorHandleFactory, 0.0625f, 64);
}
LayerTestResult<int16_t, 4> LeakyReLuInt16Test(
armnn::IWorkloadFactory& workloadFactory,
const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
const armnn::ITensorHandleFactory& tensorHandleFactory)
{
return LeakyReLuTestCommon<armnn::DataType::QSymmS16>(workloadFactory, memoryManager, tensorHandleFactory, 0.1f, 0);
}
template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
LayerTestResult<T, 4> AbsTestCommon(
armnn::IWorkloadFactory& workloadFactory,
const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
const armnn::ITensorHandleFactory& tensorHandleFactory,
float qScale,
int32_t qOffset)
{
std::vector<float> inputData = {
-0.1f, -0.2f, -0.3f, -0.4f,
0.1f, 0.2f, 0.3f, 0.4f,
-1.0f, -2.0f, -3.0f, -4.0f,
1.0f, 2.0f, 3.0f, 4.0f
};
// Calculate output values for input.
auto f = [](float value)
{
return std::abs(value);
};
std::vector<float> outputExpected(inputData.size());
std::transform(inputData.begin(), inputData.end(), outputExpected.begin(), f);
return SimpleActivationTest<ArmnnType>(workloadFactory,
memoryManager,
tensorHandleFactory,
armnn::ActivationFunction::Abs,
0.f,
0.f,
qScale,
qOffset,
inputData,
qScale,
qOffset,
outputExpected);
}
LayerTestResult<float, 4> AbsTest(
armnn::IWorkloadFactory& workloadFactory,
const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
const armnn::ITensorHandleFactory& tensorHandleFactory)
{
return AbsTestCommon<armnn::DataType::Float32>(workloadFactory, memoryManager, tensorHandleFactory, 0.1f, 0);
}
LayerTestResult<uint8_t, 4> AbsUint8Test(
armnn::IWorkloadFactory& workloadFactory,
const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
const armnn::ITensorHandleFactory& tensorHandleFactory)
{
return AbsTestCommon<armnn::DataType::QAsymmU8>(workloadFactory, memoryManager, tensorHandleFactory, 0.0625f, 64);
}
LayerTestResult<int16_t, 4> AbsInt16Test(
armnn::IWorkloadFactory& workloadFactory,
const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
const armnn::ITensorHandleFactory& tensorHandleFactory)
{
return AbsTestCommon<armnn::DataType::QSymmS16>(workloadFactory, memoryManager, tensorHandleFactory, 0.1f, 0);
}
LayerTestResult<float, 5> SqrtNNTest(
armnn::IWorkloadFactory& workloadFactory,
const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
const armnn::ITensorHandleFactory& tensorHandleFactory)
{
IgnoreUnused(memoryManager);
const int inputDataSize = 120;
std::vector<float> inputData(inputDataSize);
for (unsigned int i = 0u; i < inputDataSize; ++i)
{
inputData[i] = static_cast<float>(i) / 10;
}
auto f = [](float value)
{
return std::sqrt(value);
};
std::vector<float> expectedOutput(inputDataSize);
std::transform(inputData.begin(), inputData.end(), expectedOutput.begin(), f);
armnn::TensorInfo inputTensorInfo(
{ 1u, 2u, 3u, 4u, 5u }, armnn::DataType::Float32);
armnn::TensorInfo outputTensorInfo(
{ 1u, 2u, 3u, 4u, 5u }, armnn::DataType::Float32);
std::vector<float> actualOutput(outputTensorInfo.GetNumElements());
std::unique_ptr<armnn::ITensorHandle> inputHandle = tensorHandleFactory.CreateTensorHandle(inputTensorInfo);
std::unique_ptr<armnn::ITensorHandle> outputHandle = tensorHandleFactory.CreateTensorHandle(outputTensorInfo);
armnn::ActivationQueueDescriptor descriptor;
armnn::WorkloadInfo workloadInfo;
AddInputToWorkload(descriptor, workloadInfo, inputTensorInfo, inputHandle.get());
AddOutputToWorkload(descriptor, workloadInfo, outputTensorInfo, outputHandle.get());
descriptor.m_Parameters.m_Function = armnn::ActivationFunction::Sqrt;
std::unique_ptr<armnn::IWorkload> workload = workloadFactory.CreateWorkload(armnn::LayerType::Activation,
descriptor, workloadInfo);
inputHandle->Allocate();
outputHandle->Allocate();
CopyDataToITensorHandle(inputHandle.get(), inputData.data());
workload->Execute();
CopyDataFromITensorHandle(actualOutput.data(), outputHandle.get());
return LayerTestResult<float, 5>(actualOutput,
expectedOutput,
outputHandle->GetShape(),
outputTensorInfo.GetShape());
};
template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
LayerTestResult<T, 4> SqrtTestCommon(
armnn::IWorkloadFactory& workloadFactory,
const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
const armnn::ITensorHandleFactory& tensorHandleFactory,
float qScale,
int32_t qOffset)
{
std::vector<float> inputData = {
0.1f, 0.2f, 0.3f, 0.4f,
0.1f, 0.2f, 0.3f, 0.4f,
1.0f, 2.0f, 3.0f, 4.0f,
1.0f, 2.0f, 3.0f, 4.0f
};
// Calculate output values for input.
auto f = [](float value)
{
return std::sqrt(value);
};
std::vector<float> expectedOutput(inputData.size());
std::transform(inputData.begin(), inputData.end(), expectedOutput.begin(), f);
return SimpleActivationTest<ArmnnType>(workloadFactory,
memoryManager,
tensorHandleFactory,
armnn::ActivationFunction::Sqrt,
0.f,
0.f,
qScale,
qOffset,
inputData,
qScale,
qOffset,
expectedOutput);
}
LayerTestResult<float, 4> SqrtTest(
armnn::IWorkloadFactory& workloadFactory,
const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
const armnn::ITensorHandleFactory& tensorHandleFactory)
{
return SqrtTestCommon<armnn::DataType::Float32>(workloadFactory, memoryManager, tensorHandleFactory, 0.1f, 0);
}
LayerTestResult<uint8_t, 4> SqrtUint8Test(
armnn::IWorkloadFactory& workloadFactory,
const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
const armnn::ITensorHandleFactory& tensorHandleFactory)
{
return SqrtTestCommon<armnn::DataType::QAsymmU8>(workloadFactory, memoryManager, tensorHandleFactory, 0.0625f, 64);
}
LayerTestResult<int16_t, 4> SqrtInt16Test(
armnn::IWorkloadFactory& workloadFactory,
const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
const armnn::ITensorHandleFactory& tensorHandleFactory)
{
return SqrtTestCommon<armnn::DataType::QSymmS16>(workloadFactory, memoryManager, tensorHandleFactory, 0.1f, 0);
}
template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
LayerTestResult<T, 4> SquareTestCommon(
armnn::IWorkloadFactory& workloadFactory,
const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
const armnn::ITensorHandleFactory& tensorHandleFactory,
float qScale,
int32_t qOffset)
{
std::vector<float> inputData = {
-0.1f, -0.2f, -0.3f, -0.4f,
0.1f, 0.2f, 0.3f, 0.4f,
-1.0f, -2.0f, -3.0f, -4.0f,
1.0f, 2.0f, 3.0f, 4.0f
};
// Calculate output values for input.
auto f = [](float value)
{
return std::pow(value,2);
};
std::vector<float> expectedOutput(inputData.size());
std::transform(inputData.begin(), inputData.end(), expectedOutput.begin(), f);
return SimpleActivationTest<ArmnnType>(workloadFactory,
memoryManager,
tensorHandleFactory,
armnn::ActivationFunction::Square,
0.f,
0.f,
qScale,
qOffset,
inputData,
qScale,
qOffset,
expectedOutput);
}
LayerTestResult<float, 4> SquareTest(
armnn::IWorkloadFactory& workloadFactory,
const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
const armnn::ITensorHandleFactory& tensorHandleFactory)
{
return SquareTestCommon<armnn::DataType::Float32>(workloadFactory, memoryManager, tensorHandleFactory, 0.1f, 0);
}
LayerTestResult<uint8_t, 4> SquareUint8Test(
armnn::IWorkloadFactory& workloadFactory,
const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
const armnn::ITensorHandleFactory& tensorHandleFactory)
{
return SquareTestCommon<armnn::DataType::QAsymmU8>(workloadFactory, memoryManager,
tensorHandleFactory, 0.0625f, 64);
}
LayerTestResult<int16_t, 4> SquareInt16Test(
armnn::IWorkloadFactory& workloadFactory,
const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
const armnn::ITensorHandleFactory& tensorHandleFactory)
{
return SquareTestCommon<armnn::DataType::QSymmS16>(workloadFactory, memoryManager, tensorHandleFactory, 0.1f, 0);
}
template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
LayerTestResult<T, 4> TanhTestCommon(
armnn::IWorkloadFactory& workloadFactory,
const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
const armnn::ITensorHandleFactory& tensorHandleFactory,
float qScale,
int32_t qOffset)
{
std::vector<float> inputData = {
-0.1f, -0.2f, -0.3f, -0.4f,
0.1f, 0.2f, 0.3f, 0.4f,
-1.0f, -2.0f, -3.0f, -4.0f,
1.0f, 2.0f, 3.0f, 4.0f
};
const float a = 2.0f;
const float b = 3.0f;
// Calculate output values for input.
auto f = [a, b](float value)
{
return a * tanhf(b * value);
};
std::vector<float> expectedOutput(inputData.size());
std::transform(inputData.begin(), inputData.end(), expectedOutput.begin(), f);
return SimpleActivationTest<ArmnnType>(workloadFactory,
memoryManager,
tensorHandleFactory,
armnn::ActivationFunction::TanH,
a,
b,
qScale,
qOffset,
inputData,
qScale,
qOffset,
expectedOutput);
}
LayerTestResult<float, 4> TanhTest(
armnn::IWorkloadFactory& workloadFactory,
const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
const armnn::ITensorHandleFactory& tensorHandleFactory)
{
return TanhTestCommon<armnn::DataType::Float32>(workloadFactory, memoryManager, tensorHandleFactory, 0.1f, 0);
}
LayerTestResult<uint8_t, 4> TanhUint8Test(
armnn::IWorkloadFactory& workloadFactory,
const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
const armnn::ITensorHandleFactory& tensorHandleFactory)
{
return TanhTestCommon<armnn::DataType::QAsymmU8>(workloadFactory, memoryManager, tensorHandleFactory, 0.1f, 64);
}
LayerTestResult<int16_t, 4> TanhInt16Test(
armnn::IWorkloadFactory& workloadFactory,
const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
const armnn::ITensorHandleFactory& tensorHandleFactory)
{
return TanhTestCommon<armnn::DataType::QSymmS16>(workloadFactory, memoryManager, tensorHandleFactory, 0.1f, 0);
}
template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
LayerTestResult<T, 4> EluTestCommon(
armnn::IWorkloadFactory& workloadFactory,
const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
const armnn::ITensorHandleFactory& tensorHandleFactory,
float qScale,
int32_t qOffset)
{
std::vector<float> inputData = {
-0.1f, -0.2f, -0.3f, -0.4f,
0.1f, 0.2f, 0.3f, 0.4f,
-1.0f, -2.0f, -3.0f, -4.0f,
1.0f, 2.0f, 3.0f, 4.0f
};
const float a = 0.01f;
// Calculate output values for input.
auto f = [a](float value)
{
return (value >= 0) ? value : a * (expf(value) - 1);
};
std::vector<float> expectedOutput(inputData.size());
std::transform(inputData.begin(), inputData.end(), expectedOutput.begin(), f);
return SimpleActivationTest<ArmnnType>(workloadFactory,
memoryManager,
tensorHandleFactory,
armnn::ActivationFunction::Elu,
a,
0.0f,
qScale,
qOffset,
inputData,
qScale,
qOffset,
expectedOutput);
}
LayerTestResult<float, 4> EluTest(
armnn::IWorkloadFactory& workloadFactory,
const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
const armnn::ITensorHandleFactory& tensorHandleFactory)
{
return EluTestCommon<armnn::DataType::Float32>(workloadFactory, memoryManager, tensorHandleFactory, 0.1f, 0);
}
LayerTestResult<uint8_t, 4> EluUint8Test(
armnn::IWorkloadFactory& workloadFactory,
const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
const armnn::ITensorHandleFactory& tensorHandleFactory)
{
return EluTestCommon<armnn::DataType::QAsymmU8>(workloadFactory, memoryManager, tensorHandleFactory, 0.1f, 64);
}
LayerTestResult<int16_t, 4> EluInt16Test(
armnn::IWorkloadFactory& workloadFactory,
const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
const armnn::ITensorHandleFactory& tensorHandleFactory)
{
return EluTestCommon<armnn::DataType::QSymmS16>(workloadFactory, memoryManager, tensorHandleFactory, 0.1f, 0);
}
template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
LayerTestResult<T, 4> HardSwishTestCommon(
armnn::IWorkloadFactory& workloadFactory,
const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
const armnn::ITensorHandleFactory& tensorHandleFactory,
float qScale,
int32_t qOffset)
{
std::vector<float> inputData = {
-0.1f, -0.2f, -0.3f, -0.4f,
0.1f, 0.2f, 0.3f, 0.4f,
-1.0f, -2.0f, -3.0f, -4.0f,
1.0f, 2.0f, 3.0f, 4.0f
};
// Calculate output values for input.
auto f = [](float x)
{
// Break down the calculation to help with verification.
// hard_swish(x) = x * relu6(x+3) / 6
// relu6(x) = min(max(x,0),6)
float reLu6_step1 = std::max((x + 3),0.0f);
float reLu6Complete = std::min(reLu6_step1, 6.0f);
float hardSwish_step1 = x * reLu6Complete;
float result = hardSwish_step1 / 6;
return result;
};
std::vector<float> expectedOutput(inputData.size());
std::transform(inputData.begin(), inputData.end(), expectedOutput.begin(), f);
return SimpleActivationTest<ArmnnType>(workloadFactory,
memoryManager,
tensorHandleFactory,
armnn::ActivationFunction::HardSwish,
0.f,
0.f,
qScale,
qOffset,
inputData,
qScale,
qOffset,
expectedOutput);
}
LayerTestResult<float, 4> HardSwishTest(
armnn::IWorkloadFactory& workloadFactory,
const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
const armnn::ITensorHandleFactory& tensorHandleFactory)
{
return HardSwishTestCommon<armnn::DataType::Float32>(workloadFactory, memoryManager, tensorHandleFactory, 0.1f, 0);
}
LayerTestResult<uint8_t, 4> HardSwishUint8Test(
armnn::IWorkloadFactory& workloadFactory,
const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
const armnn::ITensorHandleFactory& tensorHandleFactory)
{
return HardSwishTestCommon<armnn::DataType::QAsymmU8>(workloadFactory, memoryManager,
tensorHandleFactory, 0.1f, 64);
}
LayerTestResult<int16_t, 4> HardSwishInt16Test(
armnn::IWorkloadFactory& workloadFactory,
const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
const armnn::ITensorHandleFactory& tensorHandleFactory)
{
return HardSwishTestCommon<armnn::DataType::QSymmS16>(workloadFactory, memoryManager, tensorHandleFactory, 0.1f, 0);
}
template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
LayerTestResult<T, 4> GeluTestCommon(
armnn::IWorkloadFactory& workloadFactory,
const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
const armnn::ITensorHandleFactory& tensorHandleFactory,
float qScale,
int32_t qOffset)
{
std::vector<float> inputData =
{
-0.1f, -0.2f, -0.3f, -0.4f,
0.1f, 0.2f, 0.3f, 0.4f,
-1.0f, -2.0f, -3.0f, -4.0f,
1.0f, 2.0f, 3.0f, 4.0f
};
// Calculate output values for input.
auto f = [](float x)
{
// gelu(x) = x * 1/2 * (1 + erf(x / sqrt(2))),
// where erf is Gaussian error function
auto result = x * (0.5f * (1.0f + erff(static_cast<float>(x / std::sqrt(2)))));
return result;
};
std::vector<float> expectedOutput(inputData.size());
std::transform(inputData.begin(), inputData.end(), expectedOutput.begin(), f);
return SimpleActivationTest<ArmnnType>(workloadFactory,
memoryManager,
tensorHandleFactory,
armnn::ActivationFunction::Gelu,
0.f,
0.f,
qScale,
qOffset,
inputData,
qScale,
qOffset,
expectedOutput);
}
LayerTestResult<float, 4> GeluTest(
armnn::IWorkloadFactory& workloadFactory,
const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
const armnn::ITensorHandleFactory& tensorHandleFactory)
{
return GeluTestCommon<armnn::DataType::Float32>(workloadFactory, memoryManager, tensorHandleFactory, 0.1f, 0);
}
LayerTestResult<uint8_t, 4> GeluUint8Test(
armnn::IWorkloadFactory& workloadFactory,
const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
const armnn::ITensorHandleFactory& tensorHandleFactory)
{
return GeluTestCommon<armnn::DataType::QAsymmU8>(workloadFactory, memoryManager, tensorHandleFactory, 0.1f, 64);
}
LayerTestResult<int16_t, 4> GeluInt16Test(
armnn::IWorkloadFactory& workloadFactory,
const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
const armnn::ITensorHandleFactory& tensorHandleFactory)
{
return GeluTestCommon<armnn::DataType::QSymmS16>(workloadFactory, memoryManager, tensorHandleFactory, 0.1f, 0);
}
template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
LayerTestResult<T, 4> CompareActivationTestImpl(
armnn::IWorkloadFactory& workloadFactory,
const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
armnn::IWorkloadFactory& refWorkloadFactory,
const armnn::ITensorHandleFactory& tensorHandleFactory,
const armnn::ITensorHandleFactory& refTensorHandleFactory,
armnn::ActivationFunction f,
unsigned int batchSize = 5,
float qScale = 1.0f,
int32_t qOffset = 0)
{
IgnoreUnused(memoryManager);
unsigned int width = 17;
unsigned int height = 29;
unsigned int channels = 2;
float a = 0.234f;
float b = -12.345f;
armnn::TensorInfo inputTensorInfo;
armnn::TensorInfo outputTensorInfo;
unsigned int shape[] = {batchSize, channels, height, width};
inputTensorInfo = armnn::TensorInfo(4, shape, ArmnnType);
outputTensorInfo = armnn::TensorInfo(4, shape, ArmnnType);
// Set quantization parameters if the requested type is a quantized type.
if(armnn::IsQuantizedType<T>())
{
inputTensorInfo.SetQuantizationScale(qScale);
inputTensorInfo.SetQuantizationOffset(qOffset);
outputTensorInfo.SetQuantizationScale(qScale);
outputTensorInfo.SetQuantizationOffset(qOffset);
}
float minVal = -10.f;
if (f == armnn::ActivationFunction::Sqrt)
{
minVal = 0.f;
}
std::vector<T> input = MakeRandomTensor<T>(inputTensorInfo, 21453, minVal, 10.f);
std::vector<T> actualOutput(outputTensorInfo.GetNumElements());
std::vector<T> expectedOutput(outputTensorInfo.GetNumElements());
std::unique_ptr<armnn::ITensorHandle> inputHandle = tensorHandleFactory.CreateTensorHandle(inputTensorInfo);
std::unique_ptr<armnn::ITensorHandle> outputHandle = tensorHandleFactory.CreateTensorHandle(outputTensorInfo);
std::unique_ptr<armnn::ITensorHandle> inputHandleRef = refTensorHandleFactory.CreateTensorHandle(inputTensorInfo);
std::unique_ptr<armnn::ITensorHandle> outputHandleRef = refTensorHandleFactory.CreateTensorHandle(outputTensorInfo);
armnn::ActivationQueueDescriptor data;
armnn::WorkloadInfo info;
AddInputToWorkload(data, info, inputTensorInfo, inputHandle.get());
AddOutputToWorkload(data, info, outputTensorInfo, outputHandle.get());
data.m_Parameters.m_A = a;
data.m_Parameters.m_B = b;
data.m_Parameters.m_Function = f;
armnn::ActivationQueueDescriptor refData = data;
armnn::WorkloadInfo refInfo = info;
SetWorkloadInput(refData, refInfo, 0, inputTensorInfo, inputHandleRef.get());
SetWorkloadOutput(refData, refInfo, 0, outputTensorInfo, outputHandleRef.get());
std::unique_ptr<armnn::IWorkload> workload = workloadFactory.CreateWorkload(armnn::LayerType::Activation,
data, info);
CHECK(workload != nullptr);
std::unique_ptr<armnn::IWorkload> workloadRef = refWorkloadFactory.CreateWorkload(armnn::LayerType::Activation,
refData, refInfo);
CHECK(workloadRef != nullptr);
inputHandle->Allocate();
outputHandle->Allocate();
inputHandleRef->Allocate();
outputHandleRef->Allocate();
CopyDataToITensorHandle(inputHandle.get(), input.data());
CopyDataToITensorHandle(inputHandleRef.get(), input.data());
workload->Execute();
workloadRef->Execute();
CopyDataFromITensorHandle(actualOutput.data(), outputHandle.get());
CopyDataFromITensorHandle(expectedOutput.data(), outputHandleRef.get());
return LayerTestResult<T, 4>(actualOutput,
expectedOutput,
outputHandle->GetShape(),
outputTensorInfo.GetShape());
}
LayerTestResult<float, 4> CompareActivationTest(
armnn::IWorkloadFactory& workloadFactory,
const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
armnn::IWorkloadFactory& refWorkloadFactory,
const armnn::ITensorHandleFactory& tensorHandleFactory,
const armnn::ITensorHandleFactory& refTensorHandleFactory,
armnn::ActivationFunction f,
unsigned int batchSize)
{
return CompareActivationTestImpl<armnn::DataType::Float32>(
workloadFactory, memoryManager, refWorkloadFactory, tensorHandleFactory,
refTensorHandleFactory, f, batchSize);
}
LayerTestResult<uint8_t, 4> CompareActivationUint8Test(
armnn::IWorkloadFactory& workloadFactory,
const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
armnn::IWorkloadFactory& refWorkloadFactory,
const armnn::ITensorHandleFactory& tensorHandleFactory,
const armnn::ITensorHandleFactory& refTensorHandleFactory,
armnn::ActivationFunction f)
{
return CompareActivationTestImpl<armnn::DataType::QAsymmU8>(
workloadFactory, memoryManager, refWorkloadFactory,
tensorHandleFactory, refTensorHandleFactory, f, 5, 0.1f, 50);
}
LayerTestResult<int16_t, 4> CompareActivationInt16Test(
armnn::IWorkloadFactory& workloadFactory,
const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
armnn::IWorkloadFactory& refWorkloadFactory,
const armnn::ITensorHandleFactory& tensorHandleFactory,
const armnn::ITensorHandleFactory& refTensorHandleFactory,
armnn::ActivationFunction f)
{
return CompareActivationTestImpl<armnn::DataType::QSymmS16>(
workloadFactory, memoryManager, refWorkloadFactory, tensorHandleFactory,
refTensorHandleFactory, f, 5, 0.1f, 0);
}