From 2a304ede65afb3426dccbd742ac3f5b42e8fb04a Mon Sep 17 00:00:00 2001 From: Nattapat Chaimanowong Date: Thu, 21 Mar 2019 11:02:13 +0000 Subject: IVGCVSW-2859 Add unit tests for QSymm16 quantization * Add quantization test under QSymm16 scheme for all layers * Refactor existing tests to reduce code duplication Change-Id: I66c9437b3247d78acbb4ebc2c2481f3238268038 Signed-off-by: Nattapat Chaimanowong --- src/armnn/test/QuantizerTest.cpp | 928 +++++++++++++++++++++++---------------- 1 file changed, 553 insertions(+), 375 deletions(-) (limited to 'src/armnn/test') diff --git a/src/armnn/test/QuantizerTest.cpp b/src/armnn/test/QuantizerTest.cpp index eead9b7f36..86070ebc97 100644 --- a/src/armnn/test/QuantizerTest.cpp +++ b/src/armnn/test/QuantizerTest.cpp @@ -11,7 +11,6 @@ #include "armnn/LayerVisitorBase.hpp" #include "../Graph.hpp" #include "../Network.hpp" -#include "../NetworkQuantizationScheme.hpp" #include "../NetworkQuantizerUtils.hpp" #include "../OverrideInputRangeVisitor.hpp" #include "../RangeTracker.hpp" @@ -27,7 +26,8 @@ using MinMaxRange = std::pair; using MinMaxRanges = std::vector; using MinMaxRangeMap = std::unordered_map; -const float g_QuantizationBase = 255.0f; +const float g_Asymm8QuantizationBase = 255.0f; +const float g_Symm16QuantizationBase = 32767.0f; const float g_TestTolerance = 0.000001f; BOOST_AUTO_TEST_SUITE(Quantizer) @@ -35,24 +35,63 @@ BOOST_AUTO_TEST_SUITE(Quantizer) class TestQuantization : public LayerVisitorBase { public: + TestQuantization() + : LayerVisitorBase() + , m_QuantizerOptions(QuantizerOptions()) {} + + TestQuantization(const QuantizerOptions& options) + : LayerVisitorBase() + , m_QuantizerOptions(options) {} + void VisitInputLayer(const IConnectableLayer* layer, LayerBindingId id, const char* name = nullptr) override { TensorInfo info = layer->GetOutputSlot(0).GetTensorInfo(); - BOOST_TEST((info.GetDataType() == DataType::QuantisedAsymm8)); - - BOOST_TEST((info.GetQuantizationOffset() == 128)); - // Based off current default [-15.0f, 15.0f] - BOOST_CHECK_CLOSE(info.GetQuantizationScale(), 30.0f / g_QuantizationBase, g_TestTolerance); + TestQuantizationParams(info, {30.0f / g_Asymm8QuantizationBase, 128}, {15.0f / g_Symm16QuantizationBase, 0}); } void VisitOutputLayer(const IConnectableLayer* layer, LayerBindingId id, const char* name = nullptr) override {} + +protected: + void TestQuantizationParams(const TensorInfo& info, + const OffsetScalePair& qAsymm8Params, + const OffsetScalePair& qSymm16Params) + { + switch (m_QuantizerOptions.m_ActivationFormat) + { + case DataType::QuantisedAsymm8: + TestQuantizationParamsImpl( + info, DataType::QuantisedAsymm8, qAsymm8Params.first, qAsymm8Params.second); + break; + case DataType::QuantisedSymm16: + TestQuantizationParamsImpl( + info, DataType::QuantisedSymm16, qSymm16Params.first, qSymm16Params.second); + break; + default: + throw InvalidArgumentException("Unsupported quantization target"); + } + } + + void TestConstantQuantizationParams(const TensorInfo& info, const OffsetScalePair& params) + { + TestQuantizationParamsImpl(info, DataType::QuantisedAsymm8, params.first, params.second); + } + +private: + void TestQuantizationParamsImpl(const TensorInfo& info, DataType dataType, float scale, int32_t offset) + { + BOOST_TEST((info.GetDataType() == dataType)); + BOOST_TEST(info.GetQuantizationOffset() == offset); + BOOST_CHECK_CLOSE(info.GetQuantizationScale(), scale, g_TestTolerance); + } + + QuantizerOptions m_QuantizerOptions; }; void VisitLayersTopologically(const INetwork* inputNetwork, ILayerVisitor& visitor) @@ -66,23 +105,25 @@ void VisitLayersTopologically(const INetwork* inputNetwork, ILayerVisitor& visit class TestAdditionQuantization : public TestQuantization { public: + TestAdditionQuantization() + : TestQuantization() {} + + TestAdditionQuantization(const QuantizerOptions& options) + : TestQuantization(options) {} + void VisitAdditionLayer(const IConnectableLayer* layer, const char* name = nullptr) override { TensorInfo info = layer->GetOutputSlot(0).GetTensorInfo(); - BOOST_TEST((info.GetDataType() == DataType::QuantisedAsymm8)); - - BOOST_TEST((info.GetQuantizationOffset() == 128)); - - // Based off current static value [-20.0f, 20.0f] - BOOST_CHECK_CLOSE(info.GetQuantizationScale(), 40.0f / g_QuantizationBase, g_TestTolerance); + // Based off default static range [-20.0f, 20.0f] + TestQuantizationParams(info, {40.0f / g_Asymm8QuantizationBase, 128}, {20.0f / g_Symm16QuantizationBase, 0}); } }; BOOST_AUTO_TEST_CASE(QuantizeAddition) { - auto network = INetwork::Create(); + INetworkPtr network = INetwork::Create(); // Add the layers IConnectableLayer* input0 = network->AddInputLayer(0); @@ -102,32 +143,39 @@ BOOST_AUTO_TEST_CASE(QuantizeAddition) input1->GetOutputSlot(0).SetTensorInfo(info); addition->GetOutputSlot(0).SetTensorInfo(info); - auto quantizedNetwork = INetworkQuantizer::Create(network.get())->ExportNetwork(); - TestAdditionQuantization validator; - VisitLayersTopologically(quantizedNetwork.get(), validator); + INetworkPtr quantizedNetworkQAsymm8 = INetworkQuantizer::Create(network.get())->ExportNetwork(); + TestAdditionQuantization validatorQAsymm8; + VisitLayersTopologically(quantizedNetworkQAsymm8.get(), validatorQAsymm8); + + const QuantizerOptions options(DataType::QuantisedSymm16); + INetworkPtr quantizedNetworkQSymm16 = INetworkQuantizer::Create(network.get(), options)->ExportNetwork(); + TestAdditionQuantization validatorQSymm16(options); + VisitLayersTopologically(quantizedNetworkQSymm16.get(), validatorQSymm16); } class TestActivationQuantization : public TestQuantization { public: + TestActivationQuantization() + : TestQuantization() {} + + TestActivationQuantization(const QuantizerOptions& options) + : TestQuantization(options) {} + void VisitActivationLayer(const IConnectableLayer* layer, const ActivationDescriptor& descriptor, const char* name = nullptr) override { TensorInfo info = layer->GetOutputSlot(0).GetTensorInfo(); - BOOST_TEST((info.GetDataType() == DataType::QuantisedAsymm8)); - - BOOST_TEST((info.GetQuantizationOffset() == 0)); - - // Based off current static value [-20.0f, 20.0f] - BOOST_CHECK_CLOSE(info.GetQuantizationScale(), 15.0f / g_QuantizationBase, g_TestTolerance); + // Based off default static range [0.0f, 15.0f] + TestQuantizationParams(info, {15.0f / g_Asymm8QuantizationBase, 0}, {15.0f / g_Symm16QuantizationBase, 0}); } }; INetworkPtr CreateNetworkWithActivationLayer(const ActivationDescriptor& descriptor) { - auto network = INetwork::Create(); + INetworkPtr network = INetwork::Create(); // Add the layers IConnectableLayer* input0 = network->AddInputLayer(0); @@ -154,11 +202,16 @@ BOOST_AUTO_TEST_CASE(QuantizeAbsActivation) descriptor.m_A = 3.5f; descriptor.m_B = -10.0f; - auto network = CreateNetworkWithActivationLayer(descriptor); + INetworkPtr network = CreateNetworkWithActivationLayer(descriptor); - auto quantizedNetwork = INetworkQuantizer::Create(network.get())->ExportNetwork(); - TestActivationQuantization validator; - VisitLayersTopologically(quantizedNetwork.get(), validator); + INetworkPtr quantizedNetworkQAsymm8 = INetworkQuantizer::Create(network.get())->ExportNetwork(); + TestActivationQuantization validatorQAsymm8; + VisitLayersTopologically(quantizedNetworkQAsymm8.get(), validatorQAsymm8); + + const QuantizerOptions options(DataType::QuantisedSymm16); + INetworkPtr quantizedNetworkQSymm16 = INetworkQuantizer::Create(network.get(), options)->ExportNetwork(); + TestActivationQuantization validatorQSymm16(options); + VisitLayersTopologically(quantizedNetworkQSymm16.get(), validatorQSymm16); } BOOST_AUTO_TEST_CASE(QuantizeLinearActivation) @@ -168,11 +221,16 @@ BOOST_AUTO_TEST_CASE(QuantizeLinearActivation) descriptor.m_A = 3.5f; descriptor.m_B = -10.0f; - auto network = CreateNetworkWithActivationLayer(descriptor); + INetworkPtr network = CreateNetworkWithActivationLayer(descriptor); + + INetworkPtr quantizedNetworkQAsymm8 = INetworkQuantizer::Create(network.get())->ExportNetwork(); + TestActivationQuantization validatorQAsymm8; + VisitLayersTopologically(quantizedNetworkQAsymm8.get(), validatorQAsymm8); - auto quantizedNetwork = INetworkQuantizer::Create(network.get())->ExportNetwork(); - TestActivationQuantization validator; - VisitLayersTopologically(quantizedNetwork.get(), validator); + const QuantizerOptions options(DataType::QuantisedSymm16); + INetworkPtr quantizedNetworkQSymm16 = INetworkQuantizer::Create(network.get(), options)->ExportNetwork(); + TestActivationQuantization validatorQSymm16(options); + VisitLayersTopologically(quantizedNetworkQSymm16.get(), validatorQSymm16); } BOOST_AUTO_TEST_CASE(QuantizeReLuActivation) @@ -182,11 +240,16 @@ BOOST_AUTO_TEST_CASE(QuantizeReLuActivation) descriptor.m_A = 3.5f; descriptor.m_B = -10.0f; - auto network = CreateNetworkWithActivationLayer(descriptor); + INetworkPtr network = CreateNetworkWithActivationLayer(descriptor); - auto quantizedNetwork = INetworkQuantizer::Create(network.get())->ExportNetwork(); - TestActivationQuantization validator; - VisitLayersTopologically(quantizedNetwork.get(), validator); + INetworkPtr quantizedNetworkQAsymm8 = INetworkQuantizer::Create(network.get())->ExportNetwork(); + TestActivationQuantization validatorQAsymm8; + VisitLayersTopologically(quantizedNetworkQAsymm8.get(), validatorQAsymm8); + + const QuantizerOptions options(DataType::QuantisedSymm16); + INetworkPtr quantizedNetworkQSymm16 = INetworkQuantizer::Create(network.get(), options)->ExportNetwork(); + TestActivationQuantization validatorQSymm16(options); + VisitLayersTopologically(quantizedNetworkQSymm16.get(), validatorQSymm16); } BOOST_AUTO_TEST_CASE(QuantizeSoftReLuActivation) @@ -196,106 +259,123 @@ BOOST_AUTO_TEST_CASE(QuantizeSoftReLuActivation) descriptor.m_A = 3.5f; descriptor.m_B = -10.0f; - auto network = CreateNetworkWithActivationLayer(descriptor); + INetworkPtr network = CreateNetworkWithActivationLayer(descriptor); + + INetworkPtr quantizedNetworkQAsymm8 = INetworkQuantizer::Create(network.get())->ExportNetwork(); + TestActivationQuantization validatorQAsymm8; + VisitLayersTopologically(quantizedNetworkQAsymm8.get(), validatorQAsymm8); - auto quantizedNetwork = INetworkQuantizer::Create(network.get())->ExportNetwork(); - TestActivationQuantization validator; - VisitLayersTopologically(quantizedNetwork.get(), validator); + const QuantizerOptions options(DataType::QuantisedSymm16); + INetworkPtr quantizedNetworkQSymm16 = INetworkQuantizer::Create(network.get(), options)->ExportNetwork(); + TestActivationQuantization validatorQSymm16(options); + VisitLayersTopologically(quantizedNetworkQSymm16.get(), validatorQSymm16); } -class TestBoundedReluActivationQuantization : public TestQuantization +BOOST_AUTO_TEST_CASE(QuantizeBoundedReluActivation) { -public: - void VisitActivationLayer(const IConnectableLayer* layer, - const ActivationDescriptor& descriptor, - const char* name = nullptr) override + class TestBoundedReluActivationQuantization : public TestQuantization { - TensorInfo info = layer->GetOutputSlot(0).GetTensorInfo(); + public: + TestBoundedReluActivationQuantization() + : TestQuantization() {} - BOOST_TEST((info.GetDataType() == DataType::QuantisedAsymm8)); + TestBoundedReluActivationQuantization(const QuantizerOptions& options) + : TestQuantization(options) {} - BOOST_TEST((info.GetQuantizationOffset() == 0)); + void VisitActivationLayer(const IConnectableLayer* layer, + const ActivationDescriptor& descriptor, + const char* name = nullptr) override + { + TensorInfo info = layer->GetOutputSlot(0).GetTensorInfo(); - // Based off current static value [0.0f, 3.5f(<-layer upper bound)] - BOOST_CHECK_CLOSE(info.GetQuantizationScale(), 3.5f / g_QuantizationBase, g_TestTolerance); - } -}; + // Based off default static range [0.0f, 3.5f] + TestQuantizationParams(info, {3.5f / g_Asymm8QuantizationBase, 0}, {3.5f / g_Symm16QuantizationBase, 0}); + } + }; -BOOST_AUTO_TEST_CASE(QuantizeBoundedReluActivation) -{ ActivationDescriptor descriptor; descriptor.m_Function = ActivationFunction::BoundedReLu; descriptor.m_A = 3.5f; descriptor.m_B = -10.0f; - auto network = CreateNetworkWithActivationLayer(descriptor); + INetworkPtr network = CreateNetworkWithActivationLayer(descriptor); + + INetworkPtr quantizedNetworkQAsymm8 = INetworkQuantizer::Create(network.get())->ExportNetwork(); + TestBoundedReluActivationQuantization validatorQAsymm8; + VisitLayersTopologically(quantizedNetworkQAsymm8.get(), validatorQAsymm8); - auto quantizedNetwork = INetworkQuantizer::Create(network.get())->ExportNetwork(); - TestBoundedReluActivationQuantization validator; - VisitLayersTopologically(quantizedNetwork.get(), validator); + const QuantizerOptions options(DataType::QuantisedSymm16); + INetworkPtr quantizedNetworkQSymm16 = INetworkQuantizer::Create(network.get(), options)->ExportNetwork(); + TestBoundedReluActivationQuantization validatorQSymm16(options); + VisitLayersTopologically(quantizedNetworkQSymm16.get(), validatorQSymm16); } -class TestTanHActivationQuantization : public TestQuantization +BOOST_AUTO_TEST_CASE(QuantizeTanHActivation) { -public: - void VisitActivationLayer(const IConnectableLayer* layer, - const ActivationDescriptor& descriptor, - const char* name = nullptr) override + class TestTanHActivationQuantization : public TestQuantization { - TensorInfo info = layer->GetOutputSlot(0).GetTensorInfo(); + public: + TestTanHActivationQuantization() + : TestQuantization() {} - BOOST_TEST((info.GetDataType() == DataType::QuantisedAsymm8)); + TestTanHActivationQuantization(const QuantizerOptions& options) + : TestQuantization(options) {} - BOOST_TEST((info.GetQuantizationOffset() == 128)); + void VisitActivationLayer(const IConnectableLayer* layer, + const ActivationDescriptor& descriptor, + const char* name = nullptr) override + { + TensorInfo info = layer->GetOutputSlot(0).GetTensorInfo(); - // Based off current static value [-1.0f, 1.0f] - BOOST_CHECK_CLOSE(info.GetQuantizationScale(), 2.0f / g_QuantizationBase, g_TestTolerance); - } -}; + // Based off default static range [-1.0f, 1.0f] + TestQuantizationParams( + info, {2.0f / g_Asymm8QuantizationBase, 128}, {1.0f / g_Symm16QuantizationBase, 0}); + } + }; -BOOST_AUTO_TEST_CASE(QuantizeTanHActivation) -{ ActivationDescriptor descriptor; descriptor.m_Function = ActivationFunction::TanH; descriptor.m_A = 3.5f; descriptor.m_B = -10.0f; - auto network = CreateNetworkWithActivationLayer(descriptor); + INetworkPtr network = CreateNetworkWithActivationLayer(descriptor); - auto quantizedNetwork = INetworkQuantizer::Create(network.get())->ExportNetwork(); - TestTanHActivationQuantization validator; - VisitLayersTopologically(quantizedNetwork.get(), validator); + INetworkPtr quantizedNetworkQAsymm8 = INetworkQuantizer::Create(network.get())->ExportNetwork(); + TestTanHActivationQuantization validatorQAsymm8; + VisitLayersTopologically(quantizedNetworkQAsymm8.get(), validatorQAsymm8); + + const QuantizerOptions options(DataType::QuantisedSymm16); + INetworkPtr quantizedNetworkQSymm16 = INetworkQuantizer::Create(network.get(), options)->ExportNetwork(); + TestTanHActivationQuantization validatorQSymm16(options); + VisitLayersTopologically(quantizedNetworkQSymm16.get(), validatorQSymm16); } class TestLeakyReLuActivationQuantization : public TestQuantization { public: + TestLeakyReLuActivationQuantization() + : TestQuantization() {} + + TestLeakyReLuActivationQuantization(const QuantizerOptions& options) + : TestQuantization(options) {} + void VisitActivationLayer(const IConnectableLayer* layer, const ActivationDescriptor& descriptor, const char* name = nullptr) override { TensorInfo info = layer->GetOutputSlot(0).GetTensorInfo(); - BOOST_TEST((info.GetDataType() == DataType::QuantisedAsymm8)); - - BOOST_TEST((info.GetQuantizationOffset() == 64)); - - // Based off current static value [-5.0f, 15.0f] - BOOST_CHECK_CLOSE(info.GetQuantizationScale(), 20.0f / g_QuantizationBase, g_TestTolerance); + // Based off default static range [-5.0f, 15.0f] + TestQuantizationParams(info, {20.0f / g_Asymm8QuantizationBase, 64}, {15.0f / g_Symm16QuantizationBase, 0}); } + protected: - // used by the descendant classes which test layers + // Used by the descendant classes which test layers // that are forwarding their parent layer settings void CheckForwardedQuantizationSettings(const IConnectableLayer* layer) { TensorInfo info = layer->GetOutputSlot(0).GetTensorInfo(); - - BOOST_TEST((info.GetDataType() == DataType::QuantisedAsymm8)); - - BOOST_TEST((info.GetQuantizationOffset() == 64)); - - // Based off parent LeakyReLu [-5.f, 15.f] - BOOST_CHECK_CLOSE(info.GetQuantizationScale(), 20.0f/g_QuantizationBase, g_TestTolerance); + TestQuantizationParams(info, {20.0f / g_Asymm8QuantizationBase, 64}, {15.0f / g_Symm16QuantizationBase, 0}); } }; @@ -306,52 +386,52 @@ BOOST_AUTO_TEST_CASE(QuantizeLeakyReLuActivation) descriptor.m_A = 3.5f; descriptor.m_B = -10.0f; - auto network = CreateNetworkWithActivationLayer(descriptor); + INetworkPtr network = CreateNetworkWithActivationLayer(descriptor); - auto quantizedNetwork = INetworkQuantizer::Create(network.get())->ExportNetwork(); - TestLeakyReLuActivationQuantization validator; - VisitLayersTopologically(quantizedNetwork.get(), validator); + INetworkPtr quantizedNetworkQAsymm8 = INetworkQuantizer::Create(network.get())->ExportNetwork(); + TestLeakyReLuActivationQuantization validatorQAsymm8; + VisitLayersTopologically(quantizedNetworkQAsymm8.get(), validatorQAsymm8); + + const QuantizerOptions options(DataType::QuantisedSymm16); + INetworkPtr quantizedNetworkQSymm16 = INetworkQuantizer::Create(network.get(), options)->ExportNetwork(); + TestLeakyReLuActivationQuantization validatorQSymm16(options); + VisitLayersTopologically(quantizedNetworkQSymm16.get(), validatorQSymm16); } -class TestBatchNormalizationQuantization : public TestQuantization +BOOST_AUTO_TEST_CASE(QuantizeBatchNorm) { -public: - void VisitBatchNormalizationLayer(const IConnectableLayer* layer, - const BatchNormalizationDescriptor& desc, - const ConstTensor& mean, - const ConstTensor& variance, - const ConstTensor& beta, - const ConstTensor& gamma, - const char* name = nullptr) override + class TestBatchNormalizationQuantization : public TestQuantization { - TensorInfo info = layer->GetOutputSlot(0).GetTensorInfo(); - - BOOST_TEST((info.GetDataType() == DataType::QuantisedAsymm8)); - - BOOST_TEST((info.GetQuantizationOffset() == 128)); - - // Based off current static value [-15.0f, 15.0f] - BOOST_CHECK_CLOSE(info.GetQuantizationScale(), 30.0f / g_QuantizationBase, g_TestTolerance); - - // Test constants - BOOST_TEST((mean.GetInfo().GetDataType() == DataType::QuantisedAsymm8)); - BOOST_TEST((variance.GetInfo().GetDataType() == DataType::QuantisedAsymm8)); - BOOST_TEST((beta.GetInfo().GetDataType() == DataType::QuantisedAsymm8)); - BOOST_TEST((gamma.GetInfo().GetDataType() == DataType::QuantisedAsymm8)); + public: + TestBatchNormalizationQuantization() + : TestQuantization() {} + + TestBatchNormalizationQuantization(const QuantizerOptions& options) + : TestQuantization(options) {} + + void VisitBatchNormalizationLayer(const IConnectableLayer* layer, + const BatchNormalizationDescriptor& desc, + const ConstTensor& mean, + const ConstTensor& variance, + const ConstTensor& beta, + const ConstTensor& gamma, + const char* name = nullptr) override + { + TensorInfo info = layer->GetOutputSlot(0).GetTensorInfo(); - float expectedQuantizationScale = 3.0f / g_QuantizationBase; - BOOST_CHECK_CLOSE(mean.GetInfo().GetQuantizationScale(), expectedQuantizationScale, g_TestTolerance); - BOOST_CHECK_CLOSE(variance.GetInfo().GetQuantizationScale(), expectedQuantizationScale, g_TestTolerance); - BOOST_CHECK_CLOSE(beta.GetInfo().GetQuantizationScale(), expectedQuantizationScale, g_TestTolerance); - BOOST_CHECK_CLOSE(gamma.GetInfo().GetQuantizationScale(), expectedQuantizationScale, g_TestTolerance); + // Based off default static range [-15.0f, 15.0f] + TestQuantizationParams( + info, {30.0f / g_Asymm8QuantizationBase, 128}, {15.0f / g_Symm16QuantizationBase, 0}); - BOOST_TEST((mean.GetInfo().GetQuantizationOffset() == 85)); - } -}; + // Test constants + TestConstantQuantizationParams(mean.GetInfo(), {3.0f / g_Asymm8QuantizationBase, 85}); + TestConstantQuantizationParams(variance.GetInfo(), {3.0f / g_Asymm8QuantizationBase, 85}); + TestConstantQuantizationParams(beta.GetInfo(), {3.0f / g_Asymm8QuantizationBase, 85}); + TestConstantQuantizationParams(gamma.GetInfo(), {3.0f / g_Asymm8QuantizationBase, 85}); + } + }; -BOOST_AUTO_TEST_CASE(QuantizeBatchNorm) -{ - auto network = INetwork::Create(); + INetworkPtr network = INetwork::Create(); TensorShape shape{3U}; TensorInfo info(shape, DataType::Float32); @@ -381,9 +461,14 @@ BOOST_AUTO_TEST_CASE(QuantizeBatchNorm) input0->GetOutputSlot(0).SetTensorInfo(info); batchNorm->GetOutputSlot(0).SetTensorInfo(info); - auto quantizedNetwork = INetworkQuantizer::Create(network.get())->ExportNetwork(); - TestBatchNormalizationQuantization validator; - VisitLayersTopologically(quantizedNetwork.get(), validator); + INetworkPtr quantizedNetworkQAsymm8 = INetworkQuantizer::Create(network.get())->ExportNetwork(); + TestBatchNormalizationQuantization validatorQAsymm8; + VisitLayersTopologically(quantizedNetworkQAsymm8.get(), validatorQAsymm8); + + const QuantizerOptions options(DataType::QuantisedSymm16); + INetworkPtr quantizedNetworkQSymm16 = INetworkQuantizer::Create(network.get(), options)->ExportNetwork(); + TestBatchNormalizationQuantization validatorQSymm16(options); + VisitLayersTopologically(quantizedNetworkQSymm16.get(), validatorQSymm16); } BOOST_AUTO_TEST_CASE(OverrideInputRangeEmptyNetwork) @@ -470,7 +555,7 @@ INetworkPtr CreateNetworkWithFullyConnectedLayer(const bool biasEnabled) { FullyConnectedDescriptor desc; desc.m_BiasEnabled = biasEnabled; - auto network = INetwork::Create(); + INetworkPtr network = INetwork::Create(); TensorShape shape{3U}; TensorInfo info(shape, DataType::Float32); @@ -504,46 +589,48 @@ INetworkPtr CreateNetworkWithFullyConnectedLayer(const bool biasEnabled) return network; } -class TestFullyConnectedQuantization : public TestQuantization +void ValidateFullyConnectedLayer(const bool biasEnabled) { -public: - void VisitFullyConnectedLayer(const IConnectableLayer* layer, - const FullyConnectedDescriptor& desc, - const ConstTensor& weights, - const Optional& biases, - const char* name = nullptr) override + class TestFullyConnectedQuantization : public TestQuantization { - TensorInfo info = layer->GetOutputSlot(0).GetTensorInfo(); + public: + TestFullyConnectedQuantization() + : TestQuantization() {} - BOOST_TEST((info.GetDataType() == DataType::QuantisedAsymm8)); + TestFullyConnectedQuantization(const QuantizerOptions& options) + : TestQuantization(options) {} - BOOST_TEST((info.GetQuantizationOffset() == 128)); + void VisitFullyConnectedLayer(const IConnectableLayer* layer, + const FullyConnectedDescriptor& desc, + const ConstTensor& weights, + const Optional& biases, + const char* name = nullptr) override + { + TensorInfo info = layer->GetOutputSlot(0).GetTensorInfo(); - // Based off current static value [-15.0f, 15.0f] - BOOST_CHECK_CLOSE(info.GetQuantizationScale(), 30.0f / g_QuantizationBase, g_TestTolerance ); + // Based off default static range [-15.0f, 15.0f] + TestQuantizationParams( + info, {30.0f / g_Asymm8QuantizationBase, 128}, {15.0f / g_Symm16QuantizationBase, 0}); - // Test weights - BOOST_TEST((weights.GetInfo().GetDataType() == DataType::QuantisedAsymm8)); - BOOST_CHECK_CLOSE(weights.GetInfo().GetQuantizationScale(), 3.0f / g_QuantizationBase, g_TestTolerance); - BOOST_TEST((weights.GetInfo().GetQuantizationOffset() == 85)); + TestConstantQuantizationParams(weights.GetInfo(), {3.0f / g_Asymm8QuantizationBase, 85}); - // Test biases - if (biases.has_value()) - { - BOOST_TEST((biases.value().GetInfo().GetDataType() == DataType::QuantisedAsymm8)); - BOOST_CHECK_CLOSE(biases.value().GetInfo().GetQuantizationScale(), - 30.0f / g_QuantizationBase, - g_TestTolerance); + if (biases.has_value()) + { + TestConstantQuantizationParams(biases.value().GetInfo(), {30.0f / g_Asymm8QuantizationBase, 0}); + } } - } -}; + }; -void ValidateFullyConnectedLayer(const bool biasEnabled) -{ - auto network = CreateNetworkWithFullyConnectedLayer(biasEnabled); - auto quantizedNetwork = INetworkQuantizer::Create(network.get())->ExportNetwork(); - TestFullyConnectedQuantization validator; - VisitLayersTopologically(quantizedNetwork.get(), validator); + INetworkPtr network = CreateNetworkWithFullyConnectedLayer(biasEnabled); + + INetworkPtr quantizedNetworkQAsymm8 = INetworkQuantizer::Create(network.get())->ExportNetwork(); + TestFullyConnectedQuantization validatorQAsymm8; + VisitLayersTopologically(quantizedNetworkQAsymm8.get(), validatorQAsymm8); + + const QuantizerOptions options(DataType::QuantisedSymm16); + INetworkPtr quantizedNetworkQSymm16 = INetworkQuantizer::Create(network.get(), options)->ExportNetwork(); + TestFullyConnectedQuantization validatorQSymm16(options); + VisitLayersTopologically(quantizedNetworkQSymm16.get(), validatorQSymm16); } BOOST_AUTO_TEST_CASE(QuantizeFullyConnected) @@ -556,44 +643,39 @@ BOOST_AUTO_TEST_CASE(QuantizeFullyConnectedBiasEnabled) ValidateFullyConnectedLayer(true); } -class TestConv2dQuantization : public TestQuantization +void TestQuantizeConvolution2d(bool useBiases) { -public: - void VisitConvolution2dLayer(const IConnectableLayer *layer, - const Convolution2dDescriptor& convolution2dDescriptor, - const ConstTensor& weights, - const Optional& biases, - const char *name = nullptr) override + class TestConv2dQuantization : public TestQuantization { - TensorInfo info = layer->GetOutputSlot(0).GetTensorInfo(); - BOOST_TEST((info.GetDataType() == DataType::QuantisedAsymm8)); - BOOST_TEST((info.GetQuantizationOffset() == 128)); - - // Based off current static value [-15.0f, 15.0f] - BOOST_CHECK_CLOSE(info.GetQuantizationScale(), 30.0f / g_QuantizationBase, g_TestTolerance); - - // Test weights - // Instantiate expected values - const float quantizationScale = 3.0f / g_QuantizationBase; - const float tolerance = 3.0f / g_QuantizationBase; - const int quantizationOffset = 85; - BOOST_TEST((weights.GetInfo().GetDataType() == DataType::QuantisedAsymm8)); - BOOST_CHECK_CLOSE(weights.GetInfo().GetQuantizationScale(), quantizationScale, tolerance); - BOOST_TEST((weights.GetInfo().GetQuantizationOffset() == quantizationOffset)); - - // Test biases - if (biases.has_value()) + public: + TestConv2dQuantization() + : TestQuantization() {} + + TestConv2dQuantization(const QuantizerOptions& options) + : TestQuantization(options) {} + + void VisitConvolution2dLayer(const IConnectableLayer *layer, + const Convolution2dDescriptor& convolution2dDescriptor, + const ConstTensor& weights, + const Optional& biases, + const char *name = nullptr) override { - BOOST_TEST((biases.value().GetInfo().GetDataType() == DataType::QuantisedAsymm8)); - BOOST_CHECK_CLOSE(biases.value().GetInfo().GetQuantizationScale(), quantizationScale, tolerance); - BOOST_TEST((biases.value().GetInfo().GetQuantizationOffset() == quantizationOffset)); + TensorInfo info = layer->GetOutputSlot(0).GetTensorInfo(); + + // Based off default static range [-15.0f, 15.0f] + TestQuantizationParams( + info, {30.0f / g_Asymm8QuantizationBase, 128}, {15.0f / g_Symm16QuantizationBase, 0}); + + TestConstantQuantizationParams(weights.GetInfo(), {3.0f / g_Asymm8QuantizationBase, 85}); + + if (biases.has_value()) + { + TestConstantQuantizationParams(biases.value().GetInfo(), {3.0f / g_Asymm8QuantizationBase, 85}); + } } - } -}; + }; -void TestQuantizeConvolution2d(bool useBiases) -{ - auto network = INetwork::Create(); + INetworkPtr network = INetwork::Create(); TensorShape shape{3U}; TensorInfo info(shape, DataType::Float32); @@ -627,9 +709,14 @@ void TestQuantizeConvolution2d(bool useBiases) input0->GetOutputSlot(0).SetTensorInfo(info); conv2d->GetOutputSlot(0).SetTensorInfo(info); - auto quantizedNetwork = INetworkQuantizer::Create(network.get())->ExportNetwork(); - TestConv2dQuantization validator; - VisitLayersTopologically(quantizedNetwork.get(), validator); + INetworkPtr quantizedNetworkQAsymm8 = INetworkQuantizer::Create(network.get())->ExportNetwork(); + TestConv2dQuantization validatorQAsymm8; + VisitLayersTopologically(quantizedNetworkQAsymm8.get(), validatorQAsymm8); + + const QuantizerOptions options(DataType::QuantisedSymm16); + INetworkPtr quantizedNetworkQSymm16 = INetworkQuantizer::Create(network.get(), options)->ExportNetwork(); + TestConv2dQuantization validatorQSymm16(options); + VisitLayersTopologically(quantizedNetworkQSymm16.get(), validatorQSymm16); } BOOST_AUTO_TEST_CASE(QuantizeConvolution2d) @@ -642,44 +729,39 @@ BOOST_AUTO_TEST_CASE(QuantizeConvolution2dWithBiases) TestQuantizeConvolution2d(true); } -class TestDepthwiseConv2dQuantization : public TestQuantization +void TestQuantizeDepthwiseConvolution2d(bool useBiases) { -public: - void VisitDepthwiseConvolution2dLayer(const IConnectableLayer *layer, - const DepthwiseConvolution2dDescriptor& desc, - const ConstTensor& weights, - const Optional& biases, - const char *name = nullptr) override + class TestDepthwiseConv2dQuantization : public TestQuantization { - TensorInfo info = layer->GetOutputSlot(0).GetTensorInfo(); - BOOST_TEST((info.GetDataType() == DataType::QuantisedAsymm8)); - BOOST_TEST((info.GetQuantizationOffset() == 128)); - - // Based off current static value [-15.0f, 15.0f] - BOOST_CHECK_CLOSE(info.GetQuantizationScale(), 30.0f / g_QuantizationBase, g_TestTolerance); - - // Test weights - // Instantiate expected values - const float quantizationScale = 3.0f / g_QuantizationBase; - const float tolerance = 3.0f / g_QuantizationBase; - const int quantizationOffset = 85; - BOOST_TEST((weights.GetInfo().GetDataType() == DataType::QuantisedAsymm8)); - BOOST_CHECK_CLOSE(weights.GetInfo().GetQuantizationScale(), quantizationScale, tolerance); - BOOST_TEST((weights.GetInfo().GetQuantizationOffset() == quantizationOffset)); - - // Test biases - if (biases.has_value()) + public: + TestDepthwiseConv2dQuantization() + : TestQuantization() {} + + TestDepthwiseConv2dQuantization(const QuantizerOptions& options) + : TestQuantization(options) {} + + void VisitDepthwiseConvolution2dLayer(const IConnectableLayer *layer, + const DepthwiseConvolution2dDescriptor& convolution2dDescriptor, + const ConstTensor& weights, + const Optional& biases, + const char *name = nullptr) override { - BOOST_TEST((biases.value().GetInfo().GetDataType() == DataType::QuantisedAsymm8)); - BOOST_CHECK_CLOSE(biases.value().GetInfo().GetQuantizationScale(), quantizationScale, tolerance); - BOOST_TEST((biases.value().GetInfo().GetQuantizationOffset() == quantizationOffset)); + TensorInfo info = layer->GetOutputSlot(0).GetTensorInfo(); + + // Based off default static range [-15.0f, 15.0f] + TestQuantizationParams( + info, {30.0f / g_Asymm8QuantizationBase, 128}, {15.0f / g_Symm16QuantizationBase, 0}); + + TestConstantQuantizationParams(weights.GetInfo(), {3.0f / g_Asymm8QuantizationBase, 85}); + + if (biases.has_value()) + { + TestConstantQuantizationParams(biases.value().GetInfo(), {3.0f / g_Asymm8QuantizationBase, 85}); + } } - } -}; + }; -void TestQuantizeDepthwiseConvolution2d(bool useBiases) -{ - auto network = INetwork::Create(); + INetworkPtr network = INetwork::Create(); TensorShape shape{3U}; TensorInfo info(shape, DataType::Float32); @@ -713,9 +795,14 @@ void TestQuantizeDepthwiseConvolution2d(bool useBiases) input0->GetOutputSlot(0).SetTensorInfo(info); depthwiseConv2d->GetOutputSlot(0).SetTensorInfo(info); - auto quantizedNetwork = INetworkQuantizer::Create(network.get())->ExportNetwork(); - TestDepthwiseConv2dQuantization validator; - VisitLayersTopologically(quantizedNetwork.get(), validator); + INetworkPtr quantizedNetworkQAsymm8 = INetworkQuantizer::Create(network.get())->ExportNetwork(); + TestDepthwiseConv2dQuantization validatorQAsymm8; + VisitLayersTopologically(quantizedNetworkQAsymm8.get(), validatorQAsymm8); + + const QuantizerOptions options(DataType::QuantisedSymm16); + INetworkPtr quantizedNetworkQSymm16 = INetworkQuantizer::Create(network.get(), options)->ExportNetwork(); + TestDepthwiseConv2dQuantization validatorQSymm16(options); + VisitLayersTopologically(quantizedNetworkQSymm16.get(), validatorQSymm16); } BOOST_AUTO_TEST_CASE(QuantizeDepthwiseConvolution2d) @@ -728,26 +815,9 @@ BOOST_AUTO_TEST_CASE(QuantizeDepthwiseConvolution2dWithBiases) TestQuantizeDepthwiseConvolution2d(true); } -class TestSoftmaxQuantization : public TestQuantization -{ -public: - void VisitSoftmaxLayer(const IConnectableLayer* layer, - const SoftmaxDescriptor& descriptor, - const char* name = nullptr) override - { - TensorInfo info = layer->GetOutputSlot(0).GetTensorInfo(); - - BOOST_TEST((info.GetDataType() == DataType::QuantisedAsymm8)); - - BOOST_TEST((info.GetQuantizationOffset() == 0)); - - BOOST_CHECK_CLOSE(info.GetQuantizationScale(), 1.0f / g_QuantizationBase, g_TestTolerance ); - } -}; - INetworkPtr CreateNetworkWithSoftmaxLayer(const SoftmaxDescriptor& descriptor) { - auto network = INetwork::Create(); + INetworkPtr network = INetwork::Create(); // Add the layers IConnectableLayer* input0 = network->AddInputLayer(0); @@ -769,14 +839,39 @@ INetworkPtr CreateNetworkWithSoftmaxLayer(const SoftmaxDescriptor& descriptor) BOOST_AUTO_TEST_CASE(QuantizeSoftmax) { + class TestSoftmaxQuantization : public TestQuantization + { + public: + TestSoftmaxQuantization() + : TestQuantization() {} + + TestSoftmaxQuantization(const QuantizerOptions& options) + : TestQuantization(options) {} + + void VisitSoftmaxLayer(const IConnectableLayer* layer, + const SoftmaxDescriptor& descriptor, + const char* name = nullptr) override + { + TensorInfo info = layer->GetOutputSlot(0).GetTensorInfo(); + + // Based off default static range [0.0f, 1.0f] + TestQuantizationParams(info, {1.0f / g_Asymm8QuantizationBase, 0}, {1.0f / g_Symm16QuantizationBase, 0}); + } + }; + SoftmaxDescriptor descriptor; descriptor.m_Beta = 1.0f; - auto network = CreateNetworkWithSoftmaxLayer(descriptor); + INetworkPtr network = CreateNetworkWithSoftmaxLayer(descriptor); + + INetworkPtr quantizedNetworkQAsymm8 = INetworkQuantizer::Create(network.get())->ExportNetwork(); + TestSoftmaxQuantization validatorQAsymm8; + VisitLayersTopologically(quantizedNetworkQAsymm8.get(), validatorQAsymm8); - auto quantizedNetwork = INetworkQuantizer::Create(network.get())->ExportNetwork(); - TestSoftmaxQuantization validator; - VisitLayersTopologically(quantizedNetwork.get(), validator); + const QuantizerOptions options(DataType::QuantisedSymm16); + INetworkPtr quantizedNetworkQSymm16 = INetworkQuantizer::Create(network.get(), options)->ExportNetwork(); + TestSoftmaxQuantization validatorQSymm16(options); + VisitLayersTopologically(quantizedNetworkQSymm16.get(), validatorQSymm16); } IConnectableLayer* CreateStartOfLeakyReluNetwork(INetwork* network, const TensorInfo& info) @@ -821,6 +916,12 @@ BOOST_AUTO_TEST_CASE(QuantizePermute) class TestPermuteQuantization : public TestLeakyReLuActivationQuantization { public: + TestPermuteQuantization() + : TestLeakyReLuActivationQuantization() {} + + TestPermuteQuantization(const QuantizerOptions& options) + : TestLeakyReLuActivationQuantization(options) {} + void VisitPermuteLayer(const IConnectableLayer* layer, const PermuteDescriptor& desc, const char* name = nullptr) override @@ -842,9 +943,14 @@ BOOST_AUTO_TEST_CASE(QuantizePermute) CompleteLeakyReluNetwork(network.get(), activation, permute, info); - auto quantizedNetwork = INetworkQuantizer::Create(network.get())->ExportNetwork(); - TestPermuteQuantization validator; - VisitLayersTopologically(quantizedNetwork.get(), validator); + INetworkPtr quantizedNetworkQAsymm8 = INetworkQuantizer::Create(network.get())->ExportNetwork(); + TestPermuteQuantization validatorQAsymm8; + VisitLayersTopologically(quantizedNetworkQAsymm8.get(), validatorQAsymm8); + + const QuantizerOptions options(DataType::QuantisedSymm16); + INetworkPtr quantizedNetworkQSymm16 = INetworkQuantizer::Create(network.get(), options)->ExportNetwork(); + TestPermuteQuantization validatorQSymm16(options); + VisitLayersTopologically(quantizedNetworkQSymm16.get(), validatorQSymm16); } BOOST_AUTO_TEST_CASE(QuantizeSpaceToBatch) @@ -852,6 +958,12 @@ BOOST_AUTO_TEST_CASE(QuantizeSpaceToBatch) class TestSpaceToBatchQuantization : public TestLeakyReLuActivationQuantization { public: + TestSpaceToBatchQuantization() + : TestLeakyReLuActivationQuantization() {} + + TestSpaceToBatchQuantization(const QuantizerOptions& options) + : TestLeakyReLuActivationQuantization(options) {} + void VisitSpaceToBatchNdLayer(const IConnectableLayer* layer, const SpaceToBatchNdDescriptor& spaceToBatchNdDescriptor, const char* name = nullptr) override @@ -873,31 +985,35 @@ BOOST_AUTO_TEST_CASE(QuantizeSpaceToBatch) CompleteLeakyReluNetwork(network.get(), activation, spaceToBatch, info); - auto quantizedNetwork = INetworkQuantizer::Create(network.get())->ExportNetwork(); - TestSpaceToBatchQuantization validator; - VisitLayersTopologically(quantizedNetwork.get(), validator); + INetworkPtr quantizedNetworkQAsymm8 = INetworkQuantizer::Create(network.get())->ExportNetwork(); + TestSpaceToBatchQuantization validatorQAsymm8; + VisitLayersTopologically(quantizedNetworkQAsymm8.get(), validatorQAsymm8); + + const QuantizerOptions options(DataType::QuantisedSymm16); + INetworkPtr quantizedNetworkQSymm16 = INetworkQuantizer::Create(network.get(), options)->ExportNetwork(); + TestSpaceToBatchQuantization validatorQSymm16(options); + VisitLayersTopologically(quantizedNetworkQSymm16.get(), validatorQSymm16); } -class TestPooling2dQuantization : public TestLeakyReLuActivationQuantization +BOOST_AUTO_TEST_CASE(QuantizePooling2d) { -public: - void VisitPooling2dLayer(const IConnectableLayer* layer, - const Pooling2dDescriptor& desc, - const char* name = nullptr) override + class TestPooling2dQuantization : public TestLeakyReLuActivationQuantization { - TensorInfo info = layer->GetOutputSlot(0).GetTensorInfo(); - - BOOST_TEST((info.GetDataType() == DataType::QuantisedAsymm8)); + public: + TestPooling2dQuantization() + : TestLeakyReLuActivationQuantization() {} - BOOST_TEST((info.GetQuantizationOffset() == 64)); + TestPooling2dQuantization(const QuantizerOptions& options) + : TestLeakyReLuActivationQuantization(options) {} - // Based off parent LeakyReLu [-5.f, 15.f] - BOOST_CHECK_CLOSE(info.GetQuantizationScale(), 20.0f / g_QuantizationBase, g_TestTolerance); - } -}; + void VisitPooling2dLayer(const IConnectableLayer* layer, + const Pooling2dDescriptor& desc, + const char* name = nullptr) override + { + CheckForwardedQuantizationSettings(layer); + } + }; -BOOST_AUTO_TEST_CASE(QuantizePooling2d) -{ auto network = INetwork::Create(); TensorShape shape{1U}; @@ -925,35 +1041,41 @@ BOOST_AUTO_TEST_CASE(QuantizePooling2d) activation->GetOutputSlot(0).SetTensorInfo(info); pooling2d->GetOutputSlot(0).SetTensorInfo(info); - auto quantizedNetwork = INetworkQuantizer::Create(network.get())->ExportNetwork(); - TestPooling2dQuantization validator; - VisitLayersTopologically(quantizedNetwork.get(), validator); + INetworkPtr quantizedNetworkQAsymm8 = INetworkQuantizer::Create(network.get())->ExportNetwork(); + TestPooling2dQuantization validatorQAsymm8; + VisitLayersTopologically(quantizedNetworkQAsymm8.get(), validatorQAsymm8); + + const QuantizerOptions options(DataType::QuantisedSymm16); + INetworkPtr quantizedNetworkQSymm16 = INetworkQuantizer::Create(network.get(), options)->ExportNetwork(); + TestPooling2dQuantization validatorQSymm16(options); + VisitLayersTopologically(quantizedNetworkQSymm16.get(), validatorQSymm16); } -class TestConstantQuantization : public TestAdditionQuantization +BOOST_AUTO_TEST_CASE(QuantizeConstant) { -public: - void VisitConstantLayer(const IConnectableLayer* layer, - const ConstTensor& input, - const char* name = nullptr) override + class TestConstantQuantization : public TestAdditionQuantization { - BOOST_CHECK(std::string(name) == "ConstantLayer"); + public: + TestConstantQuantization() + : TestAdditionQuantization() {} - TensorInfo info = layer->GetOutputSlot(0).GetTensorInfo(); - BOOST_CHECK(info.GetDataType() == DataType::QuantisedAsymm8); - BOOST_CHECK(info.GetQuantizationOffset() == 64); + TestConstantQuantization(const QuantizerOptions& options) + : TestAdditionQuantization(options) {} - // Based off the range of values in the const tensor used for the test: [-2.0f, 6.0f] - BOOST_CHECK_CLOSE(info.GetQuantizationScale(), 8.0f / g_QuantizationBase, g_TestTolerance); - } -}; + void VisitConstantLayer(const IConnectableLayer* layer, + const ConstTensor& input, + const char* name = nullptr) override + { + TensorInfo info = layer->GetOutputSlot(0).GetTensorInfo(); -BOOST_AUTO_TEST_CASE(QuantizeConstant) -{ - auto network = INetwork::Create(); + // Based off the range of values in the const tensor used for the test: [-2.0f, 6.0f] + TestQuantizationParams(info, {8.0f / g_Asymm8QuantizationBase, 64}, {6.0f / g_Symm16QuantizationBase, 0}); + } + }; + + INetworkPtr network = INetwork::Create(); // Constant layer data - const char* name = "ConstantLayer"; std::vector data = {-2.0f, -1.0f, 0.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f}; std::vector dimensions = {1, 1, 3, 3}; TensorInfo tensorInfo(4, dimensions.data(), DataType::Float32); @@ -961,7 +1083,7 @@ BOOST_AUTO_TEST_CASE(QuantizeConstant) // Add the layers IConnectableLayer* input = network->AddInputLayer(0); - IConnectableLayer* constant = network->AddConstantLayer(constantTensor, name); + IConnectableLayer* constant = network->AddConstantLayer(constantTensor); IConnectableLayer* addition = network->AddAdditionLayer(); IConnectableLayer* output = network->AddOutputLayer(1); @@ -974,46 +1096,44 @@ BOOST_AUTO_TEST_CASE(QuantizeConstant) input->GetOutputSlot(0).SetTensorInfo(tensorInfo); addition->GetOutputSlot(0).SetTensorInfo(tensorInfo); - auto quantizedNetwork = INetworkQuantizer::Create(network.get())->ExportNetwork(); - TestConstantQuantization validator; - VisitLayersTopologically(quantizedNetwork.get(), validator); + INetworkPtr quantizedNetworkQAsymm8 = INetworkQuantizer::Create(network.get())->ExportNetwork(); + TestConstantQuantization validatorQAsymm8; + VisitLayersTopologically(quantizedNetworkQAsymm8.get(), validatorQAsymm8); + + const QuantizerOptions options(DataType::QuantisedSymm16); + INetworkPtr quantizedNetworkQSymm16 = INetworkQuantizer::Create(network.get(), options)->ExportNetwork(); + TestConstantQuantization validatorQSymm16(options); + VisitLayersTopologically(quantizedNetworkQSymm16.get(), validatorQSymm16); } BOOST_AUTO_TEST_CASE(QuantizeMerger) { - class TestMergerVisitor : public LayerVisitorBase + class TestMergerQuantization : public TestQuantization { public: - TestMergerVisitor(float min, float max) : m_Min(min), m_Max(max) {} + TestMergerQuantization() + : TestQuantization() {} + + TestMergerQuantization(const QuantizerOptions& options) + : TestQuantization(options) {} - virtual void VisitInputLayer(const IConnectableLayer* layer, - LayerBindingId id, - const char* name = nullptr) + void VisitInputLayer(const IConnectableLayer* layer, + LayerBindingId id, + const char* name = nullptr) override {} - virtual void VisitOutputLayer(const IConnectableLayer* layer, - LayerBindingId id, - const char* name = nullptr) + void VisitOutputLayer(const IConnectableLayer* layer, + LayerBindingId id, + const char* name = nullptr) override {} - virtual void VisitMergerLayer(const IConnectableLayer* layer, - const OriginsDescriptor& mergerDescriptor, - const char* name = nullptr) + void VisitMergerLayer(const IConnectableLayer* layer, + const OriginsDescriptor& mergerDescriptor, + const char* name = nullptr) override { - - QAsymm8QuantizationScheme quantizationScheme; - OffsetScalePair expectedValues = quantizationScheme.ComputeScheme(m_Min, m_Max); - TensorInfo info = layer->GetOutputSlot(0).GetTensorInfo(); - BOOST_TEST((info.GetDataType() == DataType::QuantisedAsymm8)); - - BOOST_TEST((info.GetQuantizationOffset() == expectedValues.second)); - - BOOST_CHECK_CLOSE(info.GetQuantizationScale(), expectedValues.first, 0.000001f); + TestQuantizationParams( + info, {60.8f / g_Asymm8QuantizationBase, 65}, {45.3f / g_Symm16QuantizationBase, 0}); } - - private: - float m_Min; - float m_Max; }; INetworkPtr network = INetwork::Create(); @@ -1042,18 +1162,28 @@ BOOST_AUTO_TEST_CASE(QuantizeMerger) input2->GetOutputSlot(0).SetTensorInfo(info); merger->GetOutputSlot(0).SetTensorInfo(info); - INetworkQuantizerPtr quantizerPtr = INetworkQuantizer::Create(network.get()); + const QuantizerOptions options(DataType::QuantisedSymm16); + INetworkQuantizerPtr quantizerPtrQAsymm8 = INetworkQuantizer::Create(network.get()); + INetworkQuantizerPtr quantizerPtrQSymm16 = INetworkQuantizer::Create(network.get(), options); // Override the input ranges float min = -15.5f; float max = 45.3f; - quantizerPtr->OverrideInputRange(0, (min + 2.1f), (max - 3.2f)); - quantizerPtr->OverrideInputRange(1, (min + 6.7f), max); - quantizerPtr->OverrideInputRange(2, min, (max - 7.8f)); + quantizerPtrQAsymm8->OverrideInputRange(0, (min + 2.1f), (max - 3.2f)); + quantizerPtrQAsymm8->OverrideInputRange(1, (min + 6.7f), max); + quantizerPtrQAsymm8->OverrideInputRange(2, min, (max - 7.8f)); - auto quantizedNetwork = quantizerPtr->ExportNetwork(); - TestMergerVisitor validator(min, max); - VisitLayersTopologically(quantizedNetwork.get(), validator); + quantizerPtrQSymm16->OverrideInputRange(0, (min + 2.1f), (max - 3.2f)); + quantizerPtrQSymm16->OverrideInputRange(1, (min + 6.7f), max); + quantizerPtrQSymm16->OverrideInputRange(2, min, (max - 7.8f)); + + INetworkPtr quantizedNetworkQAsymm8 = quantizerPtrQAsymm8->ExportNetwork(); + TestMergerQuantization validatorQAsymm8; + VisitLayersTopologically(quantizedNetworkQAsymm8.get(), validatorQAsymm8); + + INetworkPtr quantizedNetworkQSymm16 = quantizerPtrQSymm16->ExportNetwork(); + TestMergerQuantization validatorQSymm16(options); + VisitLayersTopologically(quantizedNetworkQSymm16.get(), validatorQSymm16); } BOOST_AUTO_TEST_CASE(QuantizeReshape) @@ -1061,6 +1191,12 @@ BOOST_AUTO_TEST_CASE(QuantizeReshape) class TestReshapeQuantization : public TestLeakyReLuActivationQuantization { public: + TestReshapeQuantization() + : TestLeakyReLuActivationQuantization() {} + + TestReshapeQuantization(const QuantizerOptions& options) + : TestLeakyReLuActivationQuantization(options) {} + virtual void VisitReshapeLayer(const IConnectableLayer* layer, const ReshapeDescriptor& reshapeDescriptor, const char* name = nullptr) override @@ -1082,32 +1218,36 @@ BOOST_AUTO_TEST_CASE(QuantizeReshape) CompleteLeakyReluNetwork(network.get(), activation, reshape, info); - auto quantizedNetwork = INetworkQuantizer::Create(network.get())->ExportNetwork(); - TestReshapeQuantization validator; - VisitLayersTopologically(quantizedNetwork.get(), validator); + INetworkPtr quantizedNetworkQAsymm8 = INetworkQuantizer::Create(network.get())->ExportNetwork(); + TestReshapeQuantization validatorQAsymm8; + VisitLayersTopologically(quantizedNetworkQAsymm8.get(), validatorQAsymm8); + + const QuantizerOptions options(DataType::QuantisedSymm16); + INetworkPtr quantizedNetworkQSymm16 = INetworkQuantizer::Create(network.get(), options)->ExportNetwork(); + TestReshapeQuantization validatorQSymm16(options); + VisitLayersTopologically(quantizedNetworkQSymm16.get(), validatorQSymm16); } -class TestSplitterQuantization : public TestLeakyReLuActivationQuantization +BOOST_AUTO_TEST_CASE(QuantizeSplitter) { -public: - virtual void VisitSplitterLayer(const IConnectableLayer* layer, - const SplitterDescriptor& desc, - const char* name = nullptr) + class TestSplitterQuantization : public TestLeakyReLuActivationQuantization { - TensorInfo info = layer->GetOutputSlot(0).GetTensorInfo(); - - BOOST_TEST((info.GetDataType() == DataType::QuantisedAsymm8)); + public: + TestSplitterQuantization() + : TestLeakyReLuActivationQuantization() {} - BOOST_TEST((info.GetQuantizationOffset() == 64)); + TestSplitterQuantization(const QuantizerOptions& options) + : TestLeakyReLuActivationQuantization(options) {} - // Based off parent LeakyReLu [-5.f, 15.f] - BOOST_CHECK_CLOSE(info.GetQuantizationScale(), 20.0f/g_QuantizationBase, g_TestTolerance); - } -}; + virtual void VisitSplitterLayer(const IConnectableLayer* layer, + const SplitterDescriptor& desc, + const char* name = nullptr) + { + CheckForwardedQuantizationSettings(layer); + } + }; -BOOST_AUTO_TEST_CASE(QuantizeSplitter) -{ - auto network = INetwork::Create(); + INetworkPtr network = INetwork::Create(); TensorShape shape{3U}; TensorInfo info(shape, DataType::Float32); @@ -1119,9 +1259,14 @@ BOOST_AUTO_TEST_CASE(QuantizeSplitter) IConnectableLayer* splitter = network->AddSplitterLayer(splitterDesc); CompleteLeakyReluNetwork(network.get(), activation, splitter, info); - auto quantizedNetwork = INetworkQuantizer::Create(network.get())->ExportNetwork(); - TestSplitterQuantization validator; - VisitLayersTopologically(quantizedNetwork.get(), validator); + INetworkPtr quantizedNetworkQAsymm8 = INetworkQuantizer::Create(network.get())->ExportNetwork(); + TestSplitterQuantization validatorQAsymm8; + VisitLayersTopologically(quantizedNetworkQAsymm8.get(), validatorQAsymm8); + + const QuantizerOptions options(DataType::QuantisedSymm16); + INetworkPtr quantizedNetworkQSymm16 = INetworkQuantizer::Create(network.get(), options)->ExportNetwork(); + TestSplitterQuantization validatorQSymm16(options); + VisitLayersTopologically(quantizedNetworkQSymm16.get(), validatorQSymm16); } BOOST_AUTO_TEST_CASE(QuantizeResizeBilinear) @@ -1129,6 +1274,12 @@ BOOST_AUTO_TEST_CASE(QuantizeResizeBilinear) class TestResizeBilinearQuantization : public TestLeakyReLuActivationQuantization { public: + TestResizeBilinearQuantization() + : TestLeakyReLuActivationQuantization() {} + + TestResizeBilinearQuantization(const QuantizerOptions& options) + : TestLeakyReLuActivationQuantization(options) {} + void VisitResizeBilinearLayer(const IConnectableLayer* layer, const ResizeBilinearDescriptor& resizeDescriptor, const char* name = nullptr) override @@ -1152,25 +1303,36 @@ BOOST_AUTO_TEST_CASE(QuantizeResizeBilinear) CompleteLeakyReluNetwork(network.get(), activation, spaceToBatch, info); - auto quantizedNetwork = INetworkQuantizer::Create(network.get())->ExportNetwork(); - TestResizeBilinearQuantization validator; - VisitLayersTopologically(quantizedNetwork.get(), validator); + INetworkPtr quantizedNetworkQAsymm8 = INetworkQuantizer::Create(network.get())->ExportNetwork(); + TestResizeBilinearQuantization validatorQAsymm8; + VisitLayersTopologically(quantizedNetworkQAsymm8.get(), validatorQAsymm8); + + const QuantizerOptions options(DataType::QuantisedSymm16); + INetworkPtr quantizedNetworkQSymm16 = INetworkQuantizer::Create(network.get(), options)->ExportNetwork(); + TestResizeBilinearQuantization validatorQSymm16(options); + VisitLayersTopologically(quantizedNetworkQSymm16.get(), validatorQSymm16); } -class TestStridedSliceQuantization : public TestLeakyReLuActivationQuantization +BOOST_AUTO_TEST_CASE(QuantizeStridedSlice) { -public: - virtual void VisitStridedSliceLayer(const IConnectableLayer* layer, - const StridedSliceDescriptor& desc, - const char* name = nullptr) + class TestStridedSliceQuantization : public TestLeakyReLuActivationQuantization { - CheckForwardedQuantizationSettings(layer); - } -}; + public: + TestStridedSliceQuantization() + : TestLeakyReLuActivationQuantization() {} -BOOST_AUTO_TEST_CASE(QuantizeStridedSlice) -{ - auto network = INetwork::Create(); + TestStridedSliceQuantization(const QuantizerOptions& options) + : TestLeakyReLuActivationQuantization(options) {} + + virtual void VisitStridedSliceLayer(const IConnectableLayer* layer, + const StridedSliceDescriptor& desc, + const char* name = nullptr) + { + CheckForwardedQuantizationSettings(layer); + } + }; + + INetworkPtr network = INetwork::Create(); TensorShape shape{3U}; TensorInfo info(shape, DataType::Float32); @@ -1183,9 +1345,14 @@ BOOST_AUTO_TEST_CASE(QuantizeStridedSlice) CompleteLeakyReluNetwork(network.get(), activation, stridedSlice, info); - auto quantizedNetwork = INetworkQuantizer::Create(network.get())->ExportNetwork(); - TestStridedSliceQuantization validator; - VisitLayersTopologically(quantizedNetwork.get(), validator); + INetworkPtr quantizedNetworkQAsymm8 = INetworkQuantizer::Create(network.get())->ExportNetwork(); + TestStridedSliceQuantization validatorQAsymm8; + VisitLayersTopologically(quantizedNetworkQAsymm8.get(), validatorQAsymm8); + + const QuantizerOptions options(DataType::QuantisedSymm16); + INetworkPtr quantizedNetworkQSymm16 = INetworkQuantizer::Create(network.get(), options)->ExportNetwork(); + TestStridedSliceQuantization validatorQSymm16(options); + VisitLayersTopologically(quantizedNetworkQSymm16.get(), validatorQSymm16); } BOOST_AUTO_TEST_CASE(QuantizeBatchToSpace) @@ -1193,6 +1360,12 @@ BOOST_AUTO_TEST_CASE(QuantizeBatchToSpace) class TestBatchToSpaceQuantization : public TestLeakyReLuActivationQuantization { public: + TestBatchToSpaceQuantization() + : TestLeakyReLuActivationQuantization() {} + + TestBatchToSpaceQuantization(const QuantizerOptions& options) + : TestLeakyReLuActivationQuantization(options) {} + void VisitBatchToSpaceNdLayer(const IConnectableLayer* layer, const BatchToSpaceNdDescriptor& batchToSpaceNdDescriptor, const char* name = nullptr) override @@ -1214,9 +1387,14 @@ BOOST_AUTO_TEST_CASE(QuantizeBatchToSpace) CompleteLeakyReluNetwork(network.get(), activation, batchToSpace, info); - auto quantizedNetwork = INetworkQuantizer::Create(network.get())->ExportNetwork(); - TestBatchToSpaceQuantization validator; - VisitLayersTopologically(quantizedNetwork.get(), validator); + INetworkPtr quantizedNetworkQAsymm8 = INetworkQuantizer::Create(network.get())->ExportNetwork(); + TestBatchToSpaceQuantization validatorQAsymm8; + VisitLayersTopologically(quantizedNetworkQAsymm8.get(), validatorQAsymm8); + + const QuantizerOptions options(DataType::QuantisedSymm16); + INetworkPtr quantizedNetworkQSymm16 = INetworkQuantizer::Create(network.get(), options)->ExportNetwork(); + TestBatchToSpaceQuantization validatorQSymm16(options); + VisitLayersTopologically(quantizedNetworkQSymm16.get(), validatorQSymm16); } std::vector SetupQuantize(float value) -- cgit v1.2.1