diff options
-rw-r--r-- | Android.bp | 1 | ||||
-rw-r--r-- | arm_compute/Acl.h | 1 | ||||
-rw-r--r-- | arm_compute/Acl.hpp | 61 | ||||
-rw-r--r-- | arm_compute/AclUtils.h | 63 | ||||
-rw-r--r-- | src/c/AclTensor.cpp | 44 | ||||
-rw-r--r-- | src/c/AclTensorPack.cpp | 2 | ||||
-rw-r--r-- | src/c/cl/AclOpenClExt.cpp | 2 | ||||
-rw-r--r-- | src/common/ITensorV2.cpp | 39 | ||||
-rw-r--r-- | src/common/ITensorV2.h (renamed from src/common/ITensor.h) | 14 | ||||
-rw-r--r-- | src/common/TensorPack.cpp | 2 | ||||
-rw-r--r-- | src/common/utils/LegacySupport.cpp | 53 | ||||
-rw-r--r-- | src/common/utils/LegacySupport.h | 7 | ||||
-rw-r--r-- | src/common/utils/Utils.h | 4 | ||||
-rw-r--r-- | src/cpu/CpuTensor.cpp | 2 | ||||
-rw-r--r-- | src/cpu/CpuTensor.h | 4 | ||||
-rw-r--r-- | src/gpu/cl/ClTensor.cpp | 2 | ||||
-rw-r--r-- | src/gpu/cl/ClTensor.h | 4 | ||||
-rw-r--r-- | tests/validation/cpu/unit/Tensor.cpp | 47 | ||||
-rw-r--r-- | tests/validation/fixtures/UNIT/Tensor.h | 126 | ||||
-rw-r--r-- | tests/validation/gpu/unit/Tensor.cpp | 39 |
20 files changed, 452 insertions, 65 deletions
diff --git a/Android.bp b/Android.bp index 17281a49d1..3736ef754f 100644 --- a/Android.bp +++ b/Android.bp @@ -57,6 +57,7 @@ cc_library_static { "src/c/AclVersion.cpp", "src/c/cl/AclOpenClExt.cpp", "src/common/AllocatorWrapper.cpp", + "src/common/ITensorV2.cpp", "src/common/TensorPack.cpp", "src/common/utils/LegacySupport.cpp", "src/core/AccessWindowAutoPadding.cpp", diff --git a/arm_compute/Acl.h b/arm_compute/Acl.h index 6958f60bfd..316407c02e 100644 --- a/arm_compute/Acl.h +++ b/arm_compute/Acl.h @@ -31,6 +31,7 @@ extern "C" { /* Core headers */ #include "arm_compute/AclEntrypoints.h" #include "arm_compute/AclTypes.h" +#include "arm_compute/AclUtils.h" #include "arm_compute/AclVersion.h" #ifdef __cplusplus diff --git a/arm_compute/Acl.hpp b/arm_compute/Acl.hpp index a009894438..01f7179c2f 100644 --- a/arm_compute/Acl.hpp +++ b/arm_compute/Acl.hpp @@ -428,6 +428,20 @@ public: _cdesc.strides = nullptr; _cdesc.boffset = 0; } + /** Constructor + * + * @param[in] desc C-type descriptor + */ + explicit TensorDescriptor(const AclTensorDescriptor &desc) + { + _cdesc = desc; + _data_type = detail::as_enum<DataType>(desc.data_type); + _shape.reserve(desc.ndims); + for(int32_t d = 0; d < desc.ndims; ++d) + { + _shape.emplace_back(desc.shape[d]); + } + } /** Get underlying C tensor descriptor * * @return Underlying structure @@ -436,6 +450,29 @@ public: { return &_cdesc; } + /** Operator to compare two TensorDescriptor + * + * @param[in] other The instance to compare against + * + * @return True if two instances have the same shape and data type + */ + bool operator==(const TensorDescriptor &other) + { + bool is_same = true; + + is_same &= _data_type == other._data_type; + is_same &= _shape.size() == other._shape.size(); + + if(is_same) + { + for(uint32_t d = 0; d < _shape.size(); ++d) + { + is_same &= _shape[d] == other._shape[d]; + } + } + + return is_same; + } private: std::vector<int32_t> _shape{}; @@ -524,6 +561,30 @@ public: report_status(st, "[Arm Compute Library] Failed to import external memory to tensor!"); return st; } + /** Get the size of the tensor in byte + * + * @note The size isn't based on allocated memory, but based on information in its descriptor (dimensions, data type, etc.). + * + * @return The size of the tensor in byte + */ + uint64_t get_size() + { + uint64_t size{ 0 }; + const auto st = detail::as_enum<StatusCode>(AclGetTensorSize(_object.get(), &size)); + report_status(st, "[Arm Compute Library] Failed to get the size of the tensor"); + return size; + } + /** Get the descriptor of this tensor + * + * @return The descriptor describing the characteristics of this tensor + */ + TensorDescriptor get_descriptor() + { + AclTensorDescriptor desc; + const auto st = detail::as_enum<StatusCode>(AclGetTensorDescriptor(_object.get(), &desc)); + report_status(st, "[Arm Compute Library] Failed to get the descriptor of the tensor"); + return TensorDescriptor(desc); + } }; /** Tensor pack class diff --git a/arm_compute/AclUtils.h b/arm_compute/AclUtils.h new file mode 100644 index 0000000000..2e75772ee8 --- /dev/null +++ b/arm_compute/AclUtils.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2021 Arm Limited. + * + * SPDX-License-Identifier: MIT + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#ifndef ARM_COMPUTE_ACLUTILS_H_ +#define ARM_COMPUTE_ACLUTILS_H_ + +#include "arm_compute/AclTypes.h" + +#ifdef __cplusplus +extern "C" { +#endif /** __cplusplus */ + +/** Get the size of the existing tensor in byte + * + * @note The size isn't based on allocated memory, but based on information in its descriptor (dimensions, data type, etc.). + * + * @param[in] tensor A tensor in interest + * @param[out] size The size of the tensor + * + * @return Status code + * + * - @ref AclSuccess if function was completed successfully + * - @ref AclInvalidArgument if a given argument is invalid + */ +AclStatus AclGetTensorSize(AclTensor tensor, uint64_t *size); + +/** Get the descriptor of this tensor + * + * @param[in] tensor A tensor in interest + * @param[out] desc The descriptor of the tensor + * + * @return Status code + * + * - @ref AclSuccess if function was completed successfully + * - @ref AclInvalidArgument if a given argument is invalid + */ +AclStatus AclGetTensorDescriptor(AclTensor tensor, AclTensorDescriptor *desc); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* ARM_COMPUTE_ACLUTILS_H_ */ diff --git a/src/c/AclTensor.cpp b/src/c/AclTensor.cpp index 0d884b1ec3..8f6ce45628 100644 --- a/src/c/AclTensor.cpp +++ b/src/c/AclTensor.cpp @@ -22,11 +22,13 @@ * SOFTWARE. */ #include "arm_compute/AclEntrypoints.h" -#include "src/common/ITensor.h" +#include "arm_compute/AclUtils.h" +#include "src/common/ITensorV2.h" #include "src/common/utils/Macros.h" namespace { +using namespace arm_compute; /**< Maximum allowed dimensions by Compute Library */ constexpr int32_t max_allowed_dims = 6; @@ -55,6 +57,12 @@ bool is_desc_valid(const AclTensorDescriptor &desc) } return true; } + +StatusCode convert_and_validate_tensor(AclTensor tensor, ITensorV2 **internal_tensor) +{ + *internal_tensor = get_internal(tensor); + return detail::validate_internal_tensor(*internal_tensor); +} } // namespace extern "C" AclStatus AclCreateTensor(AclTensor *external_tensor, @@ -146,3 +154,37 @@ extern "C" AclStatus AclDestroyTensor(AclTensor external_tensor) return AclSuccess; } + +extern "C" AclStatus AclGetTensorSize(AclTensor tensor, uint64_t *size) +{ + using namespace arm_compute; + + if(size == nullptr) + { + return AclStatus::AclInvalidArgument; + } + + ITensorV2 *internal_tensor{ nullptr }; + auto status = convert_and_validate_tensor(tensor, &internal_tensor); + ARM_COMPUTE_RETURN_CENUM_ON_FAILURE(status); + + *size = internal_tensor->get_size(); + return utils::as_cenum<AclStatus>(status); +} + +extern "C" AclStatus AclGetTensorDescriptor(AclTensor tensor, AclTensorDescriptor *desc) +{ + using namespace arm_compute; + + if(desc == nullptr) + { + return AclStatus::AclInvalidArgument; + } + + ITensorV2 *internal_tensor{ nullptr }; + const auto status = convert_and_validate_tensor(tensor, &internal_tensor); + ARM_COMPUTE_RETURN_CENUM_ON_FAILURE(status); + + *desc = internal_tensor->get_descriptor(); + return utils::as_cenum<AclStatus>(status); +}
\ No newline at end of file diff --git a/src/c/AclTensorPack.cpp b/src/c/AclTensorPack.cpp index 6700ef464c..6202524ca7 100644 --- a/src/c/AclTensorPack.cpp +++ b/src/c/AclTensorPack.cpp @@ -22,7 +22,7 @@ * SOFTWARE. */ #include "arm_compute/AclEntrypoints.h" -#include "src/common/ITensor.h" +#include "src/common/ITensorV2.h" #include "src/common/TensorPack.h" #include "src/common/utils/Macros.h" diff --git a/src/c/cl/AclOpenClExt.cpp b/src/c/cl/AclOpenClExt.cpp index a144f97f55..ce6d2969de 100644 --- a/src/c/cl/AclOpenClExt.cpp +++ b/src/c/cl/AclOpenClExt.cpp @@ -23,7 +23,7 @@ */ #include "arm_compute/AclOpenClExt.h" -#include "src/common/ITensor.h" +#include "src/common/ITensorV2.h" #include "src/common/Types.h" #include "src/gpu/cl/ClContext.h" diff --git a/src/common/ITensorV2.cpp b/src/common/ITensorV2.cpp new file mode 100644 index 0000000000..39bf1c6fb3 --- /dev/null +++ b/src/common/ITensorV2.cpp @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2021 Arm Limited. + * + * SPDX-License-Identifier: MIT + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#include "src/common/ITensorV2.h" +#include "arm_compute/core/TensorInfo.h" +#include "src/common/utils/LegacySupport.h" + +namespace arm_compute +{ +size_t ITensorV2::get_size() const +{ + return tensor()->info()->total_size(); +} + +AclTensorDescriptor ITensorV2::get_descriptor() const +{ + return detail::convert_to_descriptor(*tensor()->info()); +} +} // namespace arm_compute
\ No newline at end of file diff --git a/src/common/ITensor.h b/src/common/ITensorV2.h index ee7eac7688..965aacea23 100644 --- a/src/common/ITensor.h +++ b/src/common/ITensorV2.h @@ -92,7 +92,19 @@ public: * * @return The legacy underlying tensor object */ - virtual arm_compute::ITensor *tensor() = 0; + virtual arm_compute::ITensor *tensor() const = 0; + /** Get the size of the tensor in byte + * + * @note The size isn't based on allocated memory, but based on information in its descriptor (dimensions, data type, etc.). + * + * @return The size of the tensor in byte + */ + size_t get_size() const; + /** Get the descriptor of this tensor + * + * @return The descriptor describing the characteristics of this tensor + */ + AclTensorDescriptor get_descriptor() const; }; /** Extract internal representation of a Tensor diff --git a/src/common/TensorPack.cpp b/src/common/TensorPack.cpp index c582c7b106..6c2c7f9622 100644 --- a/src/common/TensorPack.cpp +++ b/src/common/TensorPack.cpp @@ -22,7 +22,7 @@ * SOFTWARE. */ #include "src/common/TensorPack.h" -#include "src/common/ITensor.h" +#include "src/common/ITensorV2.h" #include "src/common/utils/Validate.h" namespace arm_compute diff --git a/src/common/utils/LegacySupport.cpp b/src/common/utils/LegacySupport.cpp index 5981c657bd..569b2abd89 100644 --- a/src/common/utils/LegacySupport.cpp +++ b/src/common/utils/LegacySupport.cpp @@ -29,7 +29,7 @@ namespace detail { namespace { -DataType data_type_mapper(AclDataType data_type) +DataType convert_to_legacy_data_type(AclDataType data_type) { switch(data_type) { @@ -41,11 +41,25 @@ DataType data_type_mapper(AclDataType data_type) return DataType::BFLOAT16; default: return DataType::UNKNOWN; - ; } } -TensorShape tensor_shape_mapper(int32_t ndims, int32_t *shape) +AclDataType convert_to_c_data_type(DataType data_type) +{ + switch(data_type) + { + case DataType::F32: + return AclDataType::AclFloat32; + case DataType::F16: + return AclDataType::AclFloat16; + case DataType::BFLOAT16: + return AclDataType::AclBFloat16; + default: + return AclDataType::AclDataTypeUnknown; + } +} + +TensorShape create_legacy_tensor_shape(int32_t ndims, int32_t *shape) { TensorShape legacy_shape{}; for(int32_t d = 0; d < ndims; ++d) @@ -54,13 +68,44 @@ TensorShape tensor_shape_mapper(int32_t ndims, int32_t *shape) } return legacy_shape; } +int32_t *create_tensor_shape_array(const TensorInfo &info) +{ + const auto num_dims = info.num_dimensions(); + if(num_dims <= 0) + { + return nullptr; + } + + int32_t *shape_array = new int32_t[num_dims]; + + for(size_t d = 0; d < num_dims; ++d) + { + shape_array[d] = info.tensor_shape()[d]; + } + + return shape_array; +} } // namespace TensorInfo convert_to_legacy_tensor_info(const AclTensorDescriptor &desc) { TensorInfo legacy_desc; - legacy_desc.init(tensor_shape_mapper(desc.ndims, desc.shape), 1, data_type_mapper(desc.data_type)); + legacy_desc.init(create_legacy_tensor_shape(desc.ndims, desc.shape), 1, convert_to_legacy_data_type(desc.data_type)); return legacy_desc; } + +AclTensorDescriptor convert_to_descriptor(const TensorInfo &info) +{ + const auto num_dims = info.num_dimensions(); + AclTensorDescriptor desc + { + static_cast<int32_t>(num_dims), + create_tensor_shape_array(info), + convert_to_c_data_type(info.data_type()), + nullptr, + 0 + }; + return desc; +} } // namespace detail } // namespace arm_compute diff --git a/src/common/utils/LegacySupport.h b/src/common/utils/LegacySupport.h index 37329b747c..c2cc1bc182 100644 --- a/src/common/utils/LegacySupport.h +++ b/src/common/utils/LegacySupport.h @@ -38,6 +38,13 @@ namespace detail * @return Legacy tensor meta-data */ TensorInfo convert_to_legacy_tensor_info(const AclTensorDescriptor &desc); +/** Convert a legacy tensor meta-data to a descriptor + * + * @param[in] info Legacy tensor meta-data + * + * @return A converted descriptor + */ +AclTensorDescriptor convert_to_descriptor(const TensorInfo &info); } // namespace detail } // namespace arm_compute diff --git a/src/common/utils/Utils.h b/src/common/utils/Utils.h index 87be9df509..79f4f39c47 100644 --- a/src/common/utils/Utils.h +++ b/src/common/utils/Utils.h @@ -40,7 +40,7 @@ namespace utils * @return A corresponding plain old C enumeration */ template <typename E, typename SE> -constexpr E as_cenum(SE v) noexcept +constexpr E as_cenum(const SE v) noexcept { return static_cast<E>(static_cast<std::underlying_type_t<SE>>(v)); } @@ -55,7 +55,7 @@ constexpr E as_cenum(SE v) noexcept * @return A corresponding strongly typed enumeration */ template <typename SE, typename E> -constexpr SE as_enum(E val) noexcept +constexpr SE as_enum(const E val) noexcept { return static_cast<SE>(val); } diff --git a/src/cpu/CpuTensor.cpp b/src/cpu/CpuTensor.cpp index 79dc812c58..6dd6d9c31b 100644 --- a/src/cpu/CpuTensor.cpp +++ b/src/cpu/CpuTensor.cpp @@ -72,7 +72,7 @@ StatusCode CpuTensor::import(void *handle, ImportMemoryType type) return bool(st) ? StatusCode::Success : StatusCode::RuntimeError; } -arm_compute::ITensor *CpuTensor::tensor() +arm_compute::ITensor *CpuTensor::tensor() const { return _legacy_tensor.get(); } diff --git a/src/cpu/CpuTensor.h b/src/cpu/CpuTensor.h index a46f1a26cb..b078774c99 100644 --- a/src/cpu/CpuTensor.h +++ b/src/cpu/CpuTensor.h @@ -24,7 +24,7 @@ #ifndef SRC_CPU_CPUTENSOR_H #define SRC_CPU_CPUTENSOR_H -#include "src/common/ITensor.h" +#include "src/common/ITensorV2.h" #include "arm_compute/runtime/Tensor.h" @@ -51,7 +51,7 @@ public: // Inherrited functions overriden void *map() override; StatusCode unmap() override; - arm_compute::ITensor *tensor() override; + arm_compute::ITensor *tensor() const override; StatusCode import(void *handle, ImportMemoryType type) override; private: diff --git a/src/gpu/cl/ClTensor.cpp b/src/gpu/cl/ClTensor.cpp index db2081c4ed..0df07813e3 100644 --- a/src/gpu/cl/ClTensor.cpp +++ b/src/gpu/cl/ClTensor.cpp @@ -83,7 +83,7 @@ StatusCode ClTensor::import(void *handle, ImportMemoryType type) return StatusCode::Success; } -arm_compute::ITensor *ClTensor::tensor() +arm_compute::ITensor *ClTensor::tensor() const { return _legacy_tensor.get(); } diff --git a/src/gpu/cl/ClTensor.h b/src/gpu/cl/ClTensor.h index 4188f622d6..99d228c0b8 100644 --- a/src/gpu/cl/ClTensor.h +++ b/src/gpu/cl/ClTensor.h @@ -24,7 +24,7 @@ #ifndef SRC_GPU_CLTENSOR_H #define SRC_GPU_CLTENSOR_H -#include "src/common/ITensor.h" +#include "src/common/ITensorV2.h" #include "arm_compute/runtime/CL/CLTensor.h" @@ -53,7 +53,7 @@ public: // Inherrited functions overriden void *map() override; StatusCode unmap() override; - arm_compute::ITensor *tensor() override; + arm_compute::ITensor *tensor() const override; StatusCode import(void *handle, ImportMemoryType type) override; private: 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<acl::Target::Cpu>, framework::DatasetMode::ALL) -{ -} -FIXTURE_TEST_CASE(DestroyInvalidTensor, DestroyInvalidTensorFixture<acl::Target::Cpu>, framework::DatasetMode::ALL) -{ -} -FIXTURE_TEST_CASE(SimpleTensor, SimpleTensorFixture<acl::Target::Cpu>, framework::DatasetMode::ALL) -{ -} -FIXTURE_TEST_CASE(TensorStress, TensorStressFixture<acl::Target::Cpu>, framework::DatasetMode::ALL) -{ -} -FIXTURE_TEST_CASE(MapInvalidTensor, MapInvalidTensorFixture<acl::Target::Cpu>, framework::DatasetMode::ALL) -{ -} -FIXTURE_TEST_CASE(MapNotAllocatedTensor, MapNotAllocatedTensorFixture<acl::Target::Cpu>, framework::DatasetMode::ALL) -{ -} -FIXTURE_TEST_CASE(MapAllocatedTensor, MapAllocatedTensorFixture<acl::Target::Cpu>, framework::DatasetMode::ALL) -{ -} -FIXTURE_TEST_CASE(ImportMemory, ImportMemoryFixture<acl::Target::Cpu>, 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<acl::Target::Cpu>) +TENSOR_TESE_CASE(DestroyInvalidTensor, DestroyInvalidTensorFixture<acl::Target::Cpu>) +TENSOR_TESE_CASE(SimpleTensor, SimpleTensorFixture<acl::Target::Cpu>) +TENSOR_TESE_CASE(TensorStress, TensorStressFixture<acl::Target::Cpu>) +TENSOR_TESE_CASE(MapInvalidTensor, MapInvalidTensorFixture<acl::Target::Cpu>) +TENSOR_TESE_CASE(MapNotAllocatedTensor, MapNotAllocatedTensorFixture<acl::Target::Cpu>) +TENSOR_TESE_CASE(MapAllocatedTensor, MapAllocatedTensorFixture<acl::Target::Cpu>) +TENSOR_TESE_CASE(ImportMemory, ImportMemoryFixture<acl::Target::Cpu>) +TENSOR_TESE_CASE(GetSize, TensorSizeFixture<acl::Target::Cpu>) +TENSOR_TESE_CASE(GetInvalidSize, InvalidTensorSizeFixture<acl::Target::Cpu>) +TENSOR_TESE_CASE(GetDescriptor, DescriptorConversionFixture<acl::Target::Cpu>) +TENSOR_TESE_CASE(GetInvalidDescriptor, InvalidDescriptorConversionFixture<acl::Target::Cpu>) + +#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 <acl::Target Target> +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 <acl::Target Target> +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 <acl::Target Target> +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 <acl::Target Target> +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<acl::Target::GpuOcl>, framework::DatasetMode::ALL) -{ -} -FIXTURE_TEST_CASE(DestroyInvalidTensor, DestroyInvalidTensorFixture<acl::Target::GpuOcl>, framework::DatasetMode::ALL) -{ -} -FIXTURE_TEST_CASE(SimpleTensor, SimpleTensorFixture<acl::Target::GpuOcl>, framework::DatasetMode::ALL) -{ -} -FIXTURE_TEST_CASE(TensorStress, TensorStressFixture<acl::Target::GpuOcl>, framework::DatasetMode::ALL) -{ -} -FIXTURE_TEST_CASE(MapInvalidTensor, MapInvalidTensorFixture<acl::Target::GpuOcl>, framework::DatasetMode::ALL) -{ -} -FIXTURE_TEST_CASE(MapAllocatedTensor, MapAllocatedTensorFixture<acl::Target::GpuOcl>, 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<acl::Target::GpuOcl>) +TENSOR_TESE_CASE(DestroyInvalidTensor, DestroyInvalidTensorFixture<acl::Target::GpuOcl>) +TENSOR_TESE_CASE(SimpleTensor, SimpleTensorFixture<acl::Target::GpuOcl>) +TENSOR_TESE_CASE(TensorStress, TensorStressFixture<acl::Target::GpuOcl>) +TENSOR_TESE_CASE(MapInvalidTensor, MapInvalidTensorFixture<acl::Target::GpuOcl>) +TENSOR_TESE_CASE(MapAllocatedTensor, MapAllocatedTensorFixture<acl::Target::GpuOcl>) +TENSOR_TESE_CASE(GetSize, TensorSizeFixture<acl::Target::GpuOcl>) +TENSOR_TESE_CASE(GetInvalidSize, InvalidTensorSizeFixture<acl::Target::GpuOcl>) +TENSOR_TESE_CASE(GetDescriptor, DescriptorConversionFixture<acl::Target::GpuOcl>) +TENSOR_TESE_CASE(GetInvalidDescriptor, InvalidDescriptorConversionFixture<acl::Target::GpuOcl>) + +#undef TENSOR_TEST_CASE TEST_SUITE_END() // Tensor TEST_SUITE_END() // UNIT |