diff options
Diffstat (limited to 'tests/validation')
-rw-r--r-- | tests/validation/CPP/GEMMLowp.cpp | 28 | ||||
-rw-r--r-- | tests/validation/CPP/GEMMLowp.h | 11 | ||||
-rw-r--r-- | tests/validation/NEON/GEMMLowp.cpp | 17 | ||||
-rw-r--r-- | tests/validation/fixtures/GEMMLowpAssemblyFixture.h | 42 | ||||
-rw-r--r-- | tests/validation/fixtures/GEMMLowpFixture.h | 2 |
5 files changed, 71 insertions, 29 deletions
diff --git a/tests/validation/CPP/GEMMLowp.cpp b/tests/validation/CPP/GEMMLowp.cpp index bf002cf2b5..35b8a6486e 100644 --- a/tests/validation/CPP/GEMMLowp.cpp +++ b/tests/validation/CPP/GEMMLowp.cpp @@ -63,19 +63,21 @@ void quantize_down_int32_to_uint8_scale(const SimpleTensor<T> *in, const SimpleT } } // namespace -template <typename T> -SimpleTensor<int32_t> gemmlowp_matrix_multiply_core(const SimpleTensor<T> &a, const SimpleTensor<T> &b, int32_t a_offset, int32_t b_offset) +template <typename T_out, typename T_in> +SimpleTensor<T_out> gemmlowp_matrix_multiply_core(const SimpleTensor<T_in> &a, const SimpleTensor<T_in> &b, int32_t a_offset, int32_t b_offset) { - TensorShape shape(b.shape()[0], a.shape()[1]); + static_assert(std::is_same<typename std::decay<T_out>::type, int32_t>::value, "Only int32_t is allowed for the output"); - SimpleTensor<int32_t> c(shape, DataType::S32); + TensorShape shape(b.shape()[0], a.shape()[1]); + DataType dt = std::is_same<T_out, int32_t>::value ? DataType::S32 : DataType::U32; + SimpleTensor<T_out> c(shape, dt); const int K = a.shape().x(); const int b_width = b.shape().x(); const int rows = c.shape().y(); //M const int cols = c.shape().x(); //N - std::vector<int32_t> acc; + std::vector<T_out> acc; acc.resize(cols); for(int i = 0; i < rows; ++i) @@ -86,11 +88,11 @@ SimpleTensor<int32_t> gemmlowp_matrix_multiply_core(const SimpleTensor<T> &a, co } for(int k = 0; k < K; ++k) { - const int32_t tmp_a = a_offset + static_cast<int32_t>(a[k + i * K]); + const T_out tmp_a = a_offset + static_cast<T_out>(a[k + i * K]); for(int j = 0; j < b_width; ++j) { - const int32_t tmp_b = b_offset + static_cast<int32_t>(b[j + k * b_width]); - const int32_t mult_as_int = tmp_a * tmp_b; + const T_out tmp_b = b_offset + static_cast<T_out>(b[j + k * b_width]); + const T_out mult_as_int = tmp_a * tmp_b; acc[j] += mult_as_int; } } @@ -104,9 +106,10 @@ SimpleTensor<int32_t> gemmlowp_matrix_multiply_core(const SimpleTensor<T> &a, co } // used to validate assembly kernels which don't know anything about offsets -SimpleTensor<int32_t> gemmlowp(const SimpleTensor<int8_t> &a, const SimpleTensor<int8_t> &b) +template <typename T1, typename T2> +SimpleTensor<T1> gemmlowp(const SimpleTensor<T2> &a, const SimpleTensor<T2> &b) { - return gemmlowp_matrix_multiply_core(a, b, 0, 0); + return gemmlowp_matrix_multiply_core<T1, T2>(a, b, 0, 0); } template <typename T> @@ -130,11 +133,14 @@ SimpleTensor<uint8_t> gemmlowp_quantize_down_int32_to_uint8_scale(const SimpleTe return dst; } -template SimpleTensor<int32_t> gemmlowp_matrix_multiply_core(const SimpleTensor<uint8_t> &a, const SimpleTensor<uint8_t> &b, int32_t a_offset, int32_t b_offset); template SimpleTensor<uint8_t> gemmlowp_quantize_down_int32_to_uint8_scale(const SimpleTensor<int32_t> &a, int32_t result_offset, int32_t result_mult_int, int32_t result_shift, int32_t min, int32_t max); template SimpleTensor<uint8_t> gemmlowp_quantize_down_int32_to_uint8_scale(const SimpleTensor<int32_t> &a, const SimpleTensor<int32_t> &b, int32_t result_offset, int32_t result_mult_int, int32_t result_shift, int32_t min, int32_t max); +template SimpleTensor<int32_t> gemmlowp_matrix_multiply_core(const SimpleTensor<int8_t> &a, const SimpleTensor<int8_t> &b, int32_t a_offset, int32_t b_offset); +template SimpleTensor<int32_t> gemmlowp_matrix_multiply_core(const SimpleTensor<uint8_t> &a, const SimpleTensor<uint8_t> &b, int32_t a_offset, int32_t b_offset); +template SimpleTensor<int32_t> gemmlowp(const SimpleTensor<int8_t> &a, const SimpleTensor<int8_t> &b); +template SimpleTensor<int32_t> gemmlowp(const SimpleTensor<uint8_t> &a, const SimpleTensor<uint8_t> &b); } // namespace reference } // namespace validation } // namespace test diff --git a/tests/validation/CPP/GEMMLowp.h b/tests/validation/CPP/GEMMLowp.h index ee33d8e0c0..6c72b56e7a 100644 --- a/tests/validation/CPP/GEMMLowp.h +++ b/tests/validation/CPP/GEMMLowp.h @@ -35,13 +35,16 @@ namespace validation { namespace reference { -SimpleTensor<int32_t> gemmlowp(const SimpleTensor<int8_t> &a, const SimpleTensor<int8_t> &b); - template <typename T> -SimpleTensor<int32_t> gemmlowp_matrix_multiply_core(const SimpleTensor<T> &a, const SimpleTensor<T> &b, int32_t a_offset, int32_t b_offset); +SimpleTensor<uint8_t> gemmlowp_quantize_down_int32_to_uint8_scale(const SimpleTensor<T> &in, int32_t result_offset, int32_t result_mult_int, int32_t result_shift, int32_t min = 0, int32_t max = 0); +template <typename T1, typename T2> +SimpleTensor<T1> gemmlowp_matrix_multiply_core(const SimpleTensor<T2> &a, const SimpleTensor<T2> &b, int32_t a_offset, int32_t b_offset); template <typename T> -SimpleTensor<uint8_t> gemmlowp_quantize_down_int32_to_uint8_scale(const SimpleTensor<T> &in, int32_t result_offset, int32_t result_mult_int, int32_t result_shift, int32_t min = 0, int32_t max = 0); +SimpleTensor<uint8_t> gemmlowp_quantize_down_int32_to_uint8_scale(const SimpleTensor<T> &in, int32_t result_offset, int32_t result_mult_int, int32_t result_shift); + +template <typename T1, typename T2> +SimpleTensor<T1> gemmlowp(const SimpleTensor<T2> &a, const SimpleTensor<T2> &b); template <typename T> SimpleTensor<uint8_t> gemmlowp_quantize_down_int32_to_uint8_scale(const SimpleTensor<T> &in, const SimpleTensor<T> &bias, int32_t result_offset, int32_t result_mult_int, int32_t result_shift, diff --git a/tests/validation/NEON/GEMMLowp.cpp b/tests/validation/NEON/GEMMLowp.cpp index 1418578a51..6366223820 100644 --- a/tests/validation/NEON/GEMMLowp.cpp +++ b/tests/validation/NEON/GEMMLowp.cpp @@ -58,14 +58,27 @@ const auto data_matrix_multiply = framework::dataset::make("M", 12, 20) * framew TEST_SUITE(NEON) TEST_SUITE(ASSEMBLY_MATRIX_MULTIPLY) -using NEGEMMAssemblyFixture = GEMMLowpAssemblyFixture<Tensor, Accessor, NEGEMMLowpAssemblyMatrixMultiplyCore>; -FIXTURE_DATA_TEST_CASE(RunSmall, NEGEMMAssemblyFixture, framework::DatasetMode::PRECOMMIT, data_matrix_multiply) + +using NEGEMMAssemblyFixture_S8 = GEMMLowpAssemblyFixture<Tensor, Accessor, NEGEMMLowpAssemblyMatrixMultiplyCore, int8_t>; +using NEGEMMAssemblyFixture_U8 = GEMMLowpAssemblyFixture<Tensor, Accessor, NEGEMMLowpAssemblyMatrixMultiplyCore, uint8_t>; + +TEST_SUITE(S8) +FIXTURE_DATA_TEST_CASE(RunSmall, NEGEMMAssemblyFixture_S8, framework::DatasetMode::PRECOMMIT, data_matrix_multiply) { // Validate output validate(Accessor(_target), _reference); } TEST_SUITE_END() +TEST_SUITE(U8) +FIXTURE_DATA_TEST_CASE(RunSmall, NEGEMMAssemblyFixture_U8, framework::DatasetMode::PRECOMMIT, data_matrix_multiply) +{ + // Validate output + validate(Accessor(_target), _reference); +} +TEST_SUITE_END() +TEST_SUITE_END() + TEST_SUITE(GEMMLowp) TEST_SUITE(INTERLEAVE_BLOCKED) diff --git a/tests/validation/fixtures/GEMMLowpAssemblyFixture.h b/tests/validation/fixtures/GEMMLowpAssemblyFixture.h index a2587440fb..38e08f7992 100644 --- a/tests/validation/fixtures/GEMMLowpAssemblyFixture.h +++ b/tests/validation/fixtures/GEMMLowpAssemblyFixture.h @@ -42,7 +42,7 @@ namespace test { namespace validation { -template <typename TensorType, typename AccessorType, typename FunctionType> +template <typename TensorType, typename AccessorType, typename FunctionType, typename T2> class GEMMLowpAssemblyFixture : public framework::Fixture { public: @@ -66,9 +66,11 @@ protected: TensorType compute_target(const TensorShape &shape_a, const TensorShape &shape_b, const TensorShape &shape_c) { + DataType dt_in = std::is_same<T2, int8_t>::value ? DataType::S8 : DataType::U8; + // Create tensors - TensorType a = create_tensor<TensorType>(shape_a, DataType::S8, 1); - TensorType b = create_tensor<TensorType>(shape_b, DataType::S8, 1); + TensorType a = create_tensor<TensorType>(shape_a, dt_in, 1); + TensorType b = create_tensor<TensorType>(shape_b, dt_in, 1); TensorType c = create_tensor<TensorType>(shape_c, DataType::S32, 1); // Create and configure function @@ -89,8 +91,16 @@ protected: ARM_COMPUTE_EXPECT(!c.info()->is_resizable(), framework::LogLevel::ERRORS); // Fill tensors - fill(AccessorType(a), 0, -128, 127); - fill(AccessorType(b), 1, -128, 127); + if(dt_in == DataType::S8) + { + fill(AccessorType(a), 0, -128, 127); + fill(AccessorType(b), 1, -128, 127); + } + else + { + fill(AccessorType(a), 0, 0, 128); + fill(AccessorType(b), 1, 0, 128); + } fill(AccessorType(c), 2, 0, 0); // Compute GEMM function @@ -100,15 +110,25 @@ protected: SimpleTensor<int32_t> compute_reference(const TensorShape &shape_a, const TensorShape &shape_b, const TensorShape &shape_c) { + DataType dt = std::is_same<T2, int8_t>::value ? DataType::S8 : DataType::U8; + // Create reference - SimpleTensor<int8_t> a{ shape_a, DataType::S8, 1 }; - SimpleTensor<int8_t> b{ shape_b, DataType::S8, 1 }; + SimpleTensor<T2> a{ shape_a, dt, 1 }; + SimpleTensor<T2> b{ shape_b, dt, 1 }; // Fill reference - fill(a, 0, -128, 127); - fill(b, 1, -128, 127); - - return reference::gemmlowp(a, b); + if(dt == DataType::S8) + { + fill(a, 0, -128, 127); + fill(b, 1, -128, 127); + } + else + { + fill(a, 0, 0, 128); + fill(b, 1, 0, 128); + } + + return reference::gemmlowp<int32_t, T2>(a, b); } TensorType _target{}; diff --git a/tests/validation/fixtures/GEMMLowpFixture.h b/tests/validation/fixtures/GEMMLowpFixture.h index a99e9323c8..60b89bc653 100644 --- a/tests/validation/fixtures/GEMMLowpFixture.h +++ b/tests/validation/fixtures/GEMMLowpFixture.h @@ -110,7 +110,7 @@ protected: fill(a, 0); fill(b, 1); - return reference::gemmlowp_matrix_multiply_core<uint8_t>(a, b, a_offset, b_offset); + return reference::gemmlowp_matrix_multiply_core<int32_t, uint8_t>(a, b, a_offset, b_offset); } TensorType _target{}; |