xgboost
context.h
Go to the documentation of this file.
1 
5 #ifndef XGBOOST_CONTEXT_H_
6 #define XGBOOST_CONTEXT_H_
7 
8 #include <xgboost/base.h> // for bst_d_ordinal_t
9 #include <xgboost/logging.h> // for CHECK_GE
10 #include <xgboost/parameter.h> // for XGBoostParameter
11 
12 #include <cstdint> // for int16_t, int32_t, int64_t
13 #include <memory> // for shared_ptr
14 #include <string> // for string, to_string
15 #include <type_traits> // for invoke_result_t, is_same_v, underlying_type_t
16 
17 namespace xgboost {
18 
19 struct CUDAContext;
20 
21 // symbolic names
22 struct DeviceSym {
23  static auto constexpr CPU() { return "cpu"; }
24  static auto constexpr CUDA() { return "cuda"; }
25  static auto constexpr SyclDefault() { return "sycl"; }
26  static auto constexpr SyclCPU() { return "sycl:cpu"; }
27  static auto constexpr SyclGPU() { return "sycl:gpu"; }
28 };
29 
34 struct DeviceOrd {
35  // Constant representing the device ID of CPU.
36  static bst_d_ordinal_t constexpr CPUOrdinal() { return -1; }
37  static bst_d_ordinal_t constexpr InvalidOrdinal() { return -2; }
38 
39  enum Type : std::int16_t { kCPU = 0, kCUDA = 1,
40  kSyclDefault = 2, kSyclCPU = 3, kSyclGPU = 4} device{kCPU};
41  // CUDA or Sycl device ordinal.
43 
44  [[nodiscard]] bool IsCUDA() const { return device == kCUDA; }
45  [[nodiscard]] bool IsCPU() const { return device == kCPU; }
46  [[nodiscard]] bool IsSyclDefault() const { return device == kSyclDefault; }
47  [[nodiscard]] bool IsSyclCPU() const { return device == kSyclCPU; }
48  [[nodiscard]] bool IsSyclGPU() const { return device == kSyclGPU; }
49  [[nodiscard]] bool IsSycl() const { return (IsSyclDefault() ||
50  IsSyclCPU() ||
51  IsSyclGPU()); }
52 
53  constexpr DeviceOrd() = default;
54  constexpr DeviceOrd(Type type, bst_d_ordinal_t ord) : device{type}, ordinal{ord} {}
55 
56  constexpr DeviceOrd(DeviceOrd const& that) = default;
57  constexpr DeviceOrd& operator=(DeviceOrd const& that) = default;
58  constexpr DeviceOrd(DeviceOrd&& that) = default;
59  constexpr DeviceOrd& operator=(DeviceOrd&& that) = default;
60 
64  [[nodiscard]] constexpr static auto CPU() { return DeviceOrd{kCPU, CPUOrdinal()}; }
70  [[nodiscard]] static constexpr auto CUDA(bst_d_ordinal_t ordinal) {
71  return DeviceOrd{kCUDA, ordinal};
72  }
78  [[nodiscard]] constexpr static auto SyclDefault(bst_d_ordinal_t ordinal = -1) {
80  }
86  [[nodiscard]] constexpr static auto SyclCPU(bst_d_ordinal_t ordinal = -1) {
87  return DeviceOrd{kSyclCPU, ordinal};
88  }
89 
95  [[nodiscard]] constexpr static auto SyclGPU(bst_d_ordinal_t ordinal = -1) {
96  return DeviceOrd{kSyclGPU, ordinal};
97  }
98 
99  [[nodiscard]] bool operator==(DeviceOrd const& that) const {
100  return device == that.device && ordinal == that.ordinal;
101  }
102  [[nodiscard]] bool operator!=(DeviceOrd const& that) const { return !(*this == that); }
106  [[nodiscard]] std::string Name() const {
107  switch (device) {
108  case DeviceOrd::kCPU:
109  return DeviceSym::CPU();
110  case DeviceOrd::kCUDA:
111  return DeviceSym::CUDA() + (':' + std::to_string(ordinal));
113  return DeviceSym::SyclDefault() + (':' + std::to_string(ordinal));
114  case DeviceOrd::kSyclCPU:
115  return DeviceSym::SyclCPU() + (':' + std::to_string(ordinal));
116  case DeviceOrd::kSyclGPU:
117  return DeviceSym::SyclGPU() + (':' + std::to_string(ordinal));
118  default: {
119  LOG(FATAL) << "Unknown device.";
120  return "";
121  }
122  }
123  }
124 };
125 
126 static_assert(sizeof(DeviceOrd) == sizeof(std::int32_t));
127 
128 std::ostream& operator<<(std::ostream& os, DeviceOrd ord);
129 
133 struct Context : public XGBoostParameter<Context> {
134  private:
135  // User interfacing parameter for device ordinal
136  std::string device{DeviceSym::CPU()}; // NOLINT
137  // The device ordinal set by user
138  DeviceOrd device_{DeviceOrd::CPU()};
139 
140  public:
141  static std::int64_t constexpr kDefaultSeed = 0;
142 
143  public:
145 
146  void Init(Args const& kwargs);
147 
148  template <typename Container>
149  Args UpdateAllowUnknown(Container const& kwargs) {
151  this->SetDeviceOrdinal(kwargs);
152  return args;
153  }
154 
155  // The number of threads to use if OpenMP is enabled. If equals 0, use the system default.
156  std::int32_t nthread{0}; // NOLINT
157  // stored random seed
158  std::int64_t seed{kDefaultSeed};
159  // whether seed the PRNG each iteration
160  bool seed_per_iteration{false};
161  // fail when gpu_id is invalid
163  bool validate_parameters{false};
164 
169  [[nodiscard]] std::int32_t Threads() const;
173  [[nodiscard]] bool IsCPU() const { return Device().IsCPU(); }
177  [[nodiscard]] bool IsCUDA() const { return Device().IsCUDA(); }
181  [[nodiscard]] bool IsSyclDefault() const { return Device().IsSyclDefault(); }
185  [[nodiscard]] bool IsSyclCPU() const { return Device().IsSyclCPU(); }
189  [[nodiscard]] bool IsSyclGPU() const { return Device().IsSyclGPU(); }
193  [[nodiscard]] bool IsSycl() const { return IsSyclDefault()
194  || IsSyclCPU()
195  || IsSyclGPU(); }
196 
200  [[nodiscard]] DeviceOrd Device() const { return device_; }
201 
206  [[nodiscard]] DeviceOrd DeviceFP64() const;
207 
211  [[nodiscard]] bst_d_ordinal_t Ordinal() const { return Device().ordinal; }
215  [[nodiscard]] std::string DeviceName() const { return Device().Name(); }
219  [[nodiscard]] CUDAContext const* CUDACtx() const;
220 
226  [[nodiscard]] Context MakeCUDA(bst_d_ordinal_t ordinal = 0) const {
227  Context ctx = *this;
228  return ctx.SetDevice(DeviceOrd::CUDA(ordinal));
229  }
233  [[nodiscard]] Context MakeCPU() const {
234  Context ctx = *this;
235  return ctx.SetDevice(DeviceOrd::CPU());
236  }
237 
241  template <typename CPUFn, typename CUDAFn>
242  decltype(auto) DispatchDevice(CPUFn&& cpu_fn, CUDAFn&& cuda_fn) const {
243  static_assert(std::is_same_v<std::invoke_result_t<CPUFn>, std::invoke_result_t<CUDAFn>>);
244  switch (this->Device().device) {
245  case DeviceOrd::kCPU:
246  return cpu_fn();
247  case DeviceOrd::kCUDA:
248  return cuda_fn();
249  default:
250  // Do not use the device name as this is likely an internal error, the name
251  // wouldn't be valid.
252  if (this->Device().IsSycl()) {
253  LOG(WARNING) << "The requested feature doesn't have SYCL specific implementation yet. "
254  << "CPU implementation is used";
255  return cpu_fn();
256  } else {
257  LOG(FATAL) << "Unknown device type:"
258  << static_cast<std::underlying_type_t<DeviceOrd::Type>>(this->Device().device);
259  break;
260  }
261  }
262  return std::invoke_result_t<CPUFn>();
263  }
264 
268  template <typename CPUFn, typename CUDAFn, typename SYCLFn>
269  decltype(auto) DispatchDevice(CPUFn&& cpu_fn, CUDAFn&& cuda_fn, SYCLFn&& sycl_fn) const {
270  static_assert(std::is_same_v<std::invoke_result_t<CPUFn>, std::invoke_result_t<SYCLFn>>);
271  if (this->Device().IsSycl()) {
272  return sycl_fn();
273  } else {
274  return DispatchDevice(cpu_fn, cuda_fn);
275  }
276  }
277 
278  // declare parameters
280  DMLC_DECLARE_FIELD(seed)
281  .set_default(kDefaultSeed)
282  .describe("Random number seed during training.");
283  DMLC_DECLARE_ALIAS(seed, random_state);
284  DMLC_DECLARE_FIELD(seed_per_iteration)
285  .set_default(false)
286  .describe("Seed PRNG determnisticly via iterator number.");
287  DMLC_DECLARE_FIELD(device).set_default(DeviceSym::CPU()).describe("Device ordinal.");
288  DMLC_DECLARE_FIELD(nthread).set_default(0).describe("Number of threads to use.");
289  DMLC_DECLARE_ALIAS(nthread, n_jobs);
290  DMLC_DECLARE_FIELD(fail_on_invalid_gpu_id)
291  .set_default(false)
292  .describe("Fail with error when gpu_id is invalid.");
293  DMLC_DECLARE_FIELD(validate_parameters)
294  .set_default(false)
295  .describe("Enable checking whether parameters are used or not.");
296  }
297 
298  private:
299  void SetDeviceOrdinal(Args const& kwargs);
300  Context& SetDevice(DeviceOrd d) {
301  this->device = (this->device_ = d).Name();
302  return *this;
303  }
304 
305  // mutable for lazy cuda context initialization. This avoids initializing CUDA at load.
306  // shared_ptr is used instead of unique_ptr as with unique_ptr it's difficult to define
307  // p_impl while trying to hide CUDA code from the host compiler.
308  mutable std::shared_ptr<CUDAContext> cuctx_;
309  // cached value for CFS CPU limit. (used in containerized env)
310  std::int32_t cfs_cpu_count_; // NOLINT
311 };
312 } // namespace xgboost
313 
314 #endif // XGBOOST_CONTEXT_H_
Defines configuration macros and basic types for xgboost.
Learner interface that integrates objective, gbm and evaluation together. This is the user facing XGB...
Definition: base.h:89
std::vector< std::pair< std::string, std::string > > Args
Definition: base.h:306
std::ostream & operator<<(std::ostream &os, DeviceOrd ord)
std::int16_t bst_d_ordinal_t
Ordinal of a CUDA device.
Definition: base.h:131
macro for using C++11 enum class as DMLC parameter
Runtime context for XGBoost. Contains information like threads and device.
Definition: context.h:133
decltype(auto) DispatchDevice(CPUFn &&cpu_fn, CUDAFn &&cuda_fn) const
Call function based on the current device.
Definition: context.h:242
bool fail_on_invalid_gpu_id
Definition: context.h:162
DeviceOrd Device() const
Get the current device and ordinal.
Definition: context.h:200
bool IsSycl() const
Is XGBoost running on any SYCL device?
Definition: context.h:193
std::string DeviceName() const
Name of the current device.
Definition: context.h:215
DeviceOrd DeviceFP64() const
Get the current device and ordinal, if it supports fp64, otherwise returns default CPU.
bool seed_per_iteration
Definition: context.h:160
std::int32_t Threads() const
Returns the automatically chosen number of threads based on the nthread parameter and the system sett...
bool validate_parameters
Definition: context.h:163
std::int64_t seed
Definition: context.h:158
Context MakeCUDA(bst_d_ordinal_t ordinal=0) const
Make a CUDA context based on the current context.
Definition: context.h:226
bool IsCPU() const
Is XGBoost running on CPU?
Definition: context.h:173
CUDAContext const * CUDACtx() const
Get a CUDA device context for allocator and stream.
static constexpr std::int64_t kDefaultSeed
Definition: context.h:141
bool IsCUDA() const
Is XGBoost running on a CUDA device?
Definition: context.h:177
bool IsSyclCPU() const
Is XGBoost running on a SYCL CPU?
Definition: context.h:185
std::int32_t nthread
Definition: context.h:156
Context MakeCPU() const
Make a CPU context based on the current context.
Definition: context.h:233
bool IsSyclGPU() const
Is XGBoost running on a SYCL GPU?
Definition: context.h:189
bool IsSyclDefault() const
Is XGBoost running on the default SYCL device?
Definition: context.h:181
DMLC_DECLARE_PARAMETER(Context)
Definition: context.h:279
bst_d_ordinal_t Ordinal() const
Get the CUDA device ordinal. -1 if XGBoost is running on CPU.
Definition: context.h:211
void Init(Args const &kwargs)
Args UpdateAllowUnknown(Container const &kwargs)
Definition: context.h:149
A type for device ordinal. The type is packed into 32-bit for efficient use in viewing types like lin...
Definition: context.h:34
constexpr static auto SyclGPU(bst_d_ordinal_t ordinal=-1)
Constructor for SYCL GPU.
Definition: context.h:95
bool operator==(DeviceOrd const &that) const
Definition: context.h:99
bool IsCUDA() const
Definition: context.h:44
bool operator!=(DeviceOrd const &that) const
Definition: context.h:102
bool IsSyclCPU() const
Definition: context.h:47
std::string Name() const
Get a string representation of the device and the ordinal.
Definition: context.h:106
enum xgboost::DeviceOrd::Type kCPU
bool IsSyclDefault() const
Definition: context.h:46
constexpr DeviceOrd & operator=(DeviceOrd &&that)=default
constexpr DeviceOrd(DeviceOrd &&that)=default
constexpr DeviceOrd & operator=(DeviceOrd const &that)=default
Type
Definition: context.h:39
@ kSyclGPU
Definition: context.h:40
@ kSyclDefault
Definition: context.h:40
@ kCUDA
Definition: context.h:39
@ kSyclCPU
Definition: context.h:40
bool IsSyclGPU() const
Definition: context.h:48
bool IsCPU() const
Definition: context.h:45
static constexpr bst_d_ordinal_t InvalidOrdinal()
Definition: context.h:37
static constexpr bst_d_ordinal_t CPUOrdinal()
Definition: context.h:36
constexpr DeviceOrd(Type type, bst_d_ordinal_t ord)
Definition: context.h:54
constexpr static auto SyclCPU(bst_d_ordinal_t ordinal=-1)
Constructor for SYCL CPU.
Definition: context.h:86
constexpr DeviceOrd()=default
bool IsSycl() const
Definition: context.h:49
static constexpr auto CUDA(bst_d_ordinal_t ordinal)
Constructor for CUDA device.
Definition: context.h:70
constexpr DeviceOrd(DeviceOrd const &that)=default
constexpr static auto CPU()
Constructor for CPU.
Definition: context.h:64
constexpr static auto SyclDefault(bst_d_ordinal_t ordinal=-1)
Constructor for SYCL.
Definition: context.h:78
bst_d_ordinal_t ordinal
Definition: context.h:42
Definition: context.h:22
static constexpr auto CUDA()
Definition: context.h:24
static constexpr auto CPU()
Definition: context.h:23
static constexpr auto SyclDefault()
Definition: context.h:25
static constexpr auto SyclGPU()
Definition: context.h:27
static constexpr auto SyclCPU()
Definition: context.h:26
Definition: parameter.h:84
Args UpdateAllowUnknown(Container const &kwargs)
Definition: parameter.h:90