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