diff --git a/include/aidge/backend/cpu/operator/AvgPoolingImpl.hpp b/include/aidge/backend/cpu/operator/AvgPoolingImpl.hpp
index 7c76657f7d100255f49ab1e675672407c5fbbaf8..f805f2044a9129956858d27eac7823aac06dcb42 100644
--- a/include/aidge/backend/cpu/operator/AvgPoolingImpl.hpp
+++ b/include/aidge/backend/cpu/operator/AvgPoolingImpl.hpp
@@ -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 *)>;
 
diff --git a/include/aidge/backend/cpu/operator/AvgPoolingImpl_kernels.hpp b/include/aidge/backend/cpu/operator/AvgPoolingImpl_kernels.hpp
index f9cc13b5b0be6e63aa2ac7da8d3eccbaf7c9cd2e..9980d884f5c63682e65095e9c07ae52da3d09e25 100644
--- a/include/aidge/backend/cpu/operator/AvgPoolingImpl_kernels.hpp
+++ b/include/aidge/backend/cpu/operator/AvgPoolingImpl_kernels.hpp
@@ -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;
                 }
             }
         }
diff --git a/include/aidge/backend/cpu/operator/GlobalAveragePoolingImpl.hpp b/include/aidge/backend/cpu/operator/GlobalAveragePoolingImpl.hpp
index a71174c03216dc04e27325d59062d0383f5224ea..24561ed2524f655653fa7d83ab830e6f10d18ac9 100644
--- a/include/aidge/backend/cpu/operator/GlobalAveragePoolingImpl.hpp
+++ b/include/aidge/backend/cpu/operator/GlobalAveragePoolingImpl.hpp
@@ -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);
diff --git a/include/aidge/backend/cpu/operator/GlobalAveragePoolingImpl_kernels.hpp b/include/aidge/backend/cpu/operator/GlobalAveragePoolingImpl_kernels.hpp
index 3cab0ad9647a974170bf682fcf3b57b306bd76bd..8fe83370c3d593661a75bc8a2b0c04c7283b205a 100644
--- a/include/aidge/backend/cpu/operator/GlobalAveragePoolingImpl_kernels.hpp
+++ b/include/aidge/backend/cpu/operator/GlobalAveragePoolingImpl_kernels.hpp
@@ -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);
         }
     }
 }
diff --git a/include/aidge/backend/cpu/operator/ReduceMeanImpl.hpp b/include/aidge/backend/cpu/operator/ReduceMeanImpl.hpp
index d6c60c352dc862095bad9ac67ab50d05129b8dc2..993e9941501725bf87bcd199aaa35103f8c3bcb3 100644
--- a/include/aidge/backend/cpu/operator/ReduceMeanImpl.hpp
+++ b/include/aidge/backend/cpu/operator/ReduceMeanImpl.hpp
@@ -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 *)>;
diff --git a/include/aidge/backend/cpu/operator/ReduceMeanImpl_kernels.hpp b/include/aidge/backend/cpu/operator/ReduceMeanImpl_kernels.hpp
index 73aa283d51d72e28d135ae5bb422f3f9f8dcd8c6..eea790d5b88e05fb328106c3ee452816fd8c8117 100644
--- a/include/aidge/backend/cpu/operator/ReduceMeanImpl_kernels.hpp
+++ b/include/aidge/backend/cpu/operator/ReduceMeanImpl_kernels.hpp
@@ -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;
         }
diff --git a/include/aidge/backend/cpu/operator/RoundImpl.hpp b/include/aidge/backend/cpu/operator/RoundImpl.hpp
index c595e251cc18348b6f732f1c36a05de54f647204..02e35f7495e36b576797e572c210640784c185ab 100644
--- a/include/aidge/backend/cpu/operator/RoundImpl.hpp
+++ b/include/aidge/backend/cpu/operator/RoundImpl.hpp
@@ -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);
diff --git a/include/aidge/backend/cpu/operator/RoundImpl_kernels.hpp b/include/aidge/backend/cpu/operator/RoundImpl_kernels.hpp
index 7ac4319b2b10241dda2617db7df40a7947eb17ff..0330434708b48b0c9a7162224f9679a19c7033ab 100644
--- a/include/aidge/backend/cpu/operator/RoundImpl_kernels.hpp
+++ b/include/aidge/backend/cpu/operator/RoundImpl_kernels.hpp
@@ -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));
     }
 }
 
diff --git a/src/operator/AvgPoolingImpl.cpp b/src/operator/AvgPoolingImpl.cpp
index eb5ef87bd16620cdef33330bd7b39ece1783ecfc..53f0f79956ceef7e6381fc8745834d6074c66a70 100644
--- a/src/operator/AvgPoolingImpl.cpp
+++ b/src/operator/AvgPoolingImpl.cpp
@@ -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)));
 }
diff --git a/src/operator/GlobalAveragePoolingImpl.cpp b/src/operator/GlobalAveragePoolingImpl.cpp
index 1b6d9a0629d856c2ad1fc3eae35db4c12058bc4f..ba613e554b7c9d93a406cedf2c84c39257b5bb3d 100644
--- a/src/operator/GlobalAveragePoolingImpl.cpp
+++ b/src/operator/GlobalAveragePoolingImpl.cpp
@@ -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());
 }
 
diff --git a/src/operator/ReduceMeanImpl.cpp b/src/operator/ReduceMeanImpl.cpp
index 622672569372ff4e9f135e36255095f4246d5920..7ad6df0e4d4716a96e6e4a25652033229476f96a 100644
--- a/src/operator/ReduceMeanImpl.cpp
+++ b/src/operator/ReduceMeanImpl.cpp
@@ -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());
diff --git a/src/operator/RoundImpl.cpp b/src/operator/RoundImpl.cpp
index 6f19f064cabfaa6bde7b434b0defe53f5c1b78cf..e18dbdc7523366fa6beeb9d72c2f40116819a837 100644
--- a/src/operator/RoundImpl.cpp
+++ b/src/operator/RoundImpl.cpp
@@ -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)));
 }
diff --git a/unit_tests/operator/Test_RoundImpl.cpp b/unit_tests/operator/Test_RoundImpl.cpp
index e658b0616683633ce19b2284abb9d4fae7942a23..1c93eb5eb2b0a796d7d305ee7bc621473769d5f6 100644
--- a/unit_tests/operator/Test_RoundImpl.cpp
+++ b/unit_tests/operator/Test_RoundImpl.cpp
@@ -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]);
 
                 }