diff options
Diffstat (limited to 'src/common')
25 files changed, 833 insertions, 340 deletions
diff --git a/src/common/AllocatorWrapper.cpp b/src/common/AllocatorWrapper.cpp index 7b5bb34433..28d81a9fa4 100644 --- a/src/common/AllocatorWrapper.cpp +++ b/src/common/AllocatorWrapper.cpp @@ -22,6 +22,7 @@ * SOFTWARE. */ #include "src/common/AllocatorWrapper.h" + #include "arm_compute/core/Error.h" namespace arm_compute @@ -57,7 +58,7 @@ void AllocatorWrapper::aligned_free(void *ptr) void AllocatorWrapper::set_user_data(void *user_data) { - if(user_data != nullptr) + if (user_data != nullptr) { _backing_allocator.user_data = user_data; } diff --git a/src/common/AllocatorWrapper.h b/src/common/AllocatorWrapper.h index 5e1f138f16..bbf70a2cb1 100644 --- a/src/common/AllocatorWrapper.h +++ b/src/common/AllocatorWrapper.h @@ -37,8 +37,8 @@ public: * @param[in] backing_allocator Backing memory allocator to be used */ AllocatorWrapper(const AclAllocator &backing_allocator) noexcept; - AllocatorWrapper(const AllocatorWrapper &) noexcept = default; - AllocatorWrapper(AllocatorWrapper &&) noexcept = default; + AllocatorWrapper(const AllocatorWrapper &) noexcept = default; + AllocatorWrapper(AllocatorWrapper &&) noexcept = default; AllocatorWrapper &operator=(const AllocatorWrapper &) noexcept = delete; AllocatorWrapper &operator=(AllocatorWrapper &&other) noexcept = default; /** Allocate a chunk of memory of a given size in bytes @@ -78,4 +78,4 @@ private: }; } // namespace arm_compute -#endif /* SRC_COMMON_ALLOCATORWRAPPER_H */
\ No newline at end of file +#endif /* SRC_COMMON_ALLOCATORWRAPPER_H */ diff --git a/src/common/IContext.h b/src/common/IContext.h index 31f39da06d..a221e5db61 100644 --- a/src/common/IContext.h +++ b/src/common/IContext.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Arm Limited. + * Copyright (c) 2021,2023 Arm Limited. * * SPDX-License-Identifier: MIT * @@ -29,10 +29,11 @@ #include "src/common/utils/Object.h" #include <atomic> +#include <tuple> struct AclContext_ { - arm_compute::detail::Header header{ arm_compute::detail::ObjectType::Context, nullptr }; + arm_compute::detail::Header header{arm_compute::detail::ObjectType::Context, nullptr}; protected: AclContext_() = default; @@ -44,22 +45,20 @@ namespace arm_compute // Forward declarations class ITensorV2; class IQueue; +class IOperator; /**< Context interface */ class IContext : public AclContext_ { public: - IContext(Target target) - : AclContext_(), _target(target), _refcount(0) + IContext(Target target) : AclContext_(), _target(target), _refcount(0) { } - /** Virtual Destructor */ virtual ~IContext() { header.type = detail::ObjectType::Invalid; }; - /** Target type accessor * * @return Target that the context is associated with @@ -68,19 +67,16 @@ public: { return _target; } - /** Increment context refcount */ void inc_ref() const { ++_refcount; } - /** Decrement context refcount */ void dec_ref() const { --_refcount; } - /** Reference counter accessor * * @return The number of references pointing to this object @@ -89,7 +85,6 @@ public: { return _refcount; } - /** Checks if an object is valid * * @return True if sucessful otherwise false @@ -98,7 +93,6 @@ public: { return header.type == detail::ObjectType::Context; } - /** Create a tensor object * * @param[in] desc Descriptor to use @@ -107,14 +101,17 @@ public: * @return A pointer to the created tensor object */ virtual ITensorV2 *create_tensor(const AclTensorDescriptor &desc, bool allocate) = 0; - /** Create a queue object * * @param[in] options Queue options to be used * * @return A pointer to the created queue object */ - virtual IQueue *create_queue(const AclQueueOptions *options) = 0; + virtual IQueue *create_queue(const AclQueueOptions *options) = 0; + virtual std::tuple<IOperator *, StatusCode> create_activation(const AclTensorDescriptor &src, + const AclTensorDescriptor &dst, + const AclActivationDescriptor &act, + bool is_validate) = 0; private: Target _target; /**< Target type of context */ @@ -142,7 +139,7 @@ namespace detail */ inline StatusCode validate_internal_context(const IContext *ctx) { - if(ctx == nullptr || !ctx->is_valid()) + if (ctx == nullptr || !ctx->is_valid()) { ARM_COMPUTE_LOG_ERROR_ACL("Invalid context object"); return StatusCode::InvalidArgument; diff --git a/src/common/cpuinfo/target/CpuInfoSveUtils.cpp b/src/common/IOperator.cpp index 750a1b01d1..90e3473814 100644 --- a/src/common/cpuinfo/target/CpuInfoSveUtils.cpp +++ b/src/common/IOperator.cpp @@ -21,20 +21,53 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -#include "src/common/cpuinfo/target/CpuInfoSveUtils.h" +#include "src/common/IOperator.h" + +#include "src/common/utils/Validate.h" namespace arm_compute { -namespace cpuinfo +#ifndef DOXYGEN_SKIP_THIS +IOperator::IOperator(IContext *ctx) : AclOperator_() +{ + ARM_COMPUTE_ASSERT_NOT_NULLPTR(ctx); + this->header.ctx = ctx; + this->header.ctx->inc_ref(); +} + +IOperator::~IOperator() +{ + this->header.ctx->dec_ref(); + this->header.type = detail::ObjectType::Invalid; +} + +bool IOperator::is_valid() const +{ + return this->header.type == detail::ObjectType::Operator; +} + +StatusCode IOperator::run(ITensorPack &tensors) +{ + _op->run(tensors); + return StatusCode::Success; +} + +StatusCode IOperator::run(IQueue &queue, ITensorPack &tensors) { -uint64_t get_sve_feature_reg() + ARM_COMPUTE_UNUSED(queue); + _op->run(tensors); + return StatusCode::Success; +} + +StatusCode IOperator::prepare(ITensorPack &tensors) +{ + _op->prepare(tensors); + return StatusCode::Success; +} + +MemoryRequirements IOperator::workspace() const { - uint64_t reg = 0; -#if defined(ENABLE_SVE) - __asm __volatile("MRS %0, ID_AA64ZFR0_EL1" - : "=r"(reg)); -#endif /* defined(DENABLE_SVE) */ - return reg; + return _op->workspace(); } -} // namespace cpuinfo +#endif /* DOXYGEN_SKIP_THIS */ } // namespace arm_compute diff --git a/src/common/IOperator.h b/src/common/IOperator.h new file mode 100644 index 0000000000..e86e11fe25 --- /dev/null +++ b/src/common/IOperator.h @@ -0,0 +1,137 @@ +/* + * 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 SRC_COMMON_IOPERATOR_H_ +#define SRC_COMMON_IOPERATOR_H_ + +#include "src/common/IContext.h" +#include "src/common/IQueue.h" + +// TODO: Remove when all functions have been ported +#include "arm_compute/core/experimental/Types.h" +#include "arm_compute/runtime/IOperator.h" + +#include "src/common/utils/Validate.h" + +#include <vector> + +struct AclOperator_ +{ + arm_compute::detail::Header header{arm_compute::detail::ObjectType::Operator, nullptr}; + +protected: + AclOperator_() = default; + ~AclOperator_() = default; +}; + +namespace arm_compute +{ +// Forward declarations +class ITensorPack; +namespace experimental +{ +class IOperator; +} // namespace experimental + +using MemoryRequirements = experimental::MemoryRequirements; + +/** Base class specifying the operator interface */ +class IOperator : public AclOperator_ +{ +public: + /** Explict Operator Constructor + * + * @param[in] ctx Context to be used by the operator + */ + explicit IOperator(IContext *ctx); + /** Destructor */ + virtual ~IOperator(); + /** Checks if an operator is valid + * + * @return True if successful otherwise false + */ + bool is_valid() const; + /** Run the kernels contained in the function + * + * @param[in] queue Queue to use + * @param[in] tensors Vector that contains the tensors to operate on + */ + virtual StatusCode run(IQueue &queue, ITensorPack &tensors); + /** Run the kernels contained in the function + * + * @param[in] tensors Vector that contains the tensors to operate on + */ + virtual StatusCode run(ITensorPack &tensors); + /** Prepare the operator for execution + * + * Any one off pre-processing step required by the function is handled here + * + * @param[in] tensors Vector that contains the preparation tensors. + * + * @note Prepare stage might not need all the function's buffers' backing memory to be available in order to execute + */ + virtual StatusCode prepare(ITensorPack &tensors); + /** Return the memory requirements required by the workspace + */ + virtual MemoryRequirements workspace() const; + + void set_internal_operator(std::unique_ptr<experimental::IOperator> op) + { + _op = std::move(op); + } + +private: + std::unique_ptr<experimental::IOperator> _op{nullptr}; +}; + +/** Extract internal representation of an Operator + * + * @param[in] op Opaque operator pointer + * + * @return The internal representation as an IOperator + */ +inline IOperator *get_internal(AclOperator op) +{ + return static_cast<IOperator *>(op); +} + +namespace detail +{ +/** Check if an internal operator is valid + * + * @param[in] op Internal operator to check + * + * @return A status code + */ +inline StatusCode validate_internal_operator(const IOperator *op) +{ + if (op == nullptr || !op->is_valid()) + { + ARM_COMPUTE_LOG_ERROR_ACL("[IOperator]: Invalid operator object"); + return StatusCode::InvalidArgument; + } + return StatusCode::Success; +} +} // namespace detail +} // namespace arm_compute +#endif /* SRC_COMMON_IOPERATOR_H_ */ diff --git a/src/common/IQueue.h b/src/common/IQueue.h index 6a0cbc75da..60745d206e 100644 --- a/src/common/IQueue.h +++ b/src/common/IQueue.h @@ -28,7 +28,7 @@ struct AclQueue_ { - arm_compute::detail::Header header{ arm_compute::detail::ObjectType::Queue, nullptr }; + arm_compute::detail::Header header{arm_compute::detail::ObjectType::Queue, nullptr}; protected: AclQueue_() = default; @@ -88,7 +88,7 @@ namespace detail */ inline StatusCode validate_internal_queue(const IQueue *queue) { - if(queue == nullptr || !queue->is_valid()) + if (queue == nullptr || !queue->is_valid()) { ARM_COMPUTE_LOG_ERROR_ACL("[IQueue]: Invalid queue object"); return StatusCode::InvalidArgument; diff --git a/src/common/ITensorV2.cpp b/src/common/ITensorV2.cpp index 39bf1c6fb3..bf3d963926 100644 --- a/src/common/ITensorV2.cpp +++ b/src/common/ITensorV2.cpp @@ -22,7 +22,9 @@ * SOFTWARE. */ #include "src/common/ITensorV2.h" + #include "arm_compute/core/TensorInfo.h" + #include "src/common/utils/LegacySupport.h" namespace arm_compute @@ -36,4 +38,4 @@ AclTensorDescriptor ITensorV2::get_descriptor() const { return detail::convert_to_descriptor(*tensor()->info()); } -} // namespace arm_compute
\ No newline at end of file +} // namespace arm_compute diff --git a/src/common/ITensorV2.h b/src/common/ITensorV2.h index 965aacea23..903bfad66a 100644 --- a/src/common/ITensorV2.h +++ b/src/common/ITensorV2.h @@ -29,7 +29,7 @@ struct AclTensor_ { - arm_compute::detail::Header header{ arm_compute::detail::ObjectType::Tensor, nullptr }; + arm_compute::detail::Header header{arm_compute::detail::ObjectType::Tensor, nullptr}; protected: AclTensor_() = default; @@ -49,8 +49,7 @@ public: * * @param[in] ctx Context to be used by the operator */ - explicit ITensorV2(IContext *ctx) - : AclTensor_() + explicit ITensorV2(IContext *ctx) : AclTensor_() { ARM_COMPUTE_ASSERT_NOT_NULLPTR(ctx); this->header.ctx = ctx; @@ -128,7 +127,7 @@ namespace detail */ inline StatusCode validate_internal_tensor(const ITensorV2 *tensor) { - if(tensor == nullptr || !tensor->is_valid()) + if (tensor == nullptr || !tensor->is_valid()) { ARM_COMPUTE_LOG_ERROR_ACL("[ITensorV2]: Invalid tensor object"); return StatusCode::InvalidArgument; diff --git a/src/common/TensorPack.cpp b/src/common/TensorPack.cpp index 6c2c7f9622..b51fc0bdd8 100644 --- a/src/common/TensorPack.cpp +++ b/src/common/TensorPack.cpp @@ -22,13 +22,13 @@ * SOFTWARE. */ #include "src/common/TensorPack.h" + #include "src/common/ITensorV2.h" #include "src/common/utils/Validate.h" namespace arm_compute { -TensorPack::TensorPack(IContext *ctx) - : AclTensorPack_(), _pack() +TensorPack::TensorPack(IContext *ctx) : AclTensorPack_(), _pack() { ARM_COMPUTE_ASSERT_NOT_NULLPTR(ctx); this->header.ctx = ctx; diff --git a/src/common/TensorPack.h b/src/common/TensorPack.h index f330eee740..b3d1624dae 100644 --- a/src/common/TensorPack.h +++ b/src/common/TensorPack.h @@ -25,11 +25,12 @@ #define SRC_COMMON_ITENSORPACK_H_ #include "arm_compute/core/ITensorPack.h" + #include "src/common/IContext.h" struct AclTensorPack_ { - arm_compute::detail::Header header{ arm_compute::detail::ObjectType::TensorPack, nullptr }; + arm_compute::detail::Header header{arm_compute::detail::ObjectType::TensorPack, nullptr}; protected: AclTensorPack_() = default; @@ -118,7 +119,7 @@ namespace detail */ inline StatusCode validate_internal_pack(const TensorPack *pack) { - if(pack == nullptr || !pack->is_valid()) + if (pack == nullptr || !pack->is_valid()) { ARM_COMPUTE_LOG_ERROR_ACL("[TensorPack]: Invalid tensor pack object"); return StatusCode::InvalidArgument; diff --git a/src/common/Types.h b/src/common/Types.h index ba07b51d55..25ee32353a 100644 --- a/src/common/Types.h +++ b/src/common/Types.h @@ -24,6 +24,7 @@ #ifndef SRC_COMMON_TYPES_H_ #define SRC_COMMON_TYPES_H_ +#include "arm_compute/AclDescriptors.h" #include "arm_compute/AclTypes.h" namespace arm_compute diff --git a/src/common/cpuinfo/CpuInfo.cpp b/src/common/cpuinfo/CpuInfo.cpp index 436e7ea803..92ba5223c9 100644 --- a/src/common/cpuinfo/CpuInfo.cpp +++ b/src/common/cpuinfo/CpuInfo.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Arm Limited. + * Copyright (c) 2021-2024 Arm Limited. * * SPDX-License-Identifier: MIT * @@ -25,37 +25,46 @@ #include "arm_compute/core/Error.h" #include "arm_compute/core/Log.h" -#include "src/common/cpuinfo/target/CpuInfoSveUtils.h" + #include "support/StringSupport.h" #include "support/ToolchainSupport.h" +#include <map> #include <sstream> #if !defined(BARE_METAL) #include <algorithm> #include <cstring> #include <fstream> +#if !defined(_WIN64) #include <regex.h> /* C++ std::regex takes up a lot of space in the standalone builds */ #include <sched.h> +#endif /* !defined(_WIN64) */ + #include <thread> #include <unordered_map> #endif /* !defined(BARE_METAL) */ -#if !defined(BARE_METAL) && !defined(__APPLE__) && (defined(__arm__) || defined(__aarch64__)) +#if !defined(_WIN64) +#if !defined(BARE_METAL) && !defined(__APPLE__) && !defined(__OpenBSD__) && (defined(__arm__) || defined(__aarch64__)) #include <asm/hwcap.h> /* Get HWCAP bits from asm/hwcap.h */ #include <sys/auxv.h> -#endif /* !defined(BARE_METAL) && !defined(__APPLE__) && (defined(__arm__) || defined(__aarch64__)) */ - -#define ARM_COMPUTE_CPU_FEATURE_HWCAP_CPUID (1 << 11) -#define ARM_COMPUTE_GET_FEATURE_REG(var, freg) __asm __volatile("MRS %0, " #freg \ - : "=r"(var)) +#elif defined(__APPLE__) && defined(__aarch64__) +#include <sys/sysctl.h> +#include <sys/types.h> +#endif /* defined(__APPLE__) && defined(__aarch64__)) */ +#endif /* !defined(BARE_METAL) && !defined(__APPLE__) && !defined(__OpenBSD__) && (defined(__arm__) || defined(__aarch64__)) */ + +#define ARM_COMPUTE_CPU_FEATURE_HWCAP_CPUID (1 << 11) +#define ARM_COMPUTE_GET_FEATURE_REG(var, freg) __asm __volatile("MRS %0, " #freg : "=r"(var)) namespace arm_compute { namespace cpuinfo { namespace { -#if !defined(BARE_METAL) && !defined(__APPLE__) && (defined(__arm__) || defined(__aarch64__)) +#if !defined(_WIN64) && !defined(BARE_METAL) && !defined(__APPLE__) && !defined(__OpenBSD__) && \ + (defined(__arm__) || defined(__aarch64__)) /** Extract MIDR using CPUID information that are exposed to user-space * * @param[in] max_num_cpus Maximum number of possible CPUs @@ -65,15 +74,15 @@ namespace std::vector<uint32_t> midr_from_cpuid(uint32_t max_num_cpus) { std::vector<uint32_t> cpus; - for(unsigned int i = 0; i < max_num_cpus; ++i) + for (unsigned int i = 0; i < max_num_cpus; ++i) { std::stringstream str; str << "/sys/devices/system/cpu/cpu" << i << "/regs/identification/midr_el1"; std::ifstream file(str.str(), std::ios::in); - if(file.is_open()) + if (file.is_open()) { std::string line; - if(bool(getline(file, line))) + if (bool(getline(file, line))) { cpus.emplace_back(support::cpp11::stoul(line, nullptr, support::cpp11::NumericBase::BASE_16)); } @@ -115,34 +124,35 @@ std::vector<uint32_t> midr_from_proc_cpuinfo(int max_num_cpus) ARM_COMPUTE_ERROR_ON_MSG(ret_status != 0, "Regex compilation failed."); std::ifstream file("/proc/cpuinfo", std::ios::in); - if(file.is_open()) + if (file.is_open()) { std::string line; int midr = 0; int curcpu = -1; - while(bool(getline(file, line))) + while (bool(getline(file, line))) { std::array<regmatch_t, 2> match; ret_status = regexec(&proc_regex, line.c_str(), 2, match.data(), 0); - if(ret_status == 0) + if (ret_status == 0) { std::string id = line.substr(match[1].rm_so, (match[1].rm_eo - match[1].rm_so)); int newcpu = support::cpp11::stoi(id, nullptr); - if(curcpu >= 0 && midr == 0) + if (curcpu >= 0 && midr == 0) { // Matched a new CPU ID without any description of the previous one - looks like old format. return {}; } - if(curcpu >= 0 && curcpu < max_num_cpus) + if (curcpu >= 0 && curcpu < max_num_cpus) { cpus.emplace_back(midr); } else { - ARM_COMPUTE_LOG_INFO_MSG_CORE("Trying to populate a core id with id greater than the expected number of cores!"); + ARM_COMPUTE_LOG_INFO_MSG_CORE( + "Trying to populate a core id with id greater than the expected number of cores!"); } midr = 0; @@ -152,7 +162,7 @@ std::vector<uint32_t> midr_from_proc_cpuinfo(int max_num_cpus) } ret_status = regexec(&imp_regex, line.c_str(), 2, match.data(), 0); - if(ret_status == 0) + if (ret_status == 0) { std::string subexp = line.substr(match[1].rm_so, (match[1].rm_eo - match[1].rm_so)); int impv = support::cpp11::stoi(subexp, nullptr, support::cpp11::NumericBase::BASE_16); @@ -162,7 +172,7 @@ std::vector<uint32_t> midr_from_proc_cpuinfo(int max_num_cpus) } ret_status = regexec(&var_regex, line.c_str(), 2, match.data(), 0); - if(ret_status == 0) + if (ret_status == 0) { std::string subexp = line.substr(match[1].rm_so, (match[1].rm_eo - match[1].rm_so)); int varv = support::cpp11::stoi(subexp, nullptr, support::cpp11::NumericBase::BASE_16); @@ -172,7 +182,7 @@ std::vector<uint32_t> midr_from_proc_cpuinfo(int max_num_cpus) } ret_status = regexec(&part_regex, line.c_str(), 2, match.data(), 0); - if(ret_status == 0) + if (ret_status == 0) { std::string subexp = line.substr(match[1].rm_so, (match[1].rm_eo - match[1].rm_so)); int partv = support::cpp11::stoi(subexp, nullptr, support::cpp11::NumericBase::BASE_16); @@ -182,7 +192,7 @@ std::vector<uint32_t> midr_from_proc_cpuinfo(int max_num_cpus) } ret_status = regexec(&rev_regex, line.c_str(), 2, match.data(), 0); - if(ret_status == 0) + if (ret_status == 0) { std::string subexp = line.substr(match[1].rm_so, (match[1].rm_eo - match[1].rm_so)); int regv = support::cpp11::stoi(subexp, nullptr); @@ -193,13 +203,14 @@ std::vector<uint32_t> midr_from_proc_cpuinfo(int max_num_cpus) } } - if(curcpu >= 0 && curcpu < max_num_cpus) + if (curcpu >= 0 && curcpu < max_num_cpus) { cpus.emplace_back(midr); } else { - ARM_COMPUTE_LOG_INFO_MSG_CORE("Trying to populate a core id with id greater than the expected number of cores!"); + ARM_COMPUTE_LOG_INFO_MSG_CORE( + "Trying to populate a core id with id greater than the expected number of cores!"); } } @@ -224,11 +235,11 @@ int get_max_cpus() CPUspresent.open("/sys/devices/system/cpu/present", std::ios::in); bool success = false; - if(CPUspresent.is_open()) + if (CPUspresent.is_open()) { std::string line; - if(bool(getline(CPUspresent, line))) + if (bool(getline(CPUspresent, line))) { /* The content of this file is a list of ranges or single values, e.g. * 0-5, or 1-3,5,7 or similar. As we are interested in the @@ -237,9 +248,9 @@ int get_max_cpus() */ auto startfrom = line.begin(); - for(auto i = line.begin(); i < line.end(); ++i) + for (auto i = line.begin(); i < line.end(); ++i) { - if(*i == '-' || *i == ',') + if (*i == '-' || *i == ',') { startfrom = i + 1; } @@ -253,38 +264,145 @@ int get_max_cpus() } // Return std::thread::hardware_concurrency() as a fallback. - if(!success) + if (!success) { max_cpus = std::thread::hardware_concurrency(); } return max_cpus; } -#endif /* !defined(BARE_METAL) && !defined(__APPLE__) && (defined(__arm__) || defined(__aarch64__)) */ + +const static std::map<std::string, std::vector<uint32_t>> known_configurations_with_little_cores = { + {"xiaomi14-pro", {379, 379, 923, 923, 923, 867, 867, 1024}}}; + +const static std::map<std::string, uint32_t> number_of_cores_to_use = {{"xiaomi14-pro", 6}}; + +#if defined(__ANDROID__) +std::vector<uint32_t> get_cpu_capacities() +{ + std::vector<uint32_t> cpu_capacities; + for (int i = 0; i < get_max_cpus(); ++i) + { + std::stringstream str; + str << "/sys/devices/system/cpu/cpu" << i << "/cpu_capacity"; + std::ifstream file(str.str(), std::ios::in); + if (file.is_open()) + { + std::string line; + if (bool(getline(file, line))) + { + cpu_capacities.emplace_back(support::cpp11::stoul(line)); + } + } + } + + return cpu_capacities; +} + +uint32_t not_little_num_cpus_internal() +{ + std::vector<uint32_t> cpus_all = get_cpu_capacities(); + std::vector<uint32_t> cpus_not_little; + + for (auto &it : known_configurations_with_little_cores) + { + if (it.second == cpus_all) + { + return number_of_cores_to_use.find(it.first)->second; + } + } + + std::vector<uint32_t>::iterator result = std::max_element(cpus_all.begin(), cpus_all.end()); + uint32_t max_capacity = *result; + uint32_t threshold = max_capacity / 2; + for (unsigned int i = 0; i < cpus_all.size(); i++) + { + if (!(cpus_all[i] < threshold)) + { + cpus_not_little.emplace_back(cpus_all[i]); + } + } + return cpus_not_little.size(); +} + +bool has_little_mid_big_internal() +{ + std::vector<uint32_t> cpus_all = get_cpu_capacities(); + std::vector<uint32_t> cpus_not_little; + + for (auto &it : known_configurations_with_little_cores) + { + if (it.second == cpus_all) + { + return true; + } + } + std::sort(cpus_all.begin(), cpus_all.end()); + std::vector<uint32_t>::iterator ip; + ip = std::unique(cpus_all.begin(), cpus_all.end()); + cpus_all.resize(std::distance(cpus_all.begin(), ip)); + + if (cpus_all.size() == 3) + { + return true; + } + else + { + return false; + } +} +#endif /* defined(__ANDROID__) */ +#elif defined(__aarch64__) && \ + defined(__APPLE__) /* !defined(BARE_METAL) && !defined(__APPLE__) && (defined(__arm__) || defined(__aarch64__)) */ +/** Query features through sysctlbyname + * + * @return int value queried + */ +int get_hw_capability(const std::string &cap) +{ + int64_t result(0); + size_t size = sizeof(result); + sysctlbyname(cap.c_str(), &result, &size, NULL, 0); + return result; +} +#endif /* !defined(BARE_METAL) && !defined(__APPLE__) && !defined(__OpenBSD__) && (defined(__arm__) || defined(__aarch64__)) */ + +#if defined(BARE_METAL) && defined(__aarch64__) +uint64_t get_sve_feature_reg() +{ + uint64_t svefr0 = 0; + __asm __volatile(".inst 0xd5380483 // mrs x3, ID_AA64ZFR0_EL1\n" + "MOV %0, X3" + : "=r"(svefr0) + : + : "x3"); + return svefr0; +} +#endif /* defined(BARE_METAL) && defined(__aarch64__) */ } // namespace -CpuInfo::CpuInfo(CpuIsaInfo isa, std::vector<CpuModel> cpus) - : _isa(std::move(isa)), _cpus(std::move(cpus)) +CpuInfo::CpuInfo(CpuIsaInfo isa, std::vector<CpuModel> cpus) : _isa(std::move(isa)), _cpus(std::move(cpus)) { } CpuInfo CpuInfo::build() { -#if !defined(BARE_METAL) && !defined(__APPLE__) && (defined(__arm__) || defined(__aarch64__)) +#if !defined(_WIN64) && !defined(BARE_METAL) && !defined(__APPLE__) && !defined(__OpenBSD__) && \ + (defined(__arm__) || defined(__aarch64__)) const uint32_t hwcaps = getauxval(AT_HWCAP); const uint32_t hwcaps2 = getauxval(AT_HWCAP2); const uint32_t max_cpus = get_max_cpus(); // Populate midr values std::vector<uint32_t> cpus_midr; - if(hwcaps & ARM_COMPUTE_CPU_FEATURE_HWCAP_CPUID) + if (hwcaps & ARM_COMPUTE_CPU_FEATURE_HWCAP_CPUID) { cpus_midr = midr_from_cpuid(max_cpus); } - if(cpus_midr.empty()) + if (cpus_midr.empty()) { cpus_midr = midr_from_proc_cpuinfo(max_cpus); } - if(cpus_midr.empty()) + if (cpus_midr.empty()) { cpus_midr.resize(max_cpus, 0); } @@ -300,32 +418,51 @@ CpuInfo CpuInfo::build() CpuInfo info(isa, cpus_model); return info; -#elif(BARE_METAL) && defined(__aarch64__) /* !defined(BARE_METAL) && !defined(__APPLE__) && (defined(__arm__) || defined(__aarch64__)) */ +#elif (BARE_METAL) && \ + defined( \ + __aarch64__) /* !defined(BARE_METAL) && !defined(__APPLE__) && !defined(__OpenBSD__) && (defined(__arm__) || defined(__aarch64__)) */ // Assume single CPU in bare metal mode. Just read the ID register and feature bits directly. - uint64_t isar0 = 0, isar1 = 0, pfr0 = 0, svefr0 = 0, midr = 0; + uint64_t isar0 = 0, isar1 = 0, pfr0 = 0, pfr1 = 0, svefr0 = 0, midr = 0; ARM_COMPUTE_GET_FEATURE_REG(isar0, ID_AA64ISAR0_EL1); ARM_COMPUTE_GET_FEATURE_REG(isar1, ID_AA64ISAR1_EL1); ARM_COMPUTE_GET_FEATURE_REG(pfr0, ID_AA64PFR0_EL1); + ARM_COMPUTE_GET_FEATURE_REG(pfr1, ID_AA64PFR1_EL1); ARM_COMPUTE_GET_FEATURE_REG(midr, MIDR_EL1); - if((pfr0 >> 32) & 0xf) + if ((pfr0 >> 32) & 0xf) { svefr0 = get_sve_feature_reg(); } - CpuIsaInfo isa = init_cpu_isa_from_regs(isar0, isar1, pfr0, svefr0, midr); + CpuIsaInfo isa = init_cpu_isa_from_regs(isar0, isar1, pfr0, pfr1, svefr0, midr); std::vector<CpuModel> cpus_model(1, midr_to_model(midr)); CpuInfo info(isa, cpus_model); return info; -#else /* #elif(BARE_METAL) && defined(__aarch64__) */ - CpuInfo info(CpuIsaInfo(), { CpuModel::GENERIC }); +#elif defined(__aarch64__) && defined(__APPLE__) /* #elif(BARE_METAL) && defined(__aarch64__) */ + int ncpus = get_hw_capability("hw.perflevel0.logicalcpu"); + CpuIsaInfo isainfo; + std::vector<CpuModel> cpus_model(ncpus); + isainfo.neon = get_hw_capability("hw.optional.neon"); + isainfo.fp16 = get_hw_capability("hw.optional.neon_fp16"); + isainfo.dot = get_hw_capability("hw.optional.arm.FEAT_DotProd"); + isainfo.bf16 = get_hw_capability("hw.optional.arm.FEAT_BF16"); + isainfo.i8mm = get_hw_capability("hw.optional.arm.FEAT_I8MM"); + CpuInfo info(isainfo, cpus_model); return info; -#endif /* !defined(BARE_METAL) && !defined(__APPLE__) && (defined(__arm__) || defined(__aarch64__)) */ +#elif defined(__aarch64__) && defined(_WIN64) /* #elif defined(__aarch64__) && defined(__APPLE__) */ + CpuIsaInfo isainfo; + isainfo.neon = true; + CpuInfo info(isainfo, {CpuModel::GENERIC}); + return info; +#else /* #elif defined(__aarch64__) && defined(_WIN64) */ + CpuInfo info(CpuIsaInfo(), {CpuModel::GENERIC}); + return info; +#endif /* !defined(BARE_METAL) && !defined(__APPLE__) && !defined(__OpenBSD__) && (defined(__arm__) || defined(__aarch64__)) */ } CpuModel CpuInfo::cpu_model(uint32_t cpuid) const { - if(cpuid < _cpus.size()) + if (cpuid < _cpus.size()) { return _cpus[cpuid]; } @@ -334,11 +471,12 @@ CpuModel CpuInfo::cpu_model(uint32_t cpuid) const CpuModel CpuInfo::cpu_model() const { -#if defined(BARE_METAL) || defined(__APPLE__) || (!defined(__arm__) && !defined(__aarch64__)) +#if defined(_WIN64) || defined(BARE_METAL) || defined(__APPLE__) || defined(__OpenBSD__) || \ + (!defined(__arm__) && !defined(__aarch64__)) return cpu_model(0); -#else /* defined(BARE_METAL) || defined(__APPLE__) || (!defined(__arm__) && !defined(__aarch64__)) */ +#else /* defined(BARE_METAL) || defined(__APPLE__) || defined(__OpenBSD__) || (!defined(__arm__) && !defined(__aarch64__)) */ return cpu_model(sched_getcpu()); -#endif /* defined(BARE_METAL) || defined(__APPLE__) || (!defined(__arm__) && !defined(__aarch64__)) */ +#endif /* defined(BARE_METAL) || defined(__APPLE__) || defined(__OpenBSD__) || (!defined(__arm__) && !defined(__aarch64__)) */ } uint32_t CpuInfo::num_cpus() const @@ -346,11 +484,29 @@ uint32_t CpuInfo::num_cpus() const return _cpus.size(); } +uint32_t CpuInfo::not_little_num_cpus() const +{ +#if defined(__ANDROID__) + return not_little_num_cpus_internal(); +#else /* defined(__ANDROID__) */ + return num_cpus(); +#endif /* defined(__ANDROID__) */ +} + +bool CpuInfo::has_little_mid_big() const +{ +#if defined(__ANDROID__) + return has_little_mid_big_internal(); +#else /* defined(__ANDROID__) */ + return false; +#endif /* defined(__ANDROID__) */ +} + uint32_t num_threads_hint() { unsigned int num_threads_hint = 1; -#if !defined(BARE_METAL) +#if !defined(BARE_METAL) && !defined(_WIN64) && !defined(ARM_COMPUTE_DISABLE_THREADS_HINT) std::vector<std::string> cpus; cpus.reserve(64); @@ -363,13 +519,13 @@ uint32_t num_threads_hint() // Read cpuinfo and get occurrence of each core std::ifstream cpuinfo_file("/proc/cpuinfo", std::ios::in); - if(cpuinfo_file.is_open()) + if (cpuinfo_file.is_open()) { std::string line; - while(bool(getline(cpuinfo_file, line))) + while (bool(getline(cpuinfo_file, line))) { std::array<regmatch_t, 2> match; - if(regexec(&cpu_part_rgx, line.c_str(), 2, match.data(), 0) == 0) + if (regexec(&cpu_part_rgx, line.c_str(), 2, match.data(), 0) == 0) { cpus.emplace_back(line.substr(match[1].rm_so, (match[1].rm_eo - match[1].rm_so))); } @@ -382,13 +538,13 @@ uint32_t num_threads_hint() auto least_frequent_cpu_occurences = [](const std::vector<std::string> &cpus) -> uint32_t { std::unordered_map<std::string, uint32_t> cpus_freq; - for(const auto &cpu : cpus) + for (const auto &cpu : cpus) { cpus_freq[cpu]++; } uint32_t vmin = cpus.size() + 1; - for(const auto &cpu_freq : cpus_freq) + for (const auto &cpu_freq : cpus_freq) { vmin = std::min(vmin, cpu_freq.second); } @@ -397,9 +553,9 @@ uint32_t num_threads_hint() // Set thread hint num_threads_hint = cpus.empty() ? std::thread::hardware_concurrency() : least_frequent_cpu_occurences(cpus); -#endif /* !defined(BARE_METAL) */ +#endif /* !defined(BARE_METAL) && !defined(_WIN64) && !defined(ARM_COMPUTE_DISABLE_THREADS_HINT) */ return num_threads_hint; } } // namespace cpuinfo -} // namespace arm_compute
\ No newline at end of file +} // namespace arm_compute diff --git a/src/common/cpuinfo/CpuInfo.h b/src/common/cpuinfo/CpuInfo.h index f3056d2faf..506830aa81 100644 --- a/src/common/cpuinfo/CpuInfo.h +++ b/src/common/cpuinfo/CpuInfo.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Arm Limited. + * Copyright (c) 2021-2022, 2024 Arm Limited. * * SPDX-License-Identifier: MIT * @@ -21,8 +21,8 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -#ifndef SRC_COMMON_CPUINFO_H -#define SRC_COMMON_CPUINFO_H +#ifndef ACL_SRC_COMMON_CPUINFO_CPUINFO_H +#define ACL_SRC_COMMON_CPUINFO_CPUINFO_H #include "src/common/cpuinfo/CpuIsaInfo.h" #include "src/common/cpuinfo/CpuModel.h" @@ -71,6 +71,14 @@ public: { return _isa.sve2; } + bool has_sme() const + { + return _isa.sme; + } + bool has_sme2() const + { + return _isa.sme2; + } bool has_fp16() const { return _isa.fp16; @@ -79,22 +87,41 @@ public: { return _isa.bf16; } + bool has_svebf16() const + { + return _isa.svebf16; + } bool has_dotprod() const { return _isa.dot; } - bool has_immla() const + bool has_i8mm() const + { + return _isa.i8mm; + } + bool has_svei8mm() const + { + return _isa.svei8mm; + } + bool has_svef32mm() const + { + return _isa.svef32mm; + } + + const CpuIsaInfo &isa() const { - return _isa.immla; + return _isa; } - bool has_fmmla() const + const std::vector<CpuModel> &cpus() const { - return _isa.fmmla; + return _cpus; } CpuModel cpu_model(uint32_t cpuid) const; CpuModel cpu_model() const; uint32_t num_cpus() const; + uint32_t not_little_num_cpus() const; + bool has_little_mid_big() const; private: CpuIsaInfo _isa{}; @@ -110,4 +137,4 @@ private: uint32_t num_threads_hint(); } // namespace cpuinfo } // namespace arm_compute -#endif /* SRC_COMMON_CPUINFO_H */ +#endif // ACL_SRC_COMMON_CPUINFO_CPUINFO_H diff --git a/src/common/cpuinfo/CpuIsaInfo.cpp b/src/common/cpuinfo/CpuIsaInfo.cpp index d99f9aec29..c9e39b9a08 100644 --- a/src/common/cpuinfo/CpuIsaInfo.cpp +++ b/src/common/cpuinfo/CpuIsaInfo.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Arm Limited. + * Copyright (c) 2021-2022, 2024 Arm Limited. * * SPDX-License-Identifier: MIT * @@ -24,6 +24,7 @@ #include "src/common/cpuinfo/CpuIsaInfo.h" #include "arm_compute/core/Error.h" + #include "src/common/cpuinfo/CpuModel.h" /* Arm Feature flags */ @@ -31,17 +32,18 @@ #define ARM_COMPUTE_CPU_FEATURE_HWCAP_NEON (1 << 12) /* Arm64 Feature flags */ -#define ARM_COMPUTE_CPU_FEATURE_HWCAP_ASIMD (1 << 1) -#define ARM_COMPUTE_CPU_FEATURE_HWCAP_FPHP (1 << 9) -#define ARM_COMPUTE_CPU_FEATURE_HWCAP_ASIMDHP (1 << 10) -#define ARM_COMPUTE_CPU_FEATURE_HWCAP_ASIMDDP (1 << 20) -#define ARM_COMPUTE_CPU_FEATURE_HWCAP_SVE (1 << 22) -#define ARM_COMPUTE_CPU_FEATURE_HWCAP2_SVE2 (1 << 1) -#define ARM_COMPUTE_CPU_FEATURE_HWCAP2_SVEI8MM (1 << 9) +#define ARM_COMPUTE_CPU_FEATURE_HWCAP_ASIMD (1 << 1) +#define ARM_COMPUTE_CPU_FEATURE_HWCAP_FPHP (1 << 9) +#define ARM_COMPUTE_CPU_FEATURE_HWCAP_ASIMDHP (1 << 10) +#define ARM_COMPUTE_CPU_FEATURE_HWCAP_ASIMDDP (1 << 20) +#define ARM_COMPUTE_CPU_FEATURE_HWCAP_SVE (1 << 22) +#define ARM_COMPUTE_CPU_FEATURE_HWCAP2_SVE2 (1 << 1) +#define ARM_COMPUTE_CPU_FEATURE_HWCAP2_SVEI8MM (1 << 9) #define ARM_COMPUTE_CPU_FEATURE_HWCAP2_SVEF32MM (1 << 10) -#define ARM_COMPUTE_CPU_FEATURE_HWCAP2_SVEBF16 (1 << 12) -#define ARM_COMPUTE_CPU_FEATURE_HWCAP2_I8MM (1 << 13) -#define ARM_COMPUTE_CPU_FEATURE_HWCAP2_BF16 (1 << 14) +#define ARM_COMPUTE_CPU_FEATURE_HWCAP2_SVEBF16 (1 << 12) +#define ARM_COMPUTE_CPU_FEATURE_HWCAP2_I8MM (1 << 13) +#define ARM_COMPUTE_CPU_FEATURE_HWCAP2_BF16 (1 << 14) +#define ARM_COMPUTE_CPU_FEATURE_HWCAP2_SME (1 << 23) namespace arm_compute { @@ -49,61 +51,40 @@ namespace cpuinfo { namespace { +inline bool is_feature_supported(uint64_t features, uint64_t feature_mask) +{ + return (features & feature_mask); +} + #if defined(__arm__) void decode_hwcaps(CpuIsaInfo &isa, const uint32_t hwcaps, const uint32_t hwcaps2) { ARM_COMPUTE_UNUSED(hwcaps2); - - if(hwcaps & ARM_COMPUTE_CPU_FEATURE_HWCAP_HALF) - { - isa.fp16 = true; - } - if(hwcaps & ARM_COMPUTE_CPU_FEATURE_HWCAP_NEON) - { - isa.neon = true; - } + isa.fp16 = false; + isa.neon = is_feature_supported(hwcaps, ARM_COMPUTE_CPU_FEATURE_HWCAP_NEON); } #elif defined(__aarch64__) void decode_hwcaps(CpuIsaInfo &isa, const uint32_t hwcaps, const uint32_t hwcaps2) { // High-level SIMD support - if(hwcaps & ARM_COMPUTE_CPU_FEATURE_HWCAP_ASIMD) - { - isa.neon = true; - } - if(hwcaps & ARM_COMPUTE_CPU_FEATURE_HWCAP_SVE) - { - isa.sve = true; - } - if(hwcaps2 & ARM_COMPUTE_CPU_FEATURE_HWCAP2_SVE2) - { - isa.sve2 = true; - } + isa.neon = is_feature_supported(hwcaps, ARM_COMPUTE_CPU_FEATURE_HWCAP_ASIMD); + isa.sve = is_feature_supported(hwcaps, ARM_COMPUTE_CPU_FEATURE_HWCAP_SVE); + isa.sve2 = is_feature_supported(hwcaps2, ARM_COMPUTE_CPU_FEATURE_HWCAP2_SVE2); + + // Detection of SME from type HWCAP2 in the auxillary vector + isa.sme = is_feature_supported(hwcaps2, ARM_COMPUTE_CPU_FEATURE_HWCAP2_SME); + isa.sme2 = isa.sme; // Needs to be set properly // Data-type support - const uint32_t fp16_support_mask = ARM_COMPUTE_CPU_FEATURE_HWCAP_FPHP | ARM_COMPUTE_CPU_FEATURE_HWCAP_ASIMDHP; - if(hwcaps & fp16_support_mask) - { - isa.fp16 = true; - } - if(hwcaps2 & ARM_COMPUTE_CPU_FEATURE_HWCAP2_BF16) - { - isa.bf16 = true; - } + isa.fp16 = is_feature_supported(hwcaps, ARM_COMPUTE_CPU_FEATURE_HWCAP_FPHP | ARM_COMPUTE_CPU_FEATURE_HWCAP_ASIMDHP); + isa.bf16 = is_feature_supported(hwcaps2, ARM_COMPUTE_CPU_FEATURE_HWCAP2_BF16); + isa.svebf16 = is_feature_supported(hwcaps2, ARM_COMPUTE_CPU_FEATURE_HWCAP2_SVEBF16); // Instruction extensions - if(hwcaps & ARM_COMPUTE_CPU_FEATURE_HWCAP_ASIMDDP) - { - isa.dot = true; - } - if(hwcaps2 & ARM_COMPUTE_CPU_FEATURE_HWCAP2_I8MM) - { - isa.immla = true; - } - if(hwcaps2 & ARM_COMPUTE_CPU_FEATURE_HWCAP2_SVEF32MM) - { - isa.fmmla = true; - } + isa.dot = is_feature_supported(hwcaps, ARM_COMPUTE_CPU_FEATURE_HWCAP_ASIMDDP); + isa.i8mm = is_feature_supported(hwcaps2, ARM_COMPUTE_CPU_FEATURE_HWCAP2_I8MM); + isa.svei8mm = is_feature_supported(hwcaps2, ARM_COMPUTE_CPU_FEATURE_HWCAP2_SVEI8MM); + isa.svef32mm = is_feature_supported(hwcaps2, ARM_COMPUTE_CPU_FEATURE_HWCAP2_SVEF32MM); } #else /* defined(__aarch64__) */ void decode_hwcaps(CpuIsaInfo &isa, const uint32_t hwcaps, const uint32_t hwcaps2) @@ -112,62 +93,49 @@ void decode_hwcaps(CpuIsaInfo &isa, const uint32_t hwcaps, const uint32_t hwcaps } #endif /* defined(__aarch64__) */ -void decode_regs(CpuIsaInfo &isa, const uint64_t isar0, const uint64_t isar1, const uint64_t pfr0, const uint64_t svefr0) +void decode_regs(CpuIsaInfo &isa, + const uint64_t isar0, + const uint64_t isar1, + const uint64_t pfr0, + const uint64_t pfr1, + const uint64_t svefr0) { + auto is_supported = [](uint64_t feature_reg, uint8_t feature_pos) -> bool + { return ((feature_reg >> feature_pos) & 0xf); }; + // High-level SIMD support - if((pfr0 >> 32) & 0xf) - { - isa.sve = true; - } - if(svefr0 & 0xf) - { - isa.sve2 = true; - } + isa.sve = is_supported(pfr0, 32); + isa.sve2 = is_supported(svefr0, 0); + isa.sme = is_supported(pfr1, 24); + isa.sme2 = (((pfr1 >> 24) & 0xf) > 1); // Data-type support - if((pfr0 >> 16) & 0xf) - { - isa.fp16 = true; - } - if((isar1 >> 44) & 0xf) - { - isa.bf16 = true; - } + isa.fp16 = is_supported(pfr0, 16); + isa.bf16 = is_supported(isar1, 44); + isa.svebf16 = is_supported(svefr0, 20); // Instruction extensions - if((isar0 >> 44) & 0xf) - { - isa.dot = true; - } - if((isar1 >> 48) & 0xf) - { - isa.immla = true; - } - if((svefr0 >> 52) & 0xf) - { - isa.fmmla = true; - } + isa.dot = is_supported(isar0, 44); + isa.i8mm = is_supported(isar1, 48); + isa.svei8mm = is_supported(svefr0, 44); + isa.svef32mm = is_supported(svefr0, 52); } -/** Handle features from whitelisted models in case of problematic kernels +/** Handle features from allow-listed models in case of problematic kernels * * @param[in, out] isa ISA to update * @param[in] model CPU model type */ -void whitelisted_model_features(CpuIsaInfo &isa, CpuModel model) +void allowlisted_model_features(CpuIsaInfo &isa, CpuModel model) { - if(isa.dot == false) + if (isa.dot == false) { isa.dot = model_supports_dot(model); } - if(isa.fp16 == false) + if (isa.fp16 == false) { isa.fp16 = model_supports_fp16(model); } - if(isa.sve == false) - { - isa.sve = model_supports_sve(model); - } } } // namespace @@ -178,21 +146,22 @@ CpuIsaInfo init_cpu_isa_from_hwcaps(uint32_t hwcaps, uint32_t hwcaps2, uint32_t decode_hwcaps(isa, hwcaps, hwcaps2); const CpuModel model = midr_to_model(midr); - whitelisted_model_features(isa, model); + allowlisted_model_features(isa, model); return isa; } -CpuIsaInfo init_cpu_isa_from_regs(uint64_t isar0, uint64_t isar1, uint64_t pfr0, uint64_t svefr0, uint64_t midr) +CpuIsaInfo +init_cpu_isa_from_regs(uint64_t isar0, uint64_t isar1, uint64_t pfr0, uint64_t pfr1, uint64_t svefr0, uint64_t midr) { CpuIsaInfo isa; - decode_regs(isa, isar0, isar1, pfr0, svefr0); + decode_regs(isa, isar0, isar1, pfr0, pfr1, svefr0); const CpuModel model = midr_to_model(midr); - whitelisted_model_features(isa, model); + allowlisted_model_features(isa, model); return isa; } } // namespace cpuinfo -} // namespace arm_compute
\ No newline at end of file +} // namespace arm_compute diff --git a/src/common/cpuinfo/CpuIsaInfo.h b/src/common/cpuinfo/CpuIsaInfo.h index 1125f766dd..9d6bc07b67 100644 --- a/src/common/cpuinfo/CpuIsaInfo.h +++ b/src/common/cpuinfo/CpuIsaInfo.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Arm Limited. + * Copyright (c) 2021-2022 Arm Limited. * * SPDX-License-Identifier: MIT * @@ -37,18 +37,22 @@ namespace cpuinfo struct CpuIsaInfo { /* SIMD extension support */ - bool neon{ false }; - bool sve{ false }; - bool sve2{ false }; + bool neon{false}; + bool sve{false}; + bool sve2{false}; + bool sme{false}; + bool sme2{false}; /* Data-type extensions support */ - bool fp16{ false }; - bool bf16{ false }; + bool fp16{false}; + bool bf16{false}; + bool svebf16{false}; /* Instruction support */ - bool dot{ false }; - bool immla{ false }; - bool fmmla{ false }; + bool dot{false}; + bool i8mm{false}; + bool svei8mm{false}; + bool svef32mm{false}; }; /** Identify ISA related information through system information @@ -65,13 +69,15 @@ CpuIsaInfo init_cpu_isa_from_hwcaps(uint32_t hwcaps, uint32_t hwcaps2, uint32_t * * @param[in] isar0 Value of Instruction Set Attribute Register 0 (ID_AA64ISAR0_EL1) * @param[in] isar1 Value of Instruction Set Attribute Register 1 (ID_AA64ISAR1_EL1) - * @param[in] pfr0 Value of Processor Feature Register 0 (ID_AA64PFR0_EL1) + * @param[in] pfr0 Value of Processor Feature Register 0 (ID_AA64PFR0_EL1) + * @param[in] pfr1 Value of Processor Feature Register 1 (ID_AA64PFR1_EL1) * @param[in] svefr0 Value of SVE feature ID register 0 (ID_AA64ZFR0_EL1) * @param[in] midr Value of Main ID Register (MIDR) * * @return CpuIsaInfo A populated ISA feature structure */ -CpuIsaInfo init_cpu_isa_from_regs(uint64_t isar0, uint64_t isar1, uint64_t pfr0, uint64_t svefr0, uint64_t midr); +CpuIsaInfo +init_cpu_isa_from_regs(uint64_t isar0, uint64_t isar1, uint64_t pfr0, uint64_t pfr1, uint64_t svefr0, uint64_t midr); } // namespace cpuinfo } // namespace arm_compute diff --git a/src/common/cpuinfo/CpuModel.cpp b/src/common/cpuinfo/CpuModel.cpp index 9f4d5d1433..8c3f8a8faf 100644 --- a/src/common/cpuinfo/CpuModel.cpp +++ b/src/common/cpuinfo/CpuModel.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Arm Limited. + * Copyright (c) 2021-2023 Arm Limited. * * SPDX-License-Identifier: MIT * @@ -29,12 +29,12 @@ namespace cpuinfo { std::string cpu_model_to_string(CpuModel model) { - switch(model) + switch (model) { #define X(MODEL) \ -case CpuModel::MODEL: \ - return #MODEL; - ARM_COMPUTE_CPU_MODEL_LIST + case CpuModel::MODEL: \ + return #MODEL; + ARM_COMPUTE_CPU_MODEL_LIST #undef X default: { @@ -45,13 +45,16 @@ case CpuModel::MODEL: \ bool model_supports_fp16(CpuModel model) { - switch(model) + switch (model) { case CpuModel::GENERIC_FP16: case CpuModel::GENERIC_FP16_DOT: case CpuModel::A55r1: + case CpuModel::A510: case CpuModel::X1: - case CpuModel::KLEIN: + case CpuModel::V1: + case CpuModel::A64FX: + case CpuModel::N1: return true; default: return false; @@ -60,23 +63,14 @@ bool model_supports_fp16(CpuModel model) bool model_supports_dot(CpuModel model) { - switch(model) + switch (model) { case CpuModel::GENERIC_FP16_DOT: case CpuModel::A55r1: + case CpuModel::A510: case CpuModel::X1: - case CpuModel::KLEIN: - return true; - default: - return false; - } -} - -bool model_supports_sve(CpuModel model) -{ - switch(model) - { - case CpuModel::KLEIN: + case CpuModel::V1: + case CpuModel::N1: return true; default: return false; @@ -92,17 +86,17 @@ CpuModel midr_to_model(uint32_t midr) const int variant = (midr >> 20) & 0xF; const int cpunum = (midr >> 4) & 0xFFF; - if(implementer == 0x41) // Arm CPUs + // Only CPUs we have code paths for are detected. All other CPUs can be safely classed as "GENERIC" + if (implementer == 0x41) // Arm CPUs { - // Only CPUs we have code paths for are detected. All other CPUs can be safely classed as "GENERIC" - switch(cpunum) + switch (cpunum) { case 0xd03: // A53 case 0xd04: // A35 model = CpuModel::A53; break; case 0xd05: // A55 - if(variant != 0) + if (variant != 0) { model = CpuModel::A55r1; } @@ -115,7 +109,7 @@ CpuModel midr_to_model(uint32_t midr) model = CpuModel::A73; break; case 0xd0a: // A75 - if(variant != 0) + if (variant != 0) { model = CpuModel::GENERIC_FP16_DOT; } @@ -124,9 +118,11 @@ CpuModel midr_to_model(uint32_t midr) model = CpuModel::GENERIC_FP16; } break; + case 0xd0c: // N1 + model = CpuModel::N1; + break; case 0xd06: // A65 case 0xd0b: // A76 - case 0xd0c: // N1 case 0xd0d: // A77 case 0xd0e: // A76AE case 0xd41: // A78 @@ -134,21 +130,39 @@ CpuModel midr_to_model(uint32_t midr) case 0xd4a: // E1 model = CpuModel::GENERIC_FP16_DOT; break; + case 0xd40: // V1 + model = CpuModel::V1; + break; case 0xd44: // X1 model = CpuModel::X1; break; - case 0xd46: - model = CpuModel::KLEIN; + case 0xd46: // A510 + case 0xd80: // A520 + model = CpuModel::A510; + break; + case 0xd15: // R82 + model = CpuModel::A55r1; + break; + default: + model = CpuModel::GENERIC; + break; + } + } + else if (implementer == 0x46) + { + switch (cpunum) + { + case 0x001: // A64FX + model = CpuModel::A64FX; break; default: model = CpuModel::GENERIC; break; } } - else if(implementer == 0x48) + else if (implementer == 0x48) { - // Only CPUs we have code paths for are detected. All other CPUs can be safely classed as "GENERIC" - switch(cpunum) + switch (cpunum) { case 0xd40: // A76 model = CpuModel::GENERIC_FP16_DOT; @@ -158,10 +172,9 @@ CpuModel midr_to_model(uint32_t midr) break; } } - else if(implementer == 0x51) + else if (implementer == 0x51) { - // Only CPUs we have code paths for are detected. All other CPUs can be safely classed as "GENERIC" - switch(cpunum) + switch (cpunum) { case 0x800: // A73 model = CpuModel::A73; @@ -187,4 +200,4 @@ CpuModel midr_to_model(uint32_t midr) return model; } } // namespace cpuinfo -} // namespace arm_compute
\ No newline at end of file +} // namespace arm_compute diff --git a/src/common/cpuinfo/CpuModel.h b/src/common/cpuinfo/CpuModel.h index 071efc4b3f..3b9d9e3494 100644 --- a/src/common/cpuinfo/CpuModel.h +++ b/src/common/cpuinfo/CpuModel.h @@ -24,11 +24,11 @@ #ifndef SRC_COMMON_CPUINFO_CPUMODEL_H #define SRC_COMMON_CPUINFO_CPUMODEL_H +#include "arm_compute/core/CPP/CPPTypes.h" + #include <cstdint> #include <string> -#include "arm_compute/core/CPP/CPPTypes.h" - namespace arm_compute { namespace cpuinfo @@ -55,23 +55,15 @@ CpuModel midr_to_model(uint32_t midr); * * @note This is used in case of old kernel configurations where some capabilities are not exposed. * - * @param[in] model Model to check for whitelisted capabilities + * @param[in] model Model to check for allowlisted capabilities */ bool model_supports_fp16(CpuModel model); -/** Check if a model supports SVE - * - * @note This is used in case of old kernel configurations where some capabilities are not exposed. - * - * @param[in] model Model to check for whitelisted capabilities - */ -bool model_supports_sve(CpuModel model); - /** Check if a model supports dot product * * @note This is used in case of old kernel configurations where some capabilities are not exposed. * - * @param[in] model Model to check for whitelisted capabilities + * @param[in] model Model to check for allowlisted capabilities */ bool model_supports_dot(CpuModel model); } // namespace cpuinfo diff --git a/src/common/cpuinfo/target/CpuInfoSveUtils.h b/src/common/cpuinfo/target/CpuInfoSveUtils.h deleted file mode 100644 index 73862b131c..0000000000 --- a/src/common/cpuinfo/target/CpuInfoSveUtils.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * 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 SRC_COMMON_CPUINFO_TARGET_CPUINFO_SVE_UTILS_H -#define SRC_COMMON_CPUINFO_TARGET_CPUINFO_SVE_UTILS_H - -#include <cstdint> - -namespace arm_compute -{ -namespace cpuinfo -{ -/** Returns the contents of the SVE feature register (ID_AA64ZFR0_EL1) - * - * @return uint64_t The value of the register - */ -uint64_t get_sve_feature_reg(); -} // namespace cpuinfo -} // namespace arm_compute -#endif /* SRC_COMMON_CPUINFO_CPUISAINFO_H */ diff --git a/src/common/utils/LegacySupport.cpp b/src/common/utils/LegacySupport.cpp index 569b2abd89..102644227e 100644 --- a/src/common/utils/LegacySupport.cpp +++ b/src/common/utils/LegacySupport.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Arm Limited. + * Copyright (c) 2021, 2023 Arm Limited. * * SPDX-License-Identifier: MIT * @@ -23,6 +23,8 @@ */ #include "src/common/utils/LegacySupport.h" +#include "arm_compute/function_info/ActivationLayerInfo.h" + namespace arm_compute { namespace detail @@ -31,7 +33,7 @@ namespace { DataType convert_to_legacy_data_type(AclDataType data_type) { - switch(data_type) + switch (data_type) { case AclDataType::AclFloat32: return DataType::F32; @@ -46,7 +48,7 @@ DataType convert_to_legacy_data_type(AclDataType data_type) AclDataType convert_to_c_data_type(DataType data_type) { - switch(data_type) + switch (data_type) { case DataType::F32: return AclDataType::AclFloat32; @@ -62,7 +64,7 @@ AclDataType convert_to_c_data_type(DataType data_type) TensorShape create_legacy_tensor_shape(int32_t ndims, int32_t *shape) { TensorShape legacy_shape{}; - for(int32_t d = 0; d < ndims; ++d) + for (int32_t d = 0; d < ndims; ++d) { legacy_shape.set(d, shape[d], false); } @@ -71,14 +73,14 @@ TensorShape create_legacy_tensor_shape(int32_t ndims, int32_t *shape) int32_t *create_tensor_shape_array(const TensorInfo &info) { const auto num_dims = info.num_dimensions(); - if(num_dims <= 0) + if (num_dims <= 0) { return nullptr; } int32_t *shape_array = new int32_t[num_dims]; - for(size_t d = 0; d < num_dims; ++d) + for (size_t d = 0; d < num_dims; ++d) { shape_array[d] = info.tensor_shape()[d]; } @@ -90,22 +92,71 @@ int32_t *create_tensor_shape_array(const TensorInfo &info) TensorInfo convert_to_legacy_tensor_info(const AclTensorDescriptor &desc) { TensorInfo legacy_desc; - legacy_desc.init(create_legacy_tensor_shape(desc.ndims, desc.shape), 1, convert_to_legacy_data_type(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 - }; + 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; } + +ActivationLayerInfo convert_to_activation_info(const AclActivationDescriptor &desc) +{ + ActivationLayerInfo::ActivationFunction act; + switch (desc.type) + { + case AclActivationType::AclIdentity: + act = ActivationLayerInfo::ActivationFunction::IDENTITY; + break; + case AclActivationType::AclLogistic: + act = ActivationLayerInfo::ActivationFunction::LOGISTIC; + break; + case AclActivationType::AclTanh: + act = ActivationLayerInfo::ActivationFunction::TANH; + break; + case AclActivationType::AclRelu: + act = ActivationLayerInfo::ActivationFunction::RELU; + break; + case AclActivationType::AclBoundedRelu: + act = ActivationLayerInfo::ActivationFunction::BOUNDED_RELU; + break; + case AclActivationType::AclLuBoundedRelu: + act = ActivationLayerInfo::ActivationFunction::LU_BOUNDED_RELU; + break; + case AclActivationType::AclLeakyRelu: + act = ActivationLayerInfo::ActivationFunction::LEAKY_RELU; + break; + case AclActivationType::AclSoftRelu: + act = ActivationLayerInfo::ActivationFunction::SOFT_RELU; + break; + case AclActivationType::AclElu: + act = ActivationLayerInfo::ActivationFunction::ELU; + break; + case AclActivationType::AclAbs: + act = ActivationLayerInfo::ActivationFunction::ABS; + break; + case AclActivationType::AclSquare: + act = ActivationLayerInfo::ActivationFunction::SQUARE; + break; + case AclActivationType::AclSqrt: + act = ActivationLayerInfo::ActivationFunction::SQRT; + break; + case AclActivationType::AclLinear: + act = ActivationLayerInfo::ActivationFunction::LINEAR; + break; + case AclActivationType::AclHardSwish: + act = ActivationLayerInfo::ActivationFunction::HARD_SWISH; + break; + default: + return ActivationLayerInfo(); + } + + return ActivationLayerInfo(act, desc.a, desc.b); +} } // namespace detail } // namespace arm_compute diff --git a/src/common/utils/LegacySupport.h b/src/common/utils/LegacySupport.h index c2cc1bc182..05a70fc2c6 100644 --- a/src/common/utils/LegacySupport.h +++ b/src/common/utils/LegacySupport.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Arm Limited. + * Copyright (c) 2021, 2023 Arm Limited. * * SPDX-License-Identifier: MIT * @@ -26,6 +26,8 @@ #include "arm_compute/Acl.h" #include "arm_compute/core/TensorInfo.h" +#include "arm_compute/core/Types.h" +#include "arm_compute/function_info/ActivationLayerInfo.h" namespace arm_compute { @@ -45,6 +47,13 @@ TensorInfo convert_to_legacy_tensor_info(const AclTensorDescriptor &desc); * @return A converted descriptor */ AclTensorDescriptor convert_to_descriptor(const TensorInfo &info); +/** Convert an AclActivation descriptor to an internal one + * + * @param[in] desc Descriptor to convert + * + * @return Legacy tensor meta-data + */ +ActivationLayerInfo convert_to_activation_info(const AclActivationDescriptor &desc); } // namespace detail } // namespace arm_compute diff --git a/src/common/utils/Log.h b/src/common/utils/Log.h index 496ee74a16..6ebfed366e 100644 --- a/src/common/utils/Log.h +++ b/src/common/utils/Log.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Arm Limited. + * Copyright (c) 2021,2023 Arm Limited. * * SPDX-License-Identifier: MIT * @@ -24,25 +24,37 @@ #ifndef SRC_COMMON_LOG_H #define SRC_COMMON_LOG_H +#ifndef ARM_COMPUTE_LOGGING_ENABLED + +#define ARM_COMPUTE_CREATE_ACL_LOGGER() +#define ARM_COMPUTE_LOG_MSG_ACL(log_level, msg) +#define ARM_COMPUTE_LOG_MSG_WITH_FORMAT_ACL(log_level, fmt, ...) +#define ARM_COMPUTE_LOG_ERROR_ACL(msg) +#define ARM_COMPUTE_LOG_ERROR_WITH_FUNCNAME_ACL(msg) +#define ARM_COMPUTE_LOG_INFO_WITH_FUNCNAME_ACL(msg) +#define ARM_COMPUTE_LOG_PARAMS(...) + +#else /* ARM_COMPUTE_LOGGING_ENABLED */ + #include "arm_compute/core/Error.h" #include "arm_compute/core/utils/logging/Macros.h" -#ifdef ARM_COMPUTE_LOGGING_ENABLED +#include "utils/TypePrinter.h" + /** Create a logger * * @note It will eventually create all default loggers in don't exist */ -#define ARM_COMPUTE_CREATE_ACL_LOGGER() \ - do \ - { \ - if(arm_compute::logging::LoggerRegistry::get().logger("ComputeLibrary") == nullptr) \ - { \ - arm_compute::logging::LoggerRegistry::get().create_logger("ComputeLibrary", arm_compute::logging::LogLevel::INFO); \ - } \ - } while(false) -#else /* ARM_COMPUTE_LOGGING_ENABLED */ -#define ARM_COMPUTE_CREATE_ACL_LOGGER() -#endif /* ARM_COMPUTE_LOGGING_ENABLED */ +#define ARM_COMPUTE_CREATE_ACL_LOGGER() \ + do \ + { \ + if (arm_compute::logging::LoggerRegistry::get().logger("ComputeLibrary") == nullptr) \ + { \ + arm_compute::logging::LoggerRegistry::get().create_logger("ComputeLibrary", \ + arm_compute::logging::LogLevel::INFO); \ + } \ + } while (false) + /** Log a message to the logger * * @param[in] log_level Logging level @@ -53,7 +65,8 @@ { \ ARM_COMPUTE_CREATE_ACL_LOGGER(); \ ARM_COMPUTE_LOG_MSG("ComputeLibrary", log_level, msg); \ - } while(false) + } while (false) + /** Log a message with format to the logger * * @param[in] log_level Logging level @@ -65,7 +78,8 @@ { \ ARM_COMPUTE_CREATE_ACL_LOGGER(); \ ARM_COMPUTE_LOG_MSG_WITH_FORMAT("ComputeLibrary", log_level, fmt, __VA_ARGS__); \ - } while(false) + } while (false) + /** Log an error message to the logger * * @param[in] msg Message to log @@ -75,7 +89,7 @@ { \ ARM_COMPUTE_CREATE_ACL_LOGGER(); \ ARM_COMPUTE_LOG_MSG("ComputeLibrary", arm_compute::logging::LogLevel::ERROR, msg); \ - } while(false) + } while (false) /** Log an error message to the logger with function name before the message * @@ -86,6 +100,134 @@ { \ ARM_COMPUTE_CREATE_ACL_LOGGER(); \ ARM_COMPUTE_LOG_MSG_WITH_FUNCNAME("ComputeLibrary", arm_compute::logging::LogLevel::ERROR, msg); \ - } while(false) + } while (false) + +/** Log an information message to the logger with function name before the message + * + * @param[in] msg Message to log + */ +#define ARM_COMPUTE_LOG_INFO_WITH_FUNCNAME_ACL(msg) \ + do \ + { \ + ARM_COMPUTE_CREATE_ACL_LOGGER(); \ + ARM_COMPUTE_LOG_MSG_WITH_FUNCNAME("ComputeLibrary", arm_compute::logging::LogLevel::INFO, msg); \ + } while (false) +/** Function template specialization for the out of bound element at index = tuple_size + * + * @param[in,out] data_registry Reference to the input parameters data in a string format + * @param[in] in_params_tuple Tuple of different input data types + */ +template <std::size_t Index, typename... Tp> +inline typename std::enable_if<Index == sizeof...(Tp), void>::type +logParamsImpl(std::vector<std::string> &data_registry, const std::tuple<Tp...> &in_params_tuple) +{ + // Because it is out of bound index so do nothing + ARM_COMPUTE_UNUSED(data_registry); + ARM_COMPUTE_UNUSED(in_params_tuple); +} + +/** Function template to iterate over all input parameters tuple at compile time: + * + * @param[in,out] data_registry Reference to a vector of input parameters data in a string format + * @param[in] in_params_tuple Constant reference to a tuple of different input data types + */ +template <std::size_t Index, typename... Tp> + inline typename std::enable_if < + Index<sizeof...(Tp), void>::type logParamsImpl(std::vector<std::string> &data_registry, + const std::tuple<Tp...> &in_params_tuple) +{ + data_registry.push_back(arm_compute::to_string(std::get<Index>(in_params_tuple))); + // Unfold the next tuple element + logParamsImpl<Index + 1, Tp...>(data_registry, in_params_tuple); +} + +/** Function Template with variable number of inputs to collect all the passed parameters from + * the logging macro ARM_COMPUTE_LOG_PARAMS(...) + * + * @param[in] ...ins The input parameters in the variadic template, taken by universal references Ts.. &&, (not by value) + * to avoid detecting T as an abstract data type when passing any of these parameters as an L-value + * reference to an abstract type. + * + * @return Vector of the parameters' data in a string format + */ +template <typename... Ts> +const std::vector<std::string> logParams(Ts &&...ins) +{ + std::vector<std::string> data_registry{}; + std::tuple<Ts...> in_params_tuple{ins...}; + + // Start logging the tuple elements, starting from 0 to tuple_size-1 + logParamsImpl<0>(data_registry, in_params_tuple); + return data_registry; +} + +/** Inline function to parse the input parameters string passed from strignizing of the variadic macro input + * #__VA_ARGS__. + * It is Inline to avoid the redefinition of this function each time this header is included + * + * @param[in] in_params_str Constant reference to a string consists of the names of the input parameters provided + * as:ARM_COMPUTE_LOG_PARAMS(src0, src1) the params_names = "src0, src1" + * + * @return Vector of strings containing all the names of the input parameters + */ +inline const std::vector<std::string> getParamsNames(const std::string &in_params_str) +{ + std::stringstream ss(in_params_str); + + // Vector containing all the names of the input parameters + std::vector<std::string> names; + std::string temp; + + // Usually the input parameters string would be name of parameters separated + // by ',' e.g. "src0, src1, policy" + while (std::getline(ss, temp, ',')) + { + names.push_back(temp); + } + for (auto &name : names) + { + // Totally get rid of white space characters + name.erase(std::remove(name.begin(), name.end(), ' '), name.end()); + } + return names; +} + +/** It constructs the log message to be displayed by the logger by writing each parameter name and its + * corresponding data info string. + * + * @param[in] params_names Constant reference to a string consists of the the input parameters' names + * provided e.g.: ARM_COMPUTE_LOG_PARAMS(src0, src1) then params_names = "src0, src1" + * @param[in] data_registry Constant reference to a registry of all parameters' data in string format, + * stringnized by arm_compute::to_string() + * + * @return Log message string to be displayed + */ +inline const std::string constructDataLog(const std::vector<std::string> ¶ms_names, + const std::vector<std::string> &data_registry) +{ + std::string dataLog = "\n "; + ARM_COMPUTE_ERROR_ON(params_names.size() != data_registry.size()); + for (uint8_t i = 0; i < params_names.size(); ++i) + { + dataLog += params_names[i] + ": " + data_registry.at(i) + "\n "; + } + + return dataLog; +} + +/** Macro for logging input Parameters from any function. + * It detects the input parameters names, and their corresponding values before stringizing them using + * the overloaded arm_compute::to_string() type printer. Finally, displayed using the printer configured + * in the logger. + * + * @param[in] ... Input parameters + */ +#define ARM_COMPUTE_LOG_PARAMS(...) \ + do \ + { \ + ARM_COMPUTE_LOG_INFO_WITH_FUNCNAME_ACL( \ + constructDataLog(getParamsNames(#__VA_ARGS__), logParams(__VA_ARGS__))); \ + } while (false) +#endif /* ARM_COMPUTE_LOGGING_ENABLED */ #endif /* SRC_COMMON_LOG_H */ diff --git a/src/common/utils/Macros.h b/src/common/utils/Macros.h index 2e44ea599e..35f7e759d3 100644 --- a/src/common/utils/Macros.h +++ b/src/common/utils/Macros.h @@ -28,7 +28,7 @@ #define ARM_COMPUTE_RETURN_CENUM_ON_FAILURE(status) \ { \ - if(status != arm_compute::StatusCode::Success) \ + if (status != arm_compute::StatusCode::Success) \ { \ return arm_compute::utils::as_cenum<AclStatus>(status); \ } \ diff --git a/src/common/utils/Object.h b/src/common/utils/Object.h index 1f194737d4..b73de8e430 100644 --- a/src/common/utils/Object.h +++ b/src/common/utils/Object.h @@ -52,14 +52,12 @@ struct Header * @param[in] type_ Object identification type * @param[in] ctx_ Context to reference */ - Header(ObjectType type_, IContext *ctx_) noexcept - : type(type_), - ctx(ctx_) + Header(ObjectType type_, IContext *ctx_) noexcept : type(type_), ctx(ctx_) { } - ObjectType type{ ObjectType::Invalid }; - IContext *ctx{ nullptr }; + ObjectType type{ObjectType::Invalid}; + IContext *ctx{nullptr}; }; } // namespace detail } // namespace arm_compute diff --git a/src/common/utils/Utils.h b/src/common/utils/Utils.h index 79f4f39c47..33fe6c0e81 100644 --- a/src/common/utils/Utils.h +++ b/src/common/utils/Utils.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Arm Limited. + * Copyright (c) 2021,2023 Arm Limited. * * SPDX-License-Identifier: MIT * @@ -24,6 +24,8 @@ #ifndef SRC_COMMON_UTILS_H #define SRC_COMMON_UTILS_H +#include <algorithm> +#include <initializer_list> #include <type_traits> namespace arm_compute @@ -72,10 +74,7 @@ constexpr SE as_enum(const E val) noexcept template <typename E> bool is_in(E check, std::initializer_list<E> list) { - return std::any_of(std::cbegin(list), std::cend(list), [&check](E e) - { - return check == e; - }); + return std::any_of(list.begin(), list.end(), [&check](E e) { return check == e; }); } } // namespace utils } // namespace arm_compute diff --git a/src/common/utils/Validate.h b/src/common/utils/Validate.h index 4e8807273a..97819c619f 100644 --- a/src/common/utils/Validate.h +++ b/src/common/utils/Validate.h @@ -29,7 +29,7 @@ #include <cassert> -#define ARM_COMPUTE_ASSERT(cond) assert(cond) +#define ARM_COMPUTE_ASSERT(cond) assert(cond) #define ARM_COMPUTE_ASSERT_NOT_NULLPTR(ptr) assert((ptr) != nullptr) #else /* defined(ARM_COMPUTE_ASSERTS_ENABLED) */ |