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

Added rounding mechanism

parent e1f02f51
No related branches found
No related tags found
2 merge requests!1740.6.1,!170Add new rounding mechanism
Pipeline #72753 passed
Showing
with 32 additions and 22 deletions
......@@ -32,6 +32,7 @@ using AvgPoolingImpl2D_cpu = OperatorImpl_cpu<AvgPooling_Op<2>,
const std::array<DimSize_t, 2>&,
const std::array<DimSize_t, 4>&,
bool,
RoundingMode,
const void *,
void *)>;
......
......@@ -29,14 +29,14 @@ using Acc_T = typename std::conditional<std::is_floating_point<T>::value, T, dou
template <typename T>
typename std::enable_if<std::is_floating_point<T>::value, T>::type
castFromFloat(T value) {
castFromFloat(T value, RoundingMode /*roundingMode*/) {
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));
castFromFloat(double value, RoundingMode roundingMode) {
return static_cast<T>(round(value, roundingMode));
}
/**
......@@ -54,6 +54,7 @@ void AvgPoolingImpl2D_cpu_forward_kernel(const std::array<DimSize_t, 2>& strideD
const std::array<DimSize_t, 2>& dilations,
const std::array<DimSize_t, 4> &dims,
bool ceilMode,
RoundingMode roundingMode,
const void *input_,
void *output_) {
const I *input = static_cast<const I *>(input_);
......@@ -115,7 +116,7 @@ void AvgPoolingImpl2D_cpu_forward_kernel(const std::array<DimSize_t, 2>& strideD
}
}
output[oIndexFull] = count > 0 ? castFromFloat<O>(sum / count) : 0;
output[oIndexFull] = count > 0 ? castFromFloat<O>(sum / count, roundingMode) : 0;
}
}
}
......
......@@ -22,7 +22,7 @@
namespace Aidge {
// Operator implementation entry point for the backend
using GlobalAveragePoolingImpl_cpu = OperatorImpl_cpu<GlobalAveragePooling_Op,
void(const std::shared_ptr<Tensor>&, void *)>;
void(RoundingMode, const std::shared_ptr<Tensor>&, void *)>;
// Implementation entry point registration to Operator
REGISTRAR(GlobalAveragePooling_Op, "cpu", Aidge::GlobalAveragePoolingImpl_cpu::create);
......
......@@ -45,18 +45,18 @@ static stableMean(const T* vec, std::size_t size) {
template <typename T>
typename std::enable_if_t<std::is_floating_point<T>::value, T>
static castFromFloat(T value) {
static castFromFloat(T value, RoundingMode /*roundingMode*/) {
return value;
}
template <typename T>
typename std::enable_if_t<!std::is_floating_point<T>::value, T>
static castFromFloat(double value) {
return static_cast<T>(std::nearbyint(value));
static castFromFloat(double value, RoundingMode roundingMode) {
return static_cast<T>(round(value, roundingMode));
}
template <DataType DT_I, DataType DT_O = DT_I>
void GlobalAveragePoolingImpl_cpu_forward_kernel(const std::shared_ptr<Tensor>& inputTensor, void *output_) {
void GlobalAveragePoolingImpl_cpu_forward_kernel(RoundingMode roundingMode, const std::shared_ptr<Tensor>& inputTensor, void *output_) {
// computation
using I = cpptype_t<DT_I>;
......@@ -81,7 +81,7 @@ void GlobalAveragePoolingImpl_cpu_forward_kernel(const std::shared_ptr<Tensor>&
for (int channel = 0; channel < static_cast<int>(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));
output[batch * out_batch_nb_elems + channel] = castFromFloat<O>(stableMean<I>(filter_start, in_channel_nb_elems), roundingMode);
}
}
}
......
......@@ -26,6 +26,7 @@ namespace Aidge {
using ReduceMeanImpl_cpu = OperatorImpl_cpu<ReduceMean_Op,
void(const std::vector<std::int32_t>&,
DimSize_t,
RoundingMode,
const std::vector<DimSize_t>&,
const void *,
void *)>;
......
......@@ -52,19 +52,20 @@ stableMean(const T* vec, std::size_t len, std::size_t stride) {
template <typename T>
typename std::enable_if_t<std::is_floating_point<T>::value, T>
castFromFloat(T value) {
castFromFloat(T value, RoundingMode /*roundingMode*/) {
return value;
}
template <typename T>
typename std::enable_if_t<!std::is_floating_point<T>::value, T>
castFromFloat(double value) {
return static_cast<T>(std::nearbyint(value));
castFromFloat(double value, RoundingMode roundingMode) {
return static_cast<T>(round(value, roundingMode));
}
template <class I, class O>
void ReduceMeanImpl_cpu_forward_kernel(const std::vector<std::int32_t>& axes,
DimSize_t /*keepDims*/,
RoundingMode roundingMode,
const std::vector<DimSize_t>& inputDims,
const void* input_,
void* output_) {
......@@ -87,7 +88,7 @@ void ReduceMeanImpl_cpu_forward_kernel(const std::vector<std::int32_t>& axes,
for (std::size_t post = 0; post < stride_post; ++post) {
const std::size_t idx_i = pre * dim_i * stride_post + post;
const std::size_t idx_o = pre * stride_post + post;
output[idx_o] = castFromFloat<O>(stableMean(input + idx_i, dim_i, stride_post));
output[idx_o] = castFromFloat<O>(stableMean(input + idx_i, dim_i, stride_post), roundingMode);
}
}
} else {
......@@ -133,7 +134,7 @@ void ReduceMeanImpl_cpu_forward_kernel(const std::vector<std::int32_t>& axes,
}
std::transform(inputAccumulation, inputAccumulation + outputElements, output,
[](auto value) { return castFromFloat<O>(value); });
[roundingMode](auto value) { return castFromFloat<O>(value, roundingMode); });
if (outputAccumulation) {
delete[] outputAccumulation;
}
......
......@@ -25,7 +25,7 @@
namespace Aidge {
// Operator implementation entry point for the backend
using RoundImpl_cpu = OperatorImpl_cpu<Round_Op,
void(const std::size_t, const void*, void*)>;
void(RoundingMode, const std::size_t, const void*, void*)>;
// Implementation entry point registration to Operator
REGISTRAR(Round_Op, "cpu", Aidge::RoundImpl_cpu::create);
......
......@@ -21,7 +21,8 @@
namespace Aidge {
template <class I, class O>
void RoundImpl_cpu_forward_kernel(const std::size_t inputLength,
void RoundImpl_cpu_forward_kernel(RoundingMode roundingMode,
const std::size_t inputLength,
const void* input_,
void* output_) {
......@@ -29,8 +30,7 @@ void RoundImpl_cpu_forward_kernel(const std::size_t inputLength,
O* output = static_cast<O*>(output_);
for (std::size_t i = 0; i < inputLength; ++i) {
//std::round would not work since it doesn't follow the halves rules (See ONNX Round)
output[i] = static_cast<O>(std::nearbyint(static_cast<float>(input[i])));
output[i] = static_cast<O>(round(input[i], roundingMode));
}
}
......
......@@ -35,6 +35,7 @@ void Aidge::AvgPoolingImpl2D_cpu::forward() {
op_.dilations(),
op_.getInput(0)->template dims<4>(),
op_.ceilMode(),
op_.roundingMode(),
getCPUPtr(op_.getInput(0)),
getCPUPtr(op_.getOutput(0)));
}
......
......@@ -38,7 +38,8 @@ void Aidge::GlobalAveragePoolingImpl_cpu::forward()
const auto impl = Registrar<GlobalAveragePoolingImpl_cpu>::create(getBestMatch(getRequiredSpec()));
// Call kernel
impl.forward(op_.getInput(0),
impl.forward(op_.roundingMode(),
op_.getInput(0),
op_.getOutput(0)->getImpl()->rawPtr());
}
......
......@@ -28,6 +28,7 @@ void Aidge::ReduceMeanImpl_cpu::forward() {
// Call kernel
impl.forward(op_.axes(),
op_.keepDims(),
op_.roundingMode(),
op_.getInput(0)->dims(),
op_.getInput(0)->getImpl()->rawPtr(),
op_.getOutput(0)->getImpl()->rawPtr());
......
......@@ -22,6 +22,8 @@
template <>
void Aidge::RoundImpl_cpu::forward() {
const Round_Op& op_ = dynamic_cast<const Round_Op&>(mOp);
std::shared_ptr<Tensor> in0 = std::static_pointer_cast<Tensor>(mOp.getRawInput(0));
std::shared_ptr<Tensor> out0 = std::static_pointer_cast<Tensor>(mOp.getRawOutput(0));
AIDGE_ASSERT(in0, "missing input #0");
......@@ -30,7 +32,8 @@ void Aidge::RoundImpl_cpu::forward() {
const auto impl = Registrar<RoundImpl_cpu>::create(getBestMatch(getRequiredSpec()));
// Call kernel
impl.forward(in0->size(),
impl.forward(op_.roundingMode(),
in0->size(),
getCPUPtr(mOp.getRawInput(0)),
getCPUPtr(mOp.getRawOutput(0)));
}
......
......@@ -83,7 +83,7 @@ TEST_CASE("[cpu/operator] Round_Test", "[Round][CPU]") {
for (std::size_t i = 0; i < nb_elements; ++i) {
array0[i] = valueDist(gen);
result[i] = std::nearbyint(array0[i]);
result[i] = std::round(array0[i]);
}
......
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