Medial Code Documentation
Loading...
Searching...
No Matches
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
17namespace xgboost {
18
19struct CUDAContext;
20
21// symbolic names
22struct DeviceSym {
23 static auto constexpr CPU() { return "cpu"; }
24 static auto constexpr CUDA() { return "cuda"; }
25};
26
31struct DeviceOrd {
32 enum Type : std::int16_t { kCPU = 0, kCUDA = 1 } device{kCPU};
33 // CUDA device ordinal.
34 bst_d_ordinal_t ordinal{-1};
35
36 [[nodiscard]] bool IsCUDA() const { return device == kCUDA; }
37 [[nodiscard]] bool IsCPU() const { return device == kCPU; }
38
39 DeviceOrd() = default;
40 constexpr DeviceOrd(Type type, bst_d_ordinal_t ord) : device{type}, ordinal{ord} {}
41
42 DeviceOrd(DeviceOrd const& that) = default;
43 DeviceOrd& operator=(DeviceOrd const& that) = default;
44 DeviceOrd(DeviceOrd&& that) = default;
45 DeviceOrd& operator=(DeviceOrd&& that) = default;
46
50 [[nodiscard]] constexpr static auto CPU() { return DeviceOrd{kCPU, -1}; }
56 [[nodiscard]] static auto CUDA(bst_d_ordinal_t ordinal) { return DeviceOrd{kCUDA, ordinal}; }
57
58 [[nodiscard]] bool operator==(DeviceOrd const& that) const {
59 return device == that.device && ordinal == that.ordinal;
60 }
61 [[nodiscard]] bool operator!=(DeviceOrd const& that) const { return !(*this == that); }
65 [[nodiscard]] std::string Name() const {
66 switch (device) {
67 case DeviceOrd::kCPU:
68 return DeviceSym::CPU();
69 case DeviceOrd::kCUDA:
70 return DeviceSym::CUDA() + (':' + std::to_string(ordinal));
71 default: {
72 LOG(FATAL) << "Unknown device.";
73 return "";
74 }
75 }
76 }
77};
78
79static_assert(sizeof(DeviceOrd) == sizeof(std::int32_t));
80
84struct Context : public XGBoostParameter<Context> {
85 private:
86 std::string device{DeviceSym::CPU()}; // NOLINT
87 // The device object for the current context. We are in the middle of replacing the
88 // `gpu_id` with this device field.
89 DeviceOrd device_{DeviceOrd::CPU()};
90
91 public:
92 // Constant representing the device ID of CPU.
93 static bst_d_ordinal_t constexpr kCpuId = -1;
94 static bst_d_ordinal_t constexpr InvalidOrdinal() { return -2; }
95 static std::int64_t constexpr kDefaultSeed = 0;
96
97 public:
98 Context();
99
100 template <typename Container>
101 Args UpdateAllowUnknown(Container const& kwargs) {
103 this->SetDeviceOrdinal(kwargs);
104 return args;
105 }
106
107 std::int32_t gpu_id{kCpuId};
108 // The number of threads to use if OpenMP is enabled. If equals 0, use the system default.
109 std::int32_t nthread{0}; // NOLINT
110 // stored random seed
111 std::int64_t seed{kDefaultSeed};
112 // whether seed the PRNG each iteration
113 bool seed_per_iteration{false};
114 // fail when gpu_id is invalid
115 bool fail_on_invalid_gpu_id{false};
116 bool validate_parameters{false};
117
124 void ConfigureGpuId(bool require_gpu);
129 [[nodiscard]] std::int32_t Threads() const;
133 [[nodiscard]] bool IsCPU() const { return Device().IsCPU(); }
137 [[nodiscard]] bool IsCUDA() const { return Device().IsCUDA(); }
141 [[nodiscard]] DeviceOrd Device() const { return device_; }
145 [[nodiscard]] bst_d_ordinal_t Ordinal() const { return Device().ordinal; }
149 [[nodiscard]] std::string DeviceName() const { return Device().Name(); }
153 [[nodiscard]] CUDAContext const* CUDACtx() const;
154
160 [[nodiscard]] Context MakeCUDA(bst_d_ordinal_t ordinal = 0) const {
161 Context ctx = *this;
162 return ctx.SetDevice(DeviceOrd::CUDA(ordinal));
163 }
167 [[nodiscard]] Context MakeCPU() const {
168 Context ctx = *this;
169 return ctx.SetDevice(DeviceOrd::CPU());
170 }
174 template <typename CPUFn, typename CUDAFn>
175 decltype(auto) DispatchDevice(CPUFn&& cpu_fn, CUDAFn&& cuda_fn) const {
176 static_assert(std::is_same_v<std::invoke_result_t<CPUFn>, std::invoke_result_t<CUDAFn>>);
177 switch (this->Device().device) {
178 case DeviceOrd::kCPU:
179 return cpu_fn();
180 case DeviceOrd::kCUDA:
181 return cuda_fn();
182 default:
183 // Do not use the device name as this is likely an internal error, the name
184 // wouldn't be valid.
185 LOG(FATAL) << "Unknown device type:"
186 << static_cast<std::underlying_type_t<DeviceOrd::Type>>(this->Device().device);
187 break;
188 }
189 return std::invoke_result_t<CPUFn>();
190 }
191
192 // declare parameters
193 DMLC_DECLARE_PARAMETER(Context) {
194 DMLC_DECLARE_FIELD(seed)
195 .set_default(kDefaultSeed)
196 .describe("Random number seed during training.");
197 DMLC_DECLARE_ALIAS(seed, random_state);
198 DMLC_DECLARE_FIELD(seed_per_iteration)
199 .set_default(false)
200 .describe("Seed PRNG determnisticly via iterator number.");
201 DMLC_DECLARE_FIELD(device).set_default(DeviceSym::CPU()).describe("Device ordinal.");
202 DMLC_DECLARE_FIELD(nthread).set_default(0).describe("Number of threads to use.");
203 DMLC_DECLARE_ALIAS(nthread, n_jobs);
204 DMLC_DECLARE_FIELD(fail_on_invalid_gpu_id)
205 .set_default(false)
206 .describe("Fail with error when gpu_id is invalid.");
207 DMLC_DECLARE_FIELD(validate_parameters)
208 .set_default(false)
209 .describe("Enable checking whether parameters are used or not.");
210 }
211
212 private:
213 void SetDeviceOrdinal(Args const& kwargs);
214 Context& SetDevice(DeviceOrd d) {
215 this->device_ = d;
216 this->gpu_id = d.ordinal; // this can be removed once we move away from `gpu_id`.
217 this->device = d.Name();
218 return *this;
219 }
220
221 // mutable for lazy cuda context initialization. This avoids initializing CUDA at load.
222 // shared_ptr is used instead of unique_ptr as with unique_ptr it's difficult to define
223 // p_impl while trying to hide CUDA code from the host compiler.
224 mutable std::shared_ptr<CUDAContext> cuctx_;
225 // cached value for CFS CPU limit. (used in containerized env)
226 std::int32_t cfs_cpu_count_; // NOLINT
227};
228} // namespace xgboost
229
230#endif // XGBOOST_CONTEXT_H_
Copyright 2015-2023 by XGBoost Contributors.
defines console logging options for xgboost. Use to enforce unified print behavior.
macro for using C++11 enum class as DMLC parameter
namespace of xgboost
Definition base.h:90
std::int16_t bst_d_ordinal_t
Ordinal of a CUDA device.
Definition base.h:130
Runtime context for XGBoost.
Definition context.h:84
decltype(auto) DispatchDevice(CPUFn &&cpu_fn, CUDAFn &&cuda_fn) const
Call function based on the current device.
Definition context.h:175
DeviceOrd Device() const
Get the current device and ordinal.
Definition context.h:141
std::string DeviceName() const
Name of the current device.
Definition context.h:149
void ConfigureGpuId(bool require_gpu)
Configure the parameter ‘gpu_id’.
Definition context.cc:159
std::int32_t Threads() const
Returns the automatically chosen number of threads based on the nthread parameter and the system sett...
Definition context.cc:203
Context MakeCUDA(bst_d_ordinal_t ordinal=0) const
Make a CUDA context based on the current context.
Definition context.h:160
bool IsCPU() const
Is XGBoost running on CPU?
Definition context.h:133
CUDAContext const * CUDACtx() const
Get a CUDA device context for allocator and stream.
Definition context.cc:212
bool IsCUDA() const
Is XGBoost running on a CUDA device?
Definition context.h:137
Context MakeCPU() const
Make a CPU context based on the current context.
Definition context.h:167
bst_d_ordinal_t Ordinal() const
Get the CUDA device ordinal.
Definition context.h:145
A type for device ordinal.
Definition context.h:31
std::string Name() const
Get a string representation of the device and the ordinal.
Definition context.h:65
static auto CUDA(bst_d_ordinal_t ordinal)
Constructor for CUDA device.
Definition context.h:56
static constexpr auto CPU()
Constructor for CPU.
Definition context.h:50
Definition context.h:22
Definition parameter.h:84