xgboost
common.h
Go to the documentation of this file.
1 
6 #ifndef XGBOOST_COMMON_COMMON_H_
7 #define XGBOOST_COMMON_COMMON_H_
8 
9 #include <xgboost/base.h>
10 #include <xgboost/logging.h>
11 
12 #include <exception>
13 #include <limits>
14 #include <type_traits>
15 #include <vector>
16 #include <string>
17 #include <sstream>
18 
19 #if defined(__CUDACC__)
20 #include <thrust/system/cuda/error.h>
21 #include <thrust/system_error.h>
22 
23 #define WITH_CUDA() true
24 
25 #else
26 
27 #define WITH_CUDA() false
28 
29 #endif // defined(__CUDACC__)
30 
31 namespace dh {
32 #if defined(__CUDACC__)
33 /*
34  * Error handling functions
35  */
36 #define safe_cuda(ans) ThrowOnCudaError((ans), __FILE__, __LINE__)
37 
38 inline cudaError_t ThrowOnCudaError(cudaError_t code, const char *file,
39  int line) {
40  if (code != cudaSuccess) {
41  LOG(FATAL) << thrust::system_error(code, thrust::cuda_category(),
42  std::string{file} + ": " + // NOLINT
43  std::to_string(line)).what();
44  }
45  return code;
46 }
47 #endif // defined(__CUDACC__)
48 } // namespace dh
49 
50 namespace xgboost {
51 namespace common {
57 inline std::vector<std::string> Split(const std::string& s, char delim) {
58  std::string item;
59  std::istringstream is(s);
60  std::vector<std::string> ret;
61  while (std::getline(is, item, delim)) {
62  ret.push_back(item);
63  }
64  return ret;
65 }
66 
67 // simple routine to convert any data to string
68 template<typename T>
69 inline std::string ToString(const T& data) {
70  std::ostringstream os;
71  os << data;
72  return os.str();
73 }
74 
75 /*
76  * Range iterator
77  */
78 class Range {
79  public:
80  using DifferenceType = int64_t;
81 
82  class Iterator {
83  friend class Range;
84 
85  public:
86  XGBOOST_DEVICE DifferenceType operator*() const { return i_; }
88  i_ += step_;
89  return *this;
90  }
92  Iterator res {*this};
93  i_ += step_;
94  return res;
95  }
96 
97  XGBOOST_DEVICE bool operator==(const Iterator &other) const {
98  return i_ >= other.i_;
99  }
100  XGBOOST_DEVICE bool operator!=(const Iterator &other) const {
101  return i_ < other.i_;
102  }
103 
104  XGBOOST_DEVICE void Step(DifferenceType s) { step_ = s; }
105 
106  protected:
107  XGBOOST_DEVICE explicit Iterator(DifferenceType start) : i_(start) {}
109  i_{start}, step_{step} {}
110 
111  public:
112  int64_t i_;
113  DifferenceType step_ = 1;
114  };
115 
116  XGBOOST_DEVICE Iterator begin() const { return begin_; } // NOLINT
117  XGBOOST_DEVICE Iterator end() const { return end_; } // NOLINT
118 
120  : begin_(begin), end_(end) {}
122  DifferenceType step)
123  : begin_(begin, step), end_(end) {}
124 
125  XGBOOST_DEVICE bool operator==(const Range& other) const {
126  return *begin_ == *other.begin_ && *end_ == *other.end_;
127  }
128  XGBOOST_DEVICE bool operator!=(const Range& other) const {
129  return !(*this == other);
130  }
131 
132  XGBOOST_DEVICE void Step(DifferenceType s) { begin_.Step(s); }
133 
134  private:
135  Iterator begin_;
136  Iterator end_;
137 };
138 
139 } // namespace common
141  static int AllVisible();
142 };
143 /* \brief set of devices across which HostDeviceVector can be distributed.
144  *
145  * Currently implemented as a range, but can be changed later to something else,
146  * e.g. a bitset
147  */
148 class GPUSet {
149  public:
150  using GpuIdType = int;
151  static constexpr GpuIdType kAll = -1;
152 
153  explicit GPUSet(int start = 0, int ndevices = 0)
154  : devices_(start, start + ndevices) {}
155 
156  static GPUSet Empty() { return GPUSet(); }
157 
158  static GPUSet Range(GpuIdType start, GpuIdType n_gpus) {
159  return n_gpus <= 0 ? Empty() : GPUSet{start, n_gpus};
160  }
162  static GPUSet All(GpuIdType gpu_id, GpuIdType n_gpus,
163  GpuIdType num_rows = std::numeric_limits<GpuIdType>::max()) {
164  CHECK_GE(gpu_id, 0) << "gpu_id must be >= 0.";
165  CHECK_GE(n_gpus, -1) << "n_gpus must be >= -1.";
166 
167  GpuIdType const n_devices_visible = AllVisible().Size();
168  if (n_devices_visible == 0 || n_gpus == 0) { return Empty(); }
169 
170  GpuIdType const n_available_devices = n_devices_visible - gpu_id;
171 
172  if (n_gpus == kAll) { // Use all devices starting from `gpu_id'.
173  CHECK(gpu_id < n_devices_visible)
174  << "\ngpu_id should be less than number of visible devices.\ngpu_id: "
175  << gpu_id
176  << ", number of visible devices: "
177  << n_devices_visible;
178  GpuIdType n_devices =
179  n_available_devices < num_rows ? n_available_devices : num_rows;
180  return Range(gpu_id, n_devices);
181  } else { // Use devices in ( gpu_id, gpu_id + n_gpus ).
182  CHECK_LE(n_gpus, n_available_devices)
183  << "Starting from gpu id: " << gpu_id << ", there are only "
184  << n_available_devices << " available devices, while n_gpus is set to: "
185  << n_gpus;
186  GpuIdType n_devices = n_gpus < num_rows ? n_gpus : num_rows;
187  return Range(gpu_id, n_devices);
188  }
189  }
190 
191  static GPUSet AllVisible() {
192  GpuIdType n = AllVisibleImpl::AllVisible();
193  return Range(0, n);
194  }
195 
196  size_t Size() const {
197  GpuIdType size = *devices_.end() - *devices_.begin();
198  GpuIdType res = size < 0 ? 0 : size;
199  return static_cast<size_t>(res);
200  }
201 
202  /*
203  * By default, we have two configurations of identifying device, one
204  * is the device id obtained from `cudaGetDevice'. But we sometimes
205  * store objects that allocated one for each device in a list, which
206  * requires a zero-based index.
207  *
208  * Hence, `DeviceId' converts a zero-based index to actual device id,
209  * `Index' converts a device id to a zero-based index.
210  */
211  GpuIdType DeviceId(size_t index) const {
212  GpuIdType result = *devices_.begin() + static_cast<GpuIdType>(index);
213  CHECK(Contains(result)) << "\nDevice " << result << " is not in GPUSet."
214  << "\nIndex: " << index
215  << "\nGPUSet: (" << *begin() << ", " << *end() << ")"
216  << std::endl;
217  return result;
218  }
219  size_t Index(GpuIdType device) const {
220  CHECK(Contains(device)) << "\nDevice " << device << " is not in GPUSet."
221  << "\nGPUSet: (" << *begin() << ", " << *end() << ")"
222  << std::endl;
223  size_t result = static_cast<size_t>(device - *devices_.begin());
224  return result;
225  }
226 
227  bool IsEmpty() const { return Size() == 0; }
228 
229  bool Contains(GpuIdType device) const {
230  return *devices_.begin() <= device && device < *devices_.end();
231  }
232 
233  common::Range::Iterator begin() const { return devices_.begin(); } // NOLINT
234  common::Range::Iterator end() const { return devices_.end(); } // NOLINT
235 
236  friend bool operator==(const GPUSet& lhs, const GPUSet& rhs) {
237  return lhs.devices_ == rhs.devices_;
238  }
239  friend bool operator!=(const GPUSet& lhs, const GPUSet& rhs) {
240  return !(lhs == rhs);
241  }
242 
243  private:
244  common::Range devices_;
245 };
246 
247 } // namespace xgboost
248 #endif // XGBOOST_COMMON_COMMON_H_
static GPUSet AllVisible()
Definition: common.h:191
GpuIdType DeviceId(size_t index) const
Definition: common.h:211
bool Contains(GpuIdType device) const
Definition: common.h:229
XGBOOST_DEVICE Iterator begin() const
Definition: common.h:116
Definition: common.h:140
friend bool operator!=(const GPUSet &lhs, const GPUSet &rhs)
Definition: common.h:239
XGBOOST_DEVICE Iterator(DifferenceType start)
Definition: common.h:107
Definition: common.h:148
XGBOOST_DEVICE bool operator!=(const Iterator &other) const
Definition: common.h:100
XGBOOST_DEVICE DifferenceType operator*() const
Definition: common.h:86
XGBOOST_DEVICE void Step(DifferenceType s)
Definition: common.h:132
XGBOOST_DEVICE Iterator operator++(int)
Definition: common.h:91
XGBOOST_DEVICE bool operator!=(const Range &other) const
Definition: common.h:128
Definition: common.h:78
GPUSet(int start=0, int ndevices=0)
Definition: common.h:153
int GpuIdType
Definition: common.h:150
int64_t DifferenceType
Definition: common.h:80
XGBOOST_DEVICE Iterator end() const
Definition: common.h:117
size_t Size() const
Definition: common.h:196
static GPUSet All(GpuIdType gpu_id, GpuIdType n_gpus, GpuIdType num_rows=std::numeric_limits< GpuIdType >::max())
n_gpus and num_rows both are upper bounds.
Definition: common.h:162
XGBOOST_DEVICE Iterator(DifferenceType start, DifferenceType step)
Definition: common.h:108
common::Range::Iterator end() const
Definition: common.h:234
std::vector< std::string > Split(const std::string &s, char delim)
Split a string by delimiter.
Definition: common.h:57
Definition: common.h:82
common::Range::Iterator begin() const
Definition: common.h:233
#define XGBOOST_DEVICE
Tag function as usable by device.
Definition: base.h:75
int64_t i_
Definition: common.h:112
namespace of xgboost
Definition: base.h:79
static GPUSet Range(GpuIdType start, GpuIdType n_gpus)
Definition: common.h:158
defines configuration macros of xgboost.
size_t Index(GpuIdType device) const
Definition: common.h:219
XGBOOST_DEVICE Range(DifferenceType begin, DifferenceType end)
Definition: common.h:119
XGBOOST_DEVICE bool operator==(const Iterator &other) const
Definition: common.h:97
XGBOOST_DEVICE const Iterator & operator++()
Definition: common.h:87
XGBOOST_DEVICE Range(DifferenceType begin, DifferenceType end, DifferenceType step)
Definition: common.h:121
XGBOOST_DEVICE bool operator==(const Range &other) const
Definition: common.h:125
friend bool operator==(const GPUSet &lhs, const GPUSet &rhs)
Definition: common.h:236
bool IsEmpty() const
Definition: common.h:227
std::string ToString(const T &data)
Definition: common.h:69
static GPUSet Empty()
Definition: common.h:156
XGBOOST_DEVICE void Step(DifferenceType s)
Definition: common.h:104
Definition: common.h:31