/** * Copyright 2015-2023 by XGBoost Contributors * \file common.h * \brief Common utilities */ #ifndef XGBOOST_COMMON_COMMON_H_ #define XGBOOST_COMMON_COMMON_H_ #include // for array #include // for ceil #include // for size_t #include // for int32_t, int64_t #include // for basic_istream, operator<<, istringstream #include // for string, basic_string, getline, char_traits #include // for make_tuple #include // for forward, index_sequence, make_index_sequence #include // for vector #include "xgboost/base.h" // for XGBOOST_DEVICE #include "xgboost/logging.h" // for LOG, LOG_FATAL, LogMessageFatal #if defined(__CUDACC__) #include #include #define WITH_CUDA() true #else #define WITH_CUDA() false #endif // defined(__CUDACC__) namespace dh { #if defined(__CUDACC__) /* * Error handling functions */ #define safe_cuda(ans) ThrowOnCudaError((ans), __FILE__, __LINE__) inline cudaError_t ThrowOnCudaError(cudaError_t code, const char *file, int line) { if (code != cudaSuccess) { LOG(FATAL) << thrust::system_error(code, thrust::cuda_category(), std::string{file} + ": " + // NOLINT std::to_string(line)).what(); } return code; } #endif // defined(__CUDACC__) } // namespace dh namespace xgboost::common { /*! * \brief Split a string by delimiter * \param s String to be split. * \param delim The delimiter. */ inline std::vector Split(const std::string& s, char delim) { std::string item; std::istringstream is(s); std::vector ret; while (std::getline(is, item, delim)) { ret.push_back(item); } return ret; } void EscapeU8(std::string const &string, std::string *p_buffer); template XGBOOST_DEVICE T Max(T a, T b) { return a < b ? b : a; } template XGBOOST_DEVICE T1 DivRoundUp(const T1 a, const T2 b) { return static_cast(std::ceil(static_cast(a) / b)); } namespace detail { template constexpr auto UnpackArr(std::array &&arr, std::index_sequence) { return std::make_tuple(std::forward>(arr)[Idx]...); } } // namespace detail template constexpr auto UnpackArr(std::array &&arr) { return detail::UnpackArr(std::forward>(arr), std::make_index_sequence{}); } /* * Range iterator */ class Range { public: using DifferenceType = int64_t; class Iterator { friend class Range; public: XGBOOST_DEVICE DifferenceType operator*() const { return i_; } XGBOOST_DEVICE const Iterator &operator++() { i_ += step_; return *this; } XGBOOST_DEVICE Iterator operator++(int) { Iterator res {*this}; i_ += step_; return res; } XGBOOST_DEVICE bool operator==(const Iterator &other) const { return i_ >= other.i_; } XGBOOST_DEVICE bool operator!=(const Iterator &other) const { return i_ < other.i_; } XGBOOST_DEVICE void Step(DifferenceType s) { step_ = s; } protected: XGBOOST_DEVICE explicit Iterator(DifferenceType start) : i_(start) {} XGBOOST_DEVICE explicit Iterator(DifferenceType start, DifferenceType step) : i_{start}, step_{step} {} private: int64_t i_; DifferenceType step_ = 1; }; XGBOOST_DEVICE Iterator begin() const { return begin_; } // NOLINT XGBOOST_DEVICE Iterator end() const { return end_; } // NOLINT XGBOOST_DEVICE Range(DifferenceType begin, DifferenceType end) : begin_(begin), end_(end) {} XGBOOST_DEVICE Range(DifferenceType begin, DifferenceType end, DifferenceType step) : begin_(begin, step), end_(end) {} XGBOOST_DEVICE bool operator==(const Range& other) const { return *begin_ == *other.begin_ && *end_ == *other.end_; } XGBOOST_DEVICE bool operator!=(const Range& other) const { return !(*this == other); } XGBOOST_DEVICE void Step(DifferenceType s) { begin_.Step(s); } private: Iterator begin_; Iterator end_; }; int AllVisibleGPUs(); inline void AssertGPUSupport() { #ifndef XGBOOST_USE_CUDA LOG(FATAL) << "XGBoost version not compiled with GPU support."; #endif // XGBOOST_USE_CUDA } inline void AssertNCCLSupport() { #if !defined(XGBOOST_USE_NCCL) LOG(FATAL) << "XGBoost version not compiled with NCCL support."; #endif // !defined(XGBOOST_USE_NCCL) } inline void AssertOneAPISupport() { #ifndef XGBOOST_USE_ONEAPI LOG(FATAL) << "XGBoost version not compiled with OneAPI support."; #endif // XGBOOST_USE_ONEAPI } void SetDevice(std::int32_t device); #if !defined(XGBOOST_USE_CUDA) inline void SetDevice(std::int32_t device) { if (device >= 0) { AssertGPUSupport(); } } #endif /** * @brief Last index of a group in a CSR style of index pointer. */ template XGBOOST_DEVICE size_t LastOf(size_t group, Indexable const &indptr) { return indptr[group + 1] - 1; } } // namespace xgboost::common #endif // XGBOOST_COMMON_COMMON_H_