Skip to content
Snippets Groups Projects
Commit 70ca8d05 authored by Olivier BICHLER's avatar Olivier BICHLER
Browse files

Fixed wrong computation in int

parent 83655173
No related branches found
No related tags found
No related merge requests found
Pipeline #67655 canceled
...@@ -23,6 +23,22 @@ ...@@ -23,6 +23,22 @@
#include "aidge/utils/Types.h" #include "aidge/utils/Types.h"
namespace Aidge { namespace Aidge {
template <typename T>
using Acc_T = typename std::conditional<std::is_floating_point<T>::value, T, double>::type;
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));
}
/** /**
* @brief Forward kernel for 2D AvgPoolingolution on CPU backend. * @brief Forward kernel for 2D AvgPoolingolution on CPU backend.
* @tparam I Input data type. * @tparam I Input data type.
...@@ -79,7 +95,7 @@ void AvgPoolingImpl2D_cpu_forward_kernel(const std::array<DimSize_t, 2>& strideD ...@@ -79,7 +95,7 @@ void AvgPoolingImpl2D_cpu_forward_kernel(const std::array<DimSize_t, 2>& strideD
const std::size_t ix = ox * strideDims[0]; const std::size_t ix = ox * strideDims[0];
const std::size_t iy = oy * strideDims[1]; const std::size_t iy = oy * strideDims[1];
O sum = static_cast<O>(0); Acc_T<I> sum = static_cast<Acc_T<I>>(0);
std::size_t count = 0; std::size_t count = 0;
for (unsigned int sy = syMin; sy < syMax; ++sy) { for (unsigned int sy = syMin; sy < syMax; ++sy) {
...@@ -90,13 +106,13 @@ void AvgPoolingImpl2D_cpu_forward_kernel(const std::array<DimSize_t, 2>& strideD ...@@ -90,13 +106,13 @@ void AvgPoolingImpl2D_cpu_forward_kernel(const std::array<DimSize_t, 2>& strideD
// Ensure within bounds // Ensure within bounds
if ((ix + dilated_sx) < dims[2] && (iy + dilated_sy) < dims[3]) { if ((ix + dilated_sx) < dims[2] && (iy + dilated_sy) < dims[3]) {
sum += static_cast<O>(input[iIndex + (ix + dilated_sx) * dims[3] + (iy + dilated_sy)]); sum += static_cast<Acc_T<I>>(input[iIndex + (ix + dilated_sx) * dims[3] + (iy + dilated_sy)]);
++count; ++count;
} }
} }
} }
output[oIndexFull] = count > 0 ? sum / static_cast<O>(count) : 0; output[oIndexFull] = count > 0 ? castFromFloat<O>(sum / count) : 0;
} }
} }
} }
......
...@@ -38,7 +38,7 @@ stableMean(const T* vec, size_t size) { ...@@ -38,7 +38,7 @@ stableMean(const T* vec, size_t size) {
// Specialization for integers: perform the mean computation in float // Specialization for integers: perform the mean computation in float
template <typename T> template <typename T>
typename std::enable_if<!std::is_floating_point<T>::value, T>::type typename std::enable_if<!std::is_floating_point<T>::value, double>::type
stableMean(const T* vec, size_t size) { stableMean(const T* vec, size_t size) {
double mean = 0; double mean = 0;
for (size_t i = 0; i < size; ++i) { for (size_t i = 0; i < size; ++i) {
......
...@@ -25,6 +25,9 @@ ...@@ -25,6 +25,9 @@
#include "aidge/utils/Registrar.hpp" #include "aidge/utils/Registrar.hpp"
namespace Aidge { namespace Aidge {
template <typename T>
using Acc_T = typename std::conditional<std::is_floating_point<T>::value, T, double>::type;
template <typename T> template <typename T>
typename std::enable_if<std::is_floating_point<T>::value, T>::type typename std::enable_if<std::is_floating_point<T>::value, T>::type
...@@ -38,7 +41,7 @@ stableMean(const T* vec, size_t len, size_t stride) { ...@@ -38,7 +41,7 @@ stableMean(const T* vec, size_t len, size_t stride) {
// Specialization for integers: perform the mean computation in float // Specialization for integers: perform the mean computation in float
template <typename T> template <typename T>
typename std::enable_if<!std::is_floating_point<T>::value, T>::type typename std::enable_if<!std::is_floating_point<T>::value, double>::type
stableMean(const T* vec, size_t len, size_t stride) { stableMean(const T* vec, size_t len, size_t stride) {
double mean = 0; double mean = 0;
for (size_t i = 0; i < len; ++i) { for (size_t i = 0; i < len; ++i) {
...@@ -102,13 +105,13 @@ void ReduceMeanImpl_cpu_forward_kernel(const std::vector<std::int32_t>& axes, ...@@ -102,13 +105,13 @@ void ReduceMeanImpl_cpu_forward_kernel(const std::vector<std::int32_t>& axes,
} }
// Type should be the return type of stableMean<I>(), which is always floating point // Type should be the return type of stableMean<I>(), which is always floating point
const decltype(stableMean<I>(input, 0, 0))* inputAccumulation = nullptr; const Acc_T<I>* inputAccumulation = nullptr;
decltype(stableMean<I>(input, 0, 0))* outputAccumulation = nullptr; Acc_T<I>* outputAccumulation = nullptr;
for (const auto& axisInt : axes) { for (const auto& axisInt : axes) {
const std::size_t a = static_cast<std::size_t>(axisInt); const std::size_t a = static_cast<std::size_t>(axisInt);
outputElements /= inputDims[a]; outputElements /= inputDims[a];
outputAccumulation = new I[outputElements]; outputAccumulation = new Acc_T<I>[outputElements];
const std::size_t dim_i = inputDims[a]; const std::size_t dim_i = inputDims[a];
for (std::size_t pre = 0; pre < stride_pre[a]; ++pre) { for (std::size_t pre = 0; pre < stride_pre[a]; ++pre) {
for (std::size_t post = 0; post < stride_post[a]; ++post) { for (std::size_t post = 0; post < stride_post[a]; ++post) {
...@@ -118,7 +121,7 @@ void ReduceMeanImpl_cpu_forward_kernel(const std::vector<std::int32_t>& axes, ...@@ -118,7 +121,7 @@ void ReduceMeanImpl_cpu_forward_kernel(const std::vector<std::int32_t>& axes,
outputAccumulation[idx_o] = stableMean<I>(input + idx_i, dim_i, stride_post[a]); outputAccumulation[idx_o] = stableMean<I>(input + idx_i, dim_i, stride_post[a]);
} }
else { else {
outputAccumulation[idx_o] = stableMean<I>(inputAccumulation + idx_i, dim_i, stride_post[a]); outputAccumulation[idx_o] = stableMean<Acc_T<I>>(inputAccumulation + idx_i, dim_i, stride_post[a]);
} }
} }
} }
......
...@@ -201,4 +201,25 @@ TEST_CASE("[cpu/operator] AvgPooling(forward)", "[AvgPooling][CPU]") { ...@@ -201,4 +201,25 @@ TEST_CASE("[cpu/operator] AvgPooling(forward)", "[AvgPooling][CPU]") {
op2->getOutput(0)->print(); op2->getOutput(0)->print();
REQUIRE(*(op2->getOutput(0)) == *myOutput5); REQUIRE(*(op2->getOutput(0)) == *myOutput5);
} }
SECTION("Simple test") {
std::shared_ptr<Tensor> tensor =
std::make_shared<Tensor>(Array4D<int32_t, 1, 1, 7, 7>{{{{
{0, 8, 26, 35, 49, 45, 22},
{2, 24, 48, 66, 60, 46, 26},
{8, 41, 64, 68, 39, 18, 9},
{10, 48, 72, 76, 42, 14, 9},
{6, 29, 52, 65, 27, 7, 3},
{1, 9, 24, 31, 18, 7, 1},
{0, 0, 4, 6, 7, 1, 1}}}}});
auto op = AvgPooling2D_Op({7, 7});
op.setDataType(DataType::Int32);
op.setBackend("cpu");
op.associateInput(0, tensor);
op.forwardDims();
op.forward();
REQUIRE(op.getOutput(0)->get<int32_t>(0) == 26);
}
} }
\ No newline at end of file
...@@ -558,6 +558,27 @@ TEST_CASE("[cpu/operator] GlobalAveragePooling", ...@@ -558,6 +558,27 @@ TEST_CASE("[cpu/operator] GlobalAveragePooling",
Log::info("Number of operations : {}\n", number_of_operation); Log::info("Number of operations : {}\n", number_of_operation);
Log::info("Operation / µs = {}\n", number_of_operation / duration.count()); Log::info("Operation / µs = {}\n", number_of_operation / duration.count());
} }
SECTION("Simple test") {
std::shared_ptr<Tensor> tensor =
std::make_shared<Tensor>(Array4D<int32_t, 1, 1, 7, 7>{{{{
{0, 8, 26, 35, 49, 45, 22},
{2, 24, 48, 66, 60, 46, 26},
{8, 41, 64, 68, 39, 18, 9},
{10, 48, 72, 76, 42, 14, 9},
{6, 29, 52, 65, 27, 7, 3},
{1, 9, 24, 31, 18, 7, 1},
{0, 0, 4, 6, 7, 1, 1}}}}});
auto op = GlobalAveragePooling_Op();
op.setDataType(DataType::Int32);
op.setBackend("cpu");
op.associateInput(0, tensor);
op.forwardDims();
op.forward();
REQUIRE(op.getOutput(0)->get<int32_t>(0) == 26);
}
} }
} }
} // namespace Aidge } // namespace Aidge
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment