Extract floating point rounding routines. (#8771)

This commit is contained in:
Jiaming Yuan
2023-02-12 04:26:41 +08:00
committed by GitHub
parent e9c178f402
commit 70c9b885ef
3 changed files with 64 additions and 36 deletions

View File

@@ -0,0 +1,46 @@
/**
* Copyright 2020-2023 by XGBoost Contributors
*/
#ifndef XGBOOST_COMMON_DETERMINISTIC_CUH_
#define XGBOOST_COMMON_DETERMINISTIC_CUH_
#include <cmath>
#include <limits> // std::numeric_limits
#include "xgboost/base.h" // XGBOOST_DEVICE
namespace xgboost {
namespace common {
// Following 2 functions are slightly modified version of fbcuda.
/**
* \brief Constructs a rounding factor used to truncate elements in a sum such that the
* sum of the truncated elements is the same no matter what the order of the sum
* is.
*
* Algorithm 5: Reproducible Sequential Sum in 'Fast Reproducible Floating-Point
* Summation' by Demmel and Nguyen.
*/
template <typename T>
XGBOOST_DEVICE T CreateRoundingFactor(T max_abs, int n) {
T delta = max_abs / (static_cast<T>(1.0) -
static_cast<T>(2.0) * static_cast<T>(n) * std::numeric_limits<T>::epsilon());
// Calculate ceil(log_2(delta)).
// frexpf() calculates exp and returns `x` such that
// delta = x * 2^exp, where `x` in (-1.0, -0.5] U [0.5, 1).
// Because |x| < 1, exp is exactly ceil(log_2(delta)).
int exp;
std::frexp(delta, &exp);
// return M = 2 ^ ceil(log_2(delta))
return std::ldexp(static_cast<T>(1.0), exp);
}
template <typename T>
XGBOOST_DEVICE T TruncateWithRounding(T const rounding_factor, T const x) {
return (rounding_factor + x) - rounding_factor;
}
} // namespace common
} // namespace xgboost
#endif // XGBOOST_COMMON_DETERMINISTIC_CUH_