From c6fcfb4adc37a6cf09472168dc177234d4fabdfa Mon Sep 17 00:00:00 2001 From: Sang-Hoon Park Date: Wed, 31 Mar 2021 15:18:16 +0100 Subject: Add Tensor related utilities to the new API A couple of utility functions to get the information about tensors are added. Those functions are placed at an additional header file for better grouping. Related test cases are also added. Resolves: COMPMID-4376 Change-Id: I6bd09cbf60fddcf4fe651906982397afb0451392 Signed-off-by: Sang-Hoon Park Reviewed-on: https://review.mlplatform.org/c/ml/ComputeLibrary/+/5405 Comments-Addressed: Arm Jenkins Reviewed-by: Georgios Pinitas Reviewed-by: Michele Di Giorgio Tested-by: Arm Jenkins --- tests/validation/cpu/unit/Tensor.cpp | 47 +++++------- tests/validation/fixtures/UNIT/Tensor.h | 126 ++++++++++++++++++++++++++++++++ tests/validation/gpu/unit/Tensor.cpp | 39 +++++----- 3 files changed, 164 insertions(+), 48 deletions(-) (limited to 'tests') diff --git a/tests/validation/cpu/unit/Tensor.cpp b/tests/validation/cpu/unit/Tensor.cpp index 8fad7fa3ae..aa2e3abdf1 100644 --- a/tests/validation/cpu/unit/Tensor.cpp +++ b/tests/validation/cpu/unit/Tensor.cpp @@ -33,33 +33,26 @@ TEST_SUITE(CPU) TEST_SUITE(UNIT) TEST_SUITE(Tensor) -FIXTURE_TEST_CASE(CreateTensorWithInvalidContext, CreateTensorWithInvalidContextFixture, framework::DatasetMode::ALL) -{ -} -FIXTURE_TEST_CASE(CreateTensorWithInvalidDescriptor, CreateTensorWithInvalidDescriptorFixture, framework::DatasetMode::ALL) -{ -} -FIXTURE_TEST_CASE(DestroyInvalidTensor, DestroyInvalidTensorFixture, framework::DatasetMode::ALL) -{ -} -FIXTURE_TEST_CASE(SimpleTensor, SimpleTensorFixture, framework::DatasetMode::ALL) -{ -} -FIXTURE_TEST_CASE(TensorStress, TensorStressFixture, framework::DatasetMode::ALL) -{ -} -FIXTURE_TEST_CASE(MapInvalidTensor, MapInvalidTensorFixture, framework::DatasetMode::ALL) -{ -} -FIXTURE_TEST_CASE(MapNotAllocatedTensor, MapNotAllocatedTensorFixture, framework::DatasetMode::ALL) -{ -} -FIXTURE_TEST_CASE(MapAllocatedTensor, MapAllocatedTensorFixture, framework::DatasetMode::ALL) -{ -} -FIXTURE_TEST_CASE(ImportMemory, ImportMemoryFixture, framework::DatasetMode::ALL) -{ -} +#define TENSOR_TESE_CASE(name, fixture) \ + FIXTURE_TEST_CASE(name, fixture, framework::DatasetMode::ALL) \ + { \ + } + +TENSOR_TESE_CASE(CreateTensorWithInvalidContext, CreateTensorWithInvalidContextFixture) +TENSOR_TESE_CASE(CreateTensorWithInvalidDescriptor, CreateTensorWithInvalidDescriptorFixture) +TENSOR_TESE_CASE(DestroyInvalidTensor, DestroyInvalidTensorFixture) +TENSOR_TESE_CASE(SimpleTensor, SimpleTensorFixture) +TENSOR_TESE_CASE(TensorStress, TensorStressFixture) +TENSOR_TESE_CASE(MapInvalidTensor, MapInvalidTensorFixture) +TENSOR_TESE_CASE(MapNotAllocatedTensor, MapNotAllocatedTensorFixture) +TENSOR_TESE_CASE(MapAllocatedTensor, MapAllocatedTensorFixture) +TENSOR_TESE_CASE(ImportMemory, ImportMemoryFixture) +TENSOR_TESE_CASE(GetSize, TensorSizeFixture) +TENSOR_TESE_CASE(GetInvalidSize, InvalidTensorSizeFixture) +TENSOR_TESE_CASE(GetDescriptor, DescriptorConversionFixture) +TENSOR_TESE_CASE(GetInvalidDescriptor, InvalidDescriptorConversionFixture) + +#undef TENSOR_TEST_CASE TEST_SUITE_END() // Tensor TEST_SUITE_END() // UNIT diff --git a/tests/validation/fixtures/UNIT/Tensor.h b/tests/validation/fixtures/UNIT/Tensor.h index acd10c91fe..32260cb431 100644 --- a/tests/validation/fixtures/UNIT/Tensor.h +++ b/tests/validation/fixtures/UNIT/Tensor.h @@ -292,6 +292,132 @@ public: ARM_COMPUTE_ASSERT(tensor.unmap(handle) == acl::StatusCode::Success); } }; +/** Test case for get_size() interface of Tensor + * + * + * Test Steps: + * - Create a valid context + * - Create a valid tensor + * - Compare the size value returned with the expected value + */ +template +class TensorSizeFixture : public framework::Fixture +{ +public: + void setup() + { + acl::StatusCode err = acl::StatusCode::Success; + acl::Context ctx(Target, &err); + + ARM_COMPUTE_ASSERT(err == acl::StatusCode::Success); + acl::Tensor tensor(ctx, acl::TensorDescriptor({ 2, 3 }, acl::DataType::Float32), &err); + + // size should be 6 elements (2x3) times 4 bytes (float32) = 24 bytes + constexpr size_t expected_size = 24; + ARM_COMPUTE_ASSERT(tensor.get_size() == expected_size); + }; +}; +/** Test case for get_size() dealing with invalid arguments + * + * Test Steps: + * - Test nullptr tensor can return a correct error + * - Create a valid tensor + * - Test C interface with null size argument can return a correct error + */ +template +class InvalidTensorSizeFixture : public framework::Fixture +{ +public: + void setup() + { + // Null tensor + AclTensor null_tensor = nullptr; + uint64_t size{ 0 }; + ARM_COMPUTE_ASSERT(AclGetTensorSize(null_tensor, &size) == AclStatus::AclInvalidArgument); + + // Create valid tensor + acl::StatusCode err = acl::StatusCode::Success; + acl::Context ctx(Target, &err); + ARM_COMPUTE_ASSERT(err == acl::StatusCode::Success); + acl::Tensor tensor(ctx, acl::TensorDescriptor({ 2, 3 }, acl::DataType::Float32), &err); + + // Null size argument + ARM_COMPUTE_ASSERT(AclGetTensorSize(tensor.get(), nullptr) == AclStatus::AclInvalidArgument); + }; +}; + +template +class DescriptorConversionFixture : public framework::Fixture +{ + bool compare_descriptor(const AclTensorDescriptor &desc_a, const AclTensorDescriptor &desc_b) + { + auto are_descriptors_same = true; + + are_descriptors_same &= desc_a.ndims == desc_b.ndims; + are_descriptors_same &= desc_a.data_type == desc_b.data_type; + are_descriptors_same &= desc_a.shape != nullptr && desc_b.shape != nullptr; + + for(int32_t d = 0; d < desc_a.ndims; ++d) + { + are_descriptors_same &= desc_a.shape[d] == desc_b.shape[d]; + } + + // other attributes should be added here + + return are_descriptors_same; + } + +public: + void setup() + { + auto err{ acl::StatusCode::Success }; + auto ctx{ acl::Context(Target, &err) }; + ARM_COMPUTE_ASSERT(err == acl::StatusCode::Success); + + auto desc{ acl::TensorDescriptor({ 2, 3 }, acl::DataType::Float32) }; + acl::Tensor tensor(ctx, desc, &err); + + auto desc_from_tensor = tensor.get_descriptor(); + + ARM_COMPUTE_ASSERT(compare_descriptor(*desc.get(), *desc_from_tensor.get())); + ARM_COMPUTE_ASSERT(desc == desc_from_tensor); + + // Test c interface with "prepopulated" descriptor + // Note: When c interface used, there are possibility of memory leak + // if members are not correctly deleted (e.g., shape). + // Since that is considered user's responsibility, we don't test here. + AclTensorDescriptor prepopulated_descriptor + { + 3, nullptr, AclDataType::AclBFloat16, nullptr, 0 + }; + + ARM_COMPUTE_ASSERT(AclGetTensorDescriptor(tensor.get(), &prepopulated_descriptor) == AclStatus::AclSuccess); + ARM_COMPUTE_ASSERT(compare_descriptor(*desc.get(), prepopulated_descriptor)); + ARM_COMPUTE_ASSERT(desc == acl::TensorDescriptor(prepopulated_descriptor)); + }; +}; + +template +class InvalidDescriptorConversionFixture : public framework::Fixture +{ +public: + void setup() + { + // Null tensor + AclTensor null_tensor = nullptr; + AclTensorDescriptor desc{}; + ARM_COMPUTE_ASSERT(AclGetTensorDescriptor(null_tensor, &desc) == AclStatus::AclInvalidArgument); + + // Create valid tensor + acl::StatusCode err = acl::StatusCode::Success; + acl::Context ctx(Target, &err); + ARM_COMPUTE_ASSERT(err == acl::StatusCode::Success); + acl::Tensor tensor(ctx, acl::TensorDescriptor({ 2, 3 }, acl::DataType::Float32), &err); + + // Null size argument + ARM_COMPUTE_ASSERT(AclGetTensorDescriptor(tensor.get(), nullptr) == AclStatus::AclInvalidArgument); + }; +}; } // namespace validation } // namespace test } // namespace arm_compute diff --git a/tests/validation/gpu/unit/Tensor.cpp b/tests/validation/gpu/unit/Tensor.cpp index f8278afe25..b40d6264f5 100644 --- a/tests/validation/gpu/unit/Tensor.cpp +++ b/tests/validation/gpu/unit/Tensor.cpp @@ -33,27 +33,24 @@ TEST_SUITE(CL) TEST_SUITE(UNIT) TEST_SUITE(Tensor) -FIXTURE_TEST_CASE(CreateTensorWithInvalidContext, CreateTensorWithInvalidContextFixture, framework::DatasetMode::ALL) -{ -} -FIXTURE_TEST_CASE(CreateTensorWithInvalidDescriptor, CreateTensorWithInvalidDescriptorFixture, framework::DatasetMode::ALL) -{ -} -FIXTURE_TEST_CASE(DestroyInvalidTensor, DestroyInvalidTensorFixture, framework::DatasetMode::ALL) -{ -} -FIXTURE_TEST_CASE(SimpleTensor, SimpleTensorFixture, framework::DatasetMode::ALL) -{ -} -FIXTURE_TEST_CASE(TensorStress, TensorStressFixture, framework::DatasetMode::ALL) -{ -} -FIXTURE_TEST_CASE(MapInvalidTensor, MapInvalidTensorFixture, framework::DatasetMode::ALL) -{ -} -FIXTURE_TEST_CASE(MapAllocatedTensor, MapAllocatedTensorFixture, framework::DatasetMode::ALL) -{ -} +#define TENSOR_TESE_CASE(name, fixture) \ + FIXTURE_TEST_CASE(name, fixture, framework::DatasetMode::ALL) \ + { \ + } + +TENSOR_TESE_CASE(CreateTensorWithInvalidContext, CreateTensorWithInvalidContextFixture) +TENSOR_TESE_CASE(CreateTensorWithInvalidDescriptor, CreateTensorWithInvalidDescriptorFixture) +TENSOR_TESE_CASE(DestroyInvalidTensor, DestroyInvalidTensorFixture) +TENSOR_TESE_CASE(SimpleTensor, SimpleTensorFixture) +TENSOR_TESE_CASE(TensorStress, TensorStressFixture) +TENSOR_TESE_CASE(MapInvalidTensor, MapInvalidTensorFixture) +TENSOR_TESE_CASE(MapAllocatedTensor, MapAllocatedTensorFixture) +TENSOR_TESE_CASE(GetSize, TensorSizeFixture) +TENSOR_TESE_CASE(GetInvalidSize, InvalidTensorSizeFixture) +TENSOR_TESE_CASE(GetDescriptor, DescriptorConversionFixture) +TENSOR_TESE_CASE(GetInvalidDescriptor, InvalidDescriptorConversionFixture) + +#undef TENSOR_TEST_CASE TEST_SUITE_END() // Tensor TEST_SUITE_END() // UNIT -- cgit v1.2.1