stop compiler optimizations with -ffast-math from break sum accumulator

This commit is contained in:
Hans Dembinski 2019-12-20 20:13:39 +01:00 committed by GitHub
parent b3a8158878
commit 1305445ce4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 28 additions and 16 deletions

View File

@ -48,12 +48,21 @@ public:
/// Increment sum by value /// Increment sum by value
sum& operator+=(const RealType& value) { sum& operator+=(const RealType& value) {
auto temp = large_ + value; // prevent optimization // prevent compiler optimization from destroying the algorithm
if (std::abs(large_) >= std::abs(value)) // when -ffast-math is enabled
small_ += (large_ - temp) + value; volatile RealType l;
else RealType s;
small_ += (value - temp) + large_; if (std::abs(large_) >= std::abs(value)) {
large_ = temp; l = large_;
s = value;
} else {
l = value;
s = large_;
}
large_ += value;
l -= large_;
l += s;
small_ += l;
return *this; return *this;
} }

View File

@ -16,9 +16,12 @@ namespace histogram {
namespace accumulators { namespace accumulators {
/// Holds sum of weights and its variance estimate /// Holds sum of weights and its variance estimate
template <typename RealType> template <class RealType>
class weighted_sum { class weighted_sum {
public: public:
using value_type = RealType;
using const_reference = const RealType&;
weighted_sum() = default; weighted_sum() = default;
explicit weighted_sum(const RealType& value) noexcept explicit weighted_sum(const RealType& value) noexcept
: sum_of_weights_(value), sum_of_weights_squared_(value) {} : sum_of_weights_(value), sum_of_weights_squared_(value) {}
@ -67,16 +70,13 @@ public:
} }
/// Return value of the sum. /// Return value of the sum.
const RealType& value() const noexcept { return sum_of_weights_; } const_reference value() const noexcept { return sum_of_weights_; }
/// Return estimated variance of the sum. /// Return estimated variance of the sum.
const RealType& variance() const noexcept { return sum_of_weights_squared_; } const_reference variance() const noexcept { return sum_of_weights_squared_; }
// lossy conversion must be explicit // lossy conversion must be explicit
template <class T> explicit operator const_reference() const { return sum_of_weights_; }
explicit operator T() const {
return static_cast<T>(sum_of_weights_);
}
template <class Archive> template <class Archive>
void serialize(Archive& ar, unsigned /* version */) { void serialize(Archive& ar, unsigned /* version */) {
@ -85,8 +85,8 @@ public:
} }
private: private:
RealType sum_of_weights_ = RealType(); value_type sum_of_weights_ = value_type();
RealType sum_of_weights_squared_ = RealType(); value_type sum_of_weights_squared_ = value_type();
}; };
} // namespace accumulators } // namespace accumulators

View File

@ -38,7 +38,10 @@ alias odr :
; ;
alias cxx14 : alias cxx14 :
[ run accumulators_test.cpp ] [ run accumulators_test.cpp : : :
# make sure sum accumulator works even with -ffast-math and optimizations
<toolset>gcc:<cxxflags>"-O3 -ffast-math"
<toolset>clang:<cxxflags>"-O3 -ffast-math" ]
[ run algorithm_project_test.cpp ] [ run algorithm_project_test.cpp ]
[ run algorithm_reduce_test.cpp ] [ run algorithm_reduce_test.cpp ]
[ run algorithm_sum_test.cpp ] [ run algorithm_sum_test.cpp ]