diff --git a/include/aidge/backend/cpu/operator/GlobalAveragePoolingImpl.hpp b/include/aidge/backend/cpu/operator/GlobalAveragePoolingImpl.hpp index 4e04b1a595a8660b1528e49921e7e3e7a567829a..a71174c03216dc04e27325d59062d0383f5224ea 100644 --- a/include/aidge/backend/cpu/operator/GlobalAveragePoolingImpl.hpp +++ b/include/aidge/backend/cpu/operator/GlobalAveragePoolingImpl.hpp @@ -18,12 +18,11 @@ #include "aidge/backend/cpu/operator/OperatorImpl.hpp" #include "aidge/operator/GlobalAveragePooling.hpp" #include "aidge/utils/Registrar.hpp" -#include "aidge/utils/Types.h" namespace Aidge { // Operator implementation entry point for the backend using GlobalAveragePoolingImpl_cpu = OperatorImpl_cpu<GlobalAveragePooling_Op, - void(const std::vector<DimSize_t> &, const void *, void *)>; + void(const std::shared_ptr<Tensor>&, void *)>; // Implementation entry point registration to Operator REGISTRAR(GlobalAveragePooling_Op, "cpu", Aidge::GlobalAveragePoolingImpl_cpu::create); diff --git a/include/aidge/backend/cpu/operator/GlobalAveragePoolingImpl_kernels.hpp b/include/aidge/backend/cpu/operator/GlobalAveragePoolingImpl_kernels.hpp index 7a47ccf3be4de2ee066d2d7c27a6c04f115059b4..40dd3a6932541475e7315dbb6829f99429b030ba 100644 --- a/include/aidge/backend/cpu/operator/GlobalAveragePoolingImpl_kernels.hpp +++ b/include/aidge/backend/cpu/operator/GlobalAveragePoolingImpl_kernels.hpp @@ -12,92 +12,71 @@ #ifndef AIDGE_CPU_OPERATOR_GLOBALAVERAGEPOOLINGIMPL_KERNELS_H_ #define AIDGE_CPU_OPERATOR_GLOBALAVERAGEPOOLINGIMPL_KERNELS_H_ -#include <cstddef> -#include <functional> // std::multiplies -#include <numeric> // std::accumulate +#include <cstddef> // std::size_t #include <vector> #include "aidge/backend/cpu/operator/GlobalAveragePoolingImpl.hpp" -#include "aidge/data/Data.hpp" -#include "aidge/utils/ErrorHandling.hpp" +#include "aidge/data/Tensor.hpp" #include "aidge/utils/Registrar.hpp" #include "aidge/utils/Types.h" - namespace Aidge { template <typename T> -typename std::enable_if<std::is_floating_point<T>::value, T>::type -stableMean(const T* vec, size_t size) { - T mean = 0; - for (size_t i = 0; i < size; ++i) { - mean = std::fma<T>(vec[i] - mean, 1.0f / (i + 1), mean); - } - return mean; +typename std::enable_if_t<std::is_floating_point<T>::value, T> +static stableMean(const T* vec, std::size_t size) { + T mean{0}; + for (std::size_t i = 0; i < size; ++i) { + mean = std::fma(vec[i] - mean, static_cast<T>(1) / static_cast<T>(i + 1), mean); + } + return mean; } // Specialization for integers: perform the mean computation in float template <typename T> -typename std::enable_if<!std::is_floating_point<T>::value, double>::type -stableMean(const T* vec, size_t size) { - double mean = 0; - for (size_t i = 0; i < size; ++i) { - mean = std::fma<double>(vec[i] - mean, 1.0f / (i + 1), mean); - } - return mean; -} - -template <typename T> -typename std::enable_if<std::is_floating_point<T>::value, T>::type -castFromFloat(T value) { - return value; -} - -template <typename T> -typename std::enable_if<!std::is_floating_point<T>::value, T>::type -castFromFloat(double value) { - return static_cast<T>(std::nearbyint(value)); +typename std::enable_if_t<!std::is_floating_point<T>::value, double> +static stableMean(const T* vec, std::size_t size) { + double mean{0}; + for (std::size_t i = 0; i < size; ++i) { + mean = std::fma<double>(static_cast<double>(vec[i]) - mean, 1.0 / static_cast<double>(i + 1), mean); + } + return mean; } -template <class I, class O> -void GlobalAveragePoolingImpl_cpu_forward_kernel( - const std::vector<DimSize_t> &dims, const void *input_, void *output_) { - // error checking - AIDGE_ASSERT(dims.size() >= 3,"GlobalAveragePool needs at least a 3 dimensions " - "input, number of input dim : {}", - dims.size()); +template <DataType DT_I, DataType DT_O = DT_I> +void GlobalAveragePoolingImpl_cpu_forward_kernel(const std::shared_ptr<Tensor>& inputTensor, void *output_) { - // computation - const I *input = static_cast<const I *>(input_); - O *output = static_cast<O *>(output_); + // computation + using I = cpptype_t<DT_I>; + using O = cpptype_t<DT_O>; + const I *input = static_cast<const I *>(inputTensor->getImpl()->rawPtr()); + O *output = static_cast<O *>(output_); + const auto& dims = inputTensor->dims(); - DimSize_t nb_elems = std::accumulate(dims.begin(), dims.end(), std::size_t(1), - std::multiplies<std::size_t>()); + const DimSize_t strides_channels = inputTensor->strides()[1]; - const DimSize_t in_batch_nb_elems{nb_elems / dims[0]}; - const DimSize_t in_channel_nb_elems{in_batch_nb_elems / dims[1]}; - const DimSize_t out_batch_nb_elems{dims[1]}; - // parse channel by channel and fill each output with the average of the - // values in the channel - for (DimSize_t batch = 0; batch < dims[0]; ++batch) { - for (DimSize_t channel = 0; channel < dims[1]; ++channel) { - const I *filter_start = std::next( - input, (batch * in_batch_nb_elems) + (channel * in_channel_nb_elems)); - output[batch * out_batch_nb_elems + channel] = castFromFloat<O>(stableMean<I>(filter_start, in_channel_nb_elems)); + // parse channel by channel and fill each output with the average of the + // values in the channel + std::size_t input_idx = 0; + std::size_t output_idx = 0; + for (DimSize_t batch = 0; batch < dims[0]; ++batch) { + for (DimSize_t channel = 0; channel < dims[1]; ++channel) { + output[output_idx++] = static_cast<O>(stableMean<I>(input + input_idx, strides_channels)); + input_idx += strides_channels; + } } - } } // Kernels registration to implementation entry point REGISTRAR(GlobalAveragePoolingImpl_cpu, {DataType::Float32}, - {ProdConso::defaultModel, Aidge::GlobalAveragePoolingImpl_cpu_forward_kernel<float, float>, nullptr}); + {ProdConso::defaultModel, Aidge::GlobalAveragePoolingImpl_cpu_forward_kernel<DataType::Float32>, nullptr}); REGISTRAR(GlobalAveragePoolingImpl_cpu, {DataType::Float64}, - {ProdConso::defaultModel, Aidge::GlobalAveragePoolingImpl_cpu_forward_kernel<double, double>, nullptr}); + {ProdConso::defaultModel, Aidge::GlobalAveragePoolingImpl_cpu_forward_kernel<DataType::Float64>, nullptr}); REGISTRAR(GlobalAveragePoolingImpl_cpu, {DataType::Int32}, - {ProdConso::defaultModel, Aidge::GlobalAveragePoolingImpl_cpu_forward_kernel<int32_t, int32_t>, nullptr}); + {ProdConso::defaultModel, Aidge::GlobalAveragePoolingImpl_cpu_forward_kernel<DataType::Int32>, nullptr}); } // namespace Aidge #endif /* AIDGE_CPU_OPERATOR_GLOBALAVERAGEPOOLINGIMPL_KERNELS_H_ */ diff --git a/include/aidge/backend/cpu/operator/ReduceMeanImpl.hpp b/include/aidge/backend/cpu/operator/ReduceMeanImpl.hpp index 1c50805d5af768dfc160488fda1e8fadfa798454..d6c60c352dc862095bad9ac67ab50d05129b8dc2 100644 --- a/include/aidge/backend/cpu/operator/ReduceMeanImpl.hpp +++ b/include/aidge/backend/cpu/operator/ReduceMeanImpl.hpp @@ -12,7 +12,6 @@ #ifndef AIDGE_CPU_OPERATOR_REDUCEMEANIMPL_H_ #define AIDGE_CPU_OPERATOR_REDUCEMEANIMPL_H_ -#include <array> #include <memory> #include <tuple> #include <vector> diff --git a/include/aidge/backend/cpu/operator/ReduceMeanImpl_kernels.hpp b/include/aidge/backend/cpu/operator/ReduceMeanImpl_kernels.hpp index a156232230bd6e9be496eec2b76ccf8fcab4d9e9..73aa283d51d72e28d135ae5bb422f3f9f8dcd8c6 100644 --- a/include/aidge/backend/cpu/operator/ReduceMeanImpl_kernels.hpp +++ b/include/aidge/backend/cpu/operator/ReduceMeanImpl_kernels.hpp @@ -25,39 +25,39 @@ #include "aidge/utils/Registrar.hpp" namespace Aidge { - + template <typename T> -using Acc_T = typename std::conditional<std::is_floating_point<T>::value, T, double>::type; +using Acc_T = typename std::conditional_t<std::is_floating_point<T>::value, T, double>; template <typename T> typename std::enable_if<std::is_floating_point<T>::value, T>::type -stableMean(const T* vec, size_t len, size_t stride) { +stableMean(const T* vec, std::size_t len, std::size_t stride) { T mean = 0; - for (size_t i = 0; i < len; ++i) { - mean = std::fma<T>(vec[i * stride] - mean, 1.0f / (i + 1), mean); + for (std::size_t i = 0; i < len; ++i) { + mean = std::fma(vec[i * stride] - mean, static_cast<T>(1) / static_cast<T>(i + 1), mean); } return mean; } // Specialization for integers: perform the mean computation in float template <typename T> -typename std::enable_if<!std::is_floating_point<T>::value, double>::type -stableMean(const T* vec, size_t len, size_t stride) { +typename std::enable_if_t<!std::is_floating_point<T>::value, double> +stableMean(const T* vec, std::size_t len, std::size_t stride) { double mean = 0; for (size_t i = 0; i < len; ++i) { - mean = std::fma<double>(vec[i * stride] - mean, 1.0f / (i + 1), mean); + mean = std::fma<double>(static_cast<double>(vec[i * stride]) - mean, 1.0 / static_cast<double>(i + 1), mean); } return mean; } template <typename T> -typename std::enable_if<std::is_floating_point<T>::value, T>::type +typename std::enable_if_t<std::is_floating_point<T>::value, T> castFromFloat(T value) { return value; } template <typename T> -typename std::enable_if<!std::is_floating_point<T>::value, T>::type +typename std::enable_if_t<!std::is_floating_point<T>::value, T> castFromFloat(double value) { return static_cast<T>(std::nearbyint(value)); } diff --git a/src/operator/GlobalAveragePoolingImpl.cpp b/src/operator/GlobalAveragePoolingImpl.cpp index c53f92e199aee30d55ddafe39b5ef121979acbf7..1b6d9a0629d856c2ad1fc3eae35db4c12058bc4f 100644 --- a/src/operator/GlobalAveragePoolingImpl.cpp +++ b/src/operator/GlobalAveragePoolingImpl.cpp @@ -30,13 +30,15 @@ void Aidge::GlobalAveragePoolingImpl_cpu::forward() const GlobalAveragePooling_Op& op_ = static_cast<const GlobalAveragePooling_Op&>(mOp); // Check if input is provided AIDGE_ASSERT(op_.getInput(0), "missing input 0"); + // error checking + AIDGE_ASSERT(op_.getInput(0)->nbDims() >= 3,"GlobalAveragePool needs at least a 3 dimensions " + "input. Got input dims {}", op_.getInput(0)->dims()); // Find the correct kernel type const auto impl = Registrar<GlobalAveragePoolingImpl_cpu>::create(getBestMatch(getRequiredSpec())); // Call kernel - impl.forward(op_.getInput(0)->dims(), - op_.getInput(0)->getImpl()->rawPtr(), + impl.forward(op_.getInput(0), op_.getOutput(0)->getImpl()->rawPtr()); }