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 
172  void ConfigureGpuId(bool require_gpu);
177  [[nodiscard]] std::int32_t Threads() const;
181  [[nodiscard]] bool IsCPU() const { return Device().IsCPU(); }
185  [[nodiscard]] bool IsCUDA() const { return Device().IsCUDA(); }
189  [[nodiscard]] bool IsSyclDefault() const { return Device().IsSyclDefault(); }
193  [[nodiscard]] bool IsSyclCPU() const { return Device().IsSyclCPU(); }
197  [[nodiscard]] bool IsSyclGPU() const { return Device().IsSyclGPU(); }
201  [[nodiscard]] bool IsSycl() const { return IsSyclDefault()
202  || IsSyclCPU()
203  || IsSyclGPU(); }
204 
208  [[nodiscard]] DeviceOrd Device() const { return device_; }
212  [[nodiscard]] bst_d_ordinal_t Ordinal() const { return Device().ordinal; }
216  [[nodiscard]] std::string DeviceName() const { return Device().Name(); }
220  [[nodiscard]] CUDAContext const* CUDACtx() const;
221 
227  [[nodiscard]] Context MakeCUDA(bst_d_ordinal_t ordinal = 0) const {
228  Context ctx = *this;
229  return ctx.SetDevice(DeviceOrd::CUDA(ordinal));
230  }
234  [[nodiscard]] Context MakeCPU() const {
235  Context ctx = *this;
236  return ctx.SetDevice(DeviceOrd::CPU());
237  }
238 
242  template <typename CPUFn, typename CUDAFn>
243  decltype(auto) DispatchDevice(CPUFn&& cpu_fn, CUDAFn&& cuda_fn) const {
244  static_assert(std::is_same_v<std::invoke_result_t<CPUFn>, std::invoke_result_t<CUDAFn>>);
245  switch (this->Device().device) {
246  case DeviceOrd::kCPU:
247  return cpu_fn();
248  case DeviceOrd::kCUDA:
249  return cuda_fn();
250  default:
251  // Do not use the device name as this is likely an internal error, the name
252  // wouldn't be valid.
253  if (this->Device().IsSycl()) {
254  LOG(WARNING) << "The requested feature doesn't have SYCL specific implementation yet. "
255  << "CPU implementation is used";
256  return cpu_fn();
257  } else {
258  LOG(FATAL) << "Unknown device type:"
259  << static_cast<std::underlying_type_t<DeviceOrd::Type>>(this->Device().device);
260  break;
261  }
262  }
263  return std::invoke_result_t<CPUFn>();
264  }
265 
269  template <typename CPUFn, typename CUDAFn, typename SYCLFn>
270  decltype(auto) DispatchDevice(CPUFn&& cpu_fn, CUDAFn&& cuda_fn, SYCLFn&& sycl_fn) const {
271  static_assert(std::is_same_v<std::invoke_result_t<CPUFn>, std::invoke_result_t<SYCLFn>>);
272  if (this->Device().IsSycl()) {
273  return sycl_fn();
274  } else {
275  return DispatchDevice(cpu_fn, cuda_fn);
276  }
277  }
278 
279  // declare parameters
281  DMLC_DECLARE_FIELD(seed)
282  .set_default(kDefaultSeed)
283  .describe("Random number seed during training.");
284  DMLC_DECLARE_ALIAS(seed, random_state);
285  DMLC_DECLARE_FIELD(seed_per_iteration)
286  .set_default(false)
287  .describe("Seed PRNG determnisticly via iterator number.");
288  DMLC_DECLARE_FIELD(device).set_default(DeviceSym::CPU()).describe("Device ordinal.");
289  DMLC_DECLARE_FIELD(nthread).set_default(0).describe("Number of threads to use.");
290  DMLC_DECLARE_ALIAS(nthread, n_jobs);
291  DMLC_DECLARE_FIELD(fail_on_invalid_gpu_id)
292  .set_default(false)
293  .describe("Fail with error when gpu_id is invalid.");
294  DMLC_DECLARE_FIELD(validate_parameters)
295  .set_default(false)
296  .describe("Enable checking whether parameters are used or not.");
297  }
298 
299  private:
300  void SetDeviceOrdinal(Args const& kwargs);
301  Context& SetDevice(DeviceOrd d) {
302  this->device = (this->device_ = d).Name();
303  return *this;
304  }
305 
306  // mutable for lazy cuda context initialization. This avoids initializing CUDA at load.
307  // shared_ptr is used instead of unique_ptr as with unique_ptr it's difficult to define
308  // p_impl while trying to hide CUDA code from the host compiler.
309  mutable std::shared_ptr<CUDAContext> cuctx_;
310  // cached value for CFS CPU limit. (used in containerized env)
311  std::int32_t cfs_cpu_count_; // NOLINT
312 };
313 } // namespace xgboost
314 
315 #endif // XGBOOST_CONTEXT_H_
Defines configuration macros and basic types for xgboost.
Core data structure for multi-target trees.
Definition: base.h:87
std::vector< std::pair< std::string, std::string > > Args
Definition: base.h:310
std::ostream & operator<<(std::ostream &os, DeviceOrd ord)
std::int16_t bst_d_ordinal_t
Ordinal of a CUDA device.
Definition: base.h:125
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:243
bool fail_on_invalid_gpu_id
Definition: context.h:162
DeviceOrd Device() const
Get the current device and ordinal.
Definition: context.h:208
bool IsSycl() const
Is XGBoost running on any SYCL device?
Definition: context.h:201
std::string DeviceName() const
Name of the current device.
Definition: context.h:216
void ConfigureGpuId(bool require_gpu)
Configure the parameter ‘device’. Deprecated, will remove once gpu_id is removed.
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:227
bool IsCPU() const
Is XGBoost running on CPU?
Definition: context.h:181
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:185
bool IsSyclCPU() const
Is XGBoost running on a SYCL CPU?
Definition: context.h:193
std::int32_t nthread
Definition: context.h:156
Context MakeCPU() const
Make a CPU context based on the current context.
Definition: context.h:234
bool IsSyclGPU() const
Is XGBoost running on a SYCL GPU?
Definition: context.h:197
bool IsSyclDefault() const
Is XGBoost running on the default SYCL device?
Definition: context.h:189
DMLC_DECLARE_PARAMETER(Context)
Definition: context.h:280
bst_d_ordinal_t Ordinal() const
Get the CUDA device ordinal. -1 if XGBoost is running on CPU.
Definition: context.h:212
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