1 /*! 2 * Copyright (c) 2015 by Contributors 3 * \file base.h 4 * \brief defines configuration macros of xgboost. 5 */ 6 #ifndef XGBOOST_BASE_H_ 7 #define XGBOOST_BASE_H_ 8 9 #include <dmlc/base.h> 10 #include <dmlc/omp.h> 11 #include <cmath> 12 #include <iostream> 13 #include <vector> 14 #include <string> 15 #include <utility> 16 17 /*! 18 * \brief string flag for R library, to leave hooks when needed. 19 */ 20 #ifndef XGBOOST_STRICT_R_MODE 21 #define XGBOOST_STRICT_R_MODE 0 22 #endif // XGBOOST_STRICT_R_MODE 23 24 /*! 25 * \brief Whether always log console message with time. 26 * It will display like, with timestamp appended to head of the message. 27 * "[21:47:50] 6513x126 matrix with 143286 entries loaded from 28 * ../data/agaricus.txt.train" 29 */ 30 #ifndef XGBOOST_LOG_WITH_TIME 31 #define XGBOOST_LOG_WITH_TIME 1 32 #endif // XGBOOST_LOG_WITH_TIME 33 34 /*! 35 * \brief Whether customize the logger outputs. 36 */ 37 #ifndef XGBOOST_CUSTOMIZE_LOGGER 38 #define XGBOOST_CUSTOMIZE_LOGGER XGBOOST_STRICT_R_MODE 39 #endif // XGBOOST_CUSTOMIZE_LOGGER 40 41 /*! 42 * \brief Whether to customize global PRNG. 43 */ 44 #ifndef XGBOOST_CUSTOMIZE_GLOBAL_PRNG 45 #define XGBOOST_CUSTOMIZE_GLOBAL_PRNG XGBOOST_STRICT_R_MODE 46 #endif // XGBOOST_CUSTOMIZE_GLOBAL_PRNG 47 48 /*! 49 * \brief Check if alignas(*) keyword is supported. (g++ 4.8 or higher) 50 */ 51 #if defined(__GNUC__) && ((__GNUC__ == 4 && __GNUC_MINOR__ >= 8) || __GNUC__ > 4) 52 #define XGBOOST_ALIGNAS(X) alignas(X) 53 #else 54 #define XGBOOST_ALIGNAS(X) 55 #endif // defined(__GNUC__) && ((__GNUC__ == 4 && __GNUC_MINOR__ >= 8) || __GNUC__ > 4) 56 57 #if defined(__GNUC__) && ((__GNUC__ == 4 && __GNUC_MINOR__ >= 8) || __GNUC__ > 4) && \ 58 !defined(__CUDACC__) && !defined(__sun) && !defined(sun) 59 #include <parallel/algorithm> 60 #define XGBOOST_PARALLEL_SORT(X, Y, Z) __gnu_parallel::sort((X), (Y), (Z)) 61 #define XGBOOST_PARALLEL_STABLE_SORT(X, Y, Z) \ 62 __gnu_parallel::stable_sort((X), (Y), (Z)) 63 #elif defined(_MSC_VER) && (!__INTEL_COMPILER) 64 #include <ppl.h> 65 #define XGBOOST_PARALLEL_SORT(X, Y, Z) concurrency::parallel_sort((X), (Y), (Z)) 66 #define XGBOOST_PARALLEL_STABLE_SORT(X, Y, Z) std::stable_sort((X), (Y), (Z)) 67 #else 68 #define XGBOOST_PARALLEL_SORT(X, Y, Z) std::sort((X), (Y), (Z)) 69 #define XGBOOST_PARALLEL_STABLE_SORT(X, Y, Z) std::stable_sort((X), (Y), (Z)) 70 #endif // GLIBC VERSION 71 72 #if defined(__GNUC__) 73 #define XGBOOST_EXPECT(cond, ret) __builtin_expect((cond), (ret)) 74 #else 75 #define XGBOOST_EXPECT(cond, ret) (cond) 76 #endif // defined(__GNUC__) 77 78 /*! 79 * \brief Tag function as usable by device 80 */ 81 #if defined (__CUDA__) || defined(__NVCC__) 82 #define XGBOOST_DEVICE __host__ __device__ 83 #else 84 #define XGBOOST_DEVICE 85 #endif // defined (__CUDA__) || defined(__NVCC__) 86 87 #if defined(__CUDA__) || defined(__CUDACC__) 88 #define XGBOOST_HOST_DEV_INLINE XGBOOST_DEVICE __forceinline__ 89 #define XGBOOST_DEV_INLINE __device__ __forceinline__ 90 #else 91 #define XGBOOST_HOST_DEV_INLINE 92 #define XGBOOST_DEV_INLINE 93 #endif // defined(__CUDA__) || defined(__CUDACC__) 94 95 // These check are for Makefile. 96 #if !defined(XGBOOST_MM_PREFETCH_PRESENT) && !defined(XGBOOST_BUILTIN_PREFETCH_PRESENT) 97 /* default logic for software pre-fetching */ 98 #if (defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_AMD64))) || defined(__INTEL_COMPILER) 99 // Enable _mm_prefetch for Intel compiler and MSVC+x86 100 #define XGBOOST_MM_PREFETCH_PRESENT 101 #define XGBOOST_BUILTIN_PREFETCH_PRESENT 102 #elif defined(__GNUC__) 103 // Enable __builtin_prefetch for GCC 104 #define XGBOOST_BUILTIN_PREFETCH_PRESENT 105 #endif // GUARDS 106 107 #endif // !defined(XGBOOST_MM_PREFETCH_PRESENT) && !defined() 108 109 /*! \brief namespace of xgboost*/ 110 namespace xgboost { 111 112 /*! \brief unsigned integer type used for feature index. */ 113 using bst_uint = uint32_t; // NOLINT 114 /*! \brief integer type. */ 115 using bst_int = int32_t; // NOLINT 116 /*! \brief unsigned long integers */ 117 using bst_ulong = uint64_t; // NOLINT 118 /*! \brief float type, used for storing statistics */ 119 using bst_float = float; // NOLINT 120 /*! \brief Categorical value type. */ 121 using bst_cat_t = int32_t; // NOLINT 122 /*! \brief Type for data column (feature) index. */ 123 using bst_feature_t = uint32_t; // NOLINT 124 /*! \brief Type for data row index. 125 * 126 * Be careful `std::size_t' is implementation-defined. Meaning that the binary 127 * representation of DMatrix might not be portable across platform. Booster model should 128 * be portable as parameters are floating points. 129 */ 130 using bst_row_t = std::size_t; // NOLINT 131 /*! \brief Type for tree node index. */ 132 using bst_node_t = int32_t; // NOLINT 133 /*! \brief Type for ranking group index. */ 134 using bst_group_t = uint32_t; // NOLINT 135 136 namespace detail { 137 /*! \brief Implementation of gradient statistics pair. Template specialisation 138 * may be used to overload different gradients types e.g. low precision, high 139 * precision, integer, floating point. */ 140 template <typename T> 141 class GradientPairInternal { 142 /*! \brief gradient statistics */ 143 T grad_; 144 /*! \brief second order gradient statistics */ 145 T hess_; 146 SetGrad(T g)147 XGBOOST_DEVICE void SetGrad(T g) { grad_ = g; } SetHess(T h)148 XGBOOST_DEVICE void SetHess(T h) { hess_ = h; } 149 150 public: 151 using ValueT = T; 152 Add(const ValueT & grad,const ValueT & hess)153 inline void Add(const ValueT& grad, const ValueT& hess) { 154 grad_ += grad; 155 hess_ += hess; 156 } 157 Reduce(GradientPairInternal<T> & a,const GradientPairInternal<T> & b)158 inline static void Reduce(GradientPairInternal<T>& a, const GradientPairInternal<T>& b) { // NOLINT(*) 159 a += b; 160 } 161 GradientPairInternal()162 XGBOOST_DEVICE GradientPairInternal() : grad_(0), hess_(0) {} 163 GradientPairInternal(T grad,T hess)164 XGBOOST_DEVICE GradientPairInternal(T grad, T hess) { 165 SetGrad(grad); 166 SetHess(hess); 167 } 168 169 // Copy constructor if of same value type, marked as default to be trivially_copyable 170 GradientPairInternal(const GradientPairInternal<T> &g) = default; 171 172 // Copy constructor if different value type - use getters and setters to 173 // perform conversion 174 template <typename T2> GradientPairInternal(const GradientPairInternal<T2> & g)175 XGBOOST_DEVICE explicit GradientPairInternal(const GradientPairInternal<T2> &g) { 176 SetGrad(g.GetGrad()); 177 SetHess(g.GetHess()); 178 } 179 GetGrad()180 XGBOOST_DEVICE T GetGrad() const { return grad_; } GetHess()181 XGBOOST_DEVICE T GetHess() const { return hess_; } 182 183 XGBOOST_DEVICE GradientPairInternal<T> &operator+=( 184 const GradientPairInternal<T> &rhs) { 185 grad_ += rhs.grad_; 186 hess_ += rhs.hess_; 187 return *this; 188 } 189 190 XGBOOST_DEVICE GradientPairInternal<T> operator+( 191 const GradientPairInternal<T> &rhs) const { 192 GradientPairInternal<T> g; 193 g.grad_ = grad_ + rhs.grad_; 194 g.hess_ = hess_ + rhs.hess_; 195 return g; 196 } 197 198 XGBOOST_DEVICE GradientPairInternal<T> &operator-=( 199 const GradientPairInternal<T> &rhs) { 200 grad_ -= rhs.grad_; 201 hess_ -= rhs.hess_; 202 return *this; 203 } 204 205 XGBOOST_DEVICE GradientPairInternal<T> operator-( 206 const GradientPairInternal<T> &rhs) const { 207 GradientPairInternal<T> g; 208 g.grad_ = grad_ - rhs.grad_; 209 g.hess_ = hess_ - rhs.hess_; 210 return g; 211 } 212 213 XGBOOST_DEVICE GradientPairInternal<T> &operator*=(float multiplier) { 214 grad_ *= multiplier; 215 hess_ *= multiplier; 216 return *this; 217 } 218 219 XGBOOST_DEVICE GradientPairInternal<T> operator*(float multiplier) const { 220 GradientPairInternal<T> g; 221 g.grad_ = grad_ * multiplier; 222 g.hess_ = hess_ * multiplier; 223 return g; 224 } 225 226 XGBOOST_DEVICE GradientPairInternal<T> &operator/=(float divisor) { 227 grad_ /= divisor; 228 hess_ /= divisor; 229 return *this; 230 } 231 232 XGBOOST_DEVICE GradientPairInternal<T> operator/(float divisor) const { 233 GradientPairInternal<T> g; 234 g.grad_ = grad_ / divisor; 235 g.hess_ = hess_ / divisor; 236 return g; 237 } 238 239 XGBOOST_DEVICE bool operator==(const GradientPairInternal<T> &rhs) const { 240 return grad_ == rhs.grad_ && hess_ == rhs.hess_; 241 } 242 GradientPairInternal(int value)243 XGBOOST_DEVICE explicit GradientPairInternal(int value) { 244 *this = GradientPairInternal<T>(static_cast<float>(value), 245 static_cast<float>(value)); 246 } 247 248 friend std::ostream &operator<<(std::ostream &os, 249 const GradientPairInternal<T> &g) { 250 os << g.GetGrad() << "/" << g.GetHess(); 251 return os; 252 } 253 }; 254 } // namespace detail 255 256 /*! \brief gradient statistics pair usually needed in gradient boosting */ 257 using GradientPair = detail::GradientPairInternal<float>; 258 /*! \brief High precision gradient statistics pair */ 259 using GradientPairPrecise = detail::GradientPairInternal<double>; 260 /*! \brief Fixed point representation for gradient pair. */ 261 using GradientPairInt32 = detail::GradientPairInternal<int>; 262 /*! \brief Fixed point representation for high precision gradient pair. */ 263 using GradientPairInt64 = detail::GradientPairInternal<int64_t>; 264 265 using Args = std::vector<std::pair<std::string, std::string> >; 266 267 /*! \brief small eps gap for minimum split decision. */ 268 constexpr bst_float kRtEps = 1e-6f; 269 270 /*! \brief define unsigned long for openmp loop */ 271 using omp_ulong = dmlc::omp_ulong; // NOLINT 272 /*! \brief define unsigned int for openmp loop */ 273 using bst_omp_uint = dmlc::omp_uint; // NOLINT 274 /*! \brief Type used for representing version number in binary form.*/ 275 using XGBoostVersionT = int32_t; 276 277 /*! 278 * \brief define compatible keywords in g++ 279 * Used to support g++-4.6 and g++4.7 280 */ 281 #if DMLC_USE_CXX11 && defined(__GNUC__) && !defined(__clang_version__) 282 #if __GNUC__ == 4 && __GNUC_MINOR__ < 8 283 #define override 284 #define final 285 #endif // __GNUC__ == 4 && __GNUC_MINOR__ < 8 286 #endif // DMLC_USE_CXX11 && defined(__GNUC__) && !defined(__clang_version__) 287 } // namespace xgboost 288 289 #endif // XGBOOST_BASE_H_ 290