Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hack for GPU ID config #5086

Merged
merged 13 commits into from
Dec 7, 2019
9 changes: 7 additions & 2 deletions doc/parameter.rst
Original file line number Diff line number Diff line change
Expand Up @@ -181,12 +181,17 @@ Parameters for Tree Booster
- Maximum number of discrete bins to bucket continuous features.
- Increasing this number improves the optimality of splits at the cost of higher computation time.

* ``predictor``, [default=``cpu_predictor``]
* ``predictor``, [default=``auto``]

- The type of predictor algorithm to use. Provides the same results but allows the use of GPU or CPU.

- ``auto``: Configure predictor based on heuristics.
- ``cpu_predictor``: Multicore CPU prediction algorithm.
- ``gpu_predictor``: Prediction using GPU. Default when ``tree_method`` is ``gpu_hist``.
- ``gpu_predictor``: Prediction using GPU. Used when ``tree_method`` is ``gpu_hist``.
When ``predictor`` is set to default value ``auto``, the ``gpu_hist`` tree method is
able to provide GPU based prediction without copying training data to GPU memory.
If ``gpu_predictor`` is explicitly specified, then all data is copied into GPU, only
recommended for performing prediction tasks.

* ``num_parallel_tree``, [default=1]
- Number of parallel trees constructed during each iteration. This option is used to support boosted random forest.
Expand Down
2 changes: 1 addition & 1 deletion include/xgboost/gbm.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ namespace xgboost {
*/
class GradientBooster {
protected:
GenericParameter const* learner_param_;
GenericParameter const* generic_param_;

public:
/*! \brief virtual destructor */
Expand Down
5 changes: 5 additions & 0 deletions include/xgboost/generic_parameters.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@

namespace xgboost {
struct GenericParameter : public XGBoostParameter<GenericParameter> {
// Constant representing the device ID of CPU.
static int constexpr kCpuId = -1;

// stored random seed
int seed;
// whether seed the PRNG each iteration
Expand All @@ -24,6 +27,8 @@ struct GenericParameter : public XGBoostParameter<GenericParameter> {
// gpu page size in external memory mode, 0 means using the default.
size_t gpu_page_size;

void ConfigureGpuId(bool require_gpu);

void CheckDeprecated() {
if (this->n_gpus != 0) {
LOG(WARNING)
Expand Down
83 changes: 47 additions & 36 deletions include/xgboost/predictor.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,15 @@ struct GBTreeModel;
}

namespace xgboost {
/**
* \struct PredictionCacheEntry
*
* \brief Contains pointer to input matrix and associated cached predictions.
*/
struct PredictionCacheEntry {
std::shared_ptr<DMatrix> data;
HostDeviceVector<bst_float> predictions;
};

/**
* \class Predictor
Expand All @@ -41,23 +50,37 @@ namespace xgboost {

class Predictor {
protected:
GenericParameter const* learner_param_;
/*
* \brief Runtime parameters.
*/
GenericParameter const* generic_param_;
/**
* \brief Map of matrices and associated cached predictions to facilitate
* storing and looking up predictions.
*/
std::shared_ptr<std::unordered_map<DMatrix*, PredictionCacheEntry>> cache_;

std::unordered_map<DMatrix*, PredictionCacheEntry>::iterator FindCache(DMatrix const* dmat) {
auto cache_emtry = std::find_if(
cache_->begin(), cache_->end(),
[dmat](std::pair<DMatrix *, PredictionCacheEntry const &> const &kv) {
return kv.second.data.get() == dmat;
});
return cache_emtry;
}

public:
Predictor(GenericParameter const* generic_param,
std::shared_ptr<std::unordered_map<DMatrix*, PredictionCacheEntry>> cache) :
generic_param_{generic_param}, cache_{cache} {}
virtual ~Predictor() = default;

/**
* \fn virtual void Predictor::Init(const std::vector<std::pair<std::string,
* std::string> >&cfg ,const std::vector<std::shared_ptr<DMatrix> > &cache);
*
* \brief Configure and register input matrices in prediction cache.
*
* \param cfg The configuration.
* \param cache Vector of DMatrix's to be used in prediction.
*/

virtual void Configure(const std::vector<std::pair<std::string, std::string>>& cfg,
const std::vector<std::shared_ptr<DMatrix>>& cache);
virtual void Configure(const std::vector<std::pair<std::string, std::string>>& cfg);

/**
* \brief Generate batch predictions for a given feature matrix. May use
Expand Down Expand Up @@ -162,45 +185,33 @@ class Predictor {
unsigned condition_feature = 0) = 0;

virtual void PredictInteractionContributions(DMatrix* dmat,
std::vector<bst_float>* out_contribs,
const gbm::GBTreeModel& model,
unsigned ntree_limit = 0,
std::vector<bst_float>* tree_weights = nullptr,
bool approximate = false) = 0;

/**
* \fn static Predictor* Predictor::Create(std::string name);
*
* \brief Creates a new Predictor*.
*
*/
std::vector<bst_float>* out_contribs,
const gbm::GBTreeModel& model,
unsigned ntree_limit = 0,
std::vector<bst_float>* tree_weights = nullptr,
bool approximate = false) = 0;

static Predictor* Create(std::string const& name, GenericParameter const*);

protected:
/**
* \struct PredictionCacheEntry
* \brief Creates a new Predictor*.
*
* \brief Contains pointer to input matrix and associated cached predictions.
*/
struct PredictionCacheEntry {
std::shared_ptr<DMatrix> data;
HostDeviceVector<bst_float> predictions;
};

/**
* \brief Map of matrices and associated cached predictions to facilitate
* storing and looking up predictions.
* \param name Name of the predictor.
* \param generic_param Pointer to runtime parameters.
* \param cache Pointer to prediction cache.
*/
std::unordered_map<DMatrix*, PredictionCacheEntry> cache_;
static Predictor* Create(
std::string const& name, GenericParameter const* generic_param,
std::shared_ptr<std::unordered_map<DMatrix*, PredictionCacheEntry>> cache);
};

/*!
* \brief Registry entry for predictor.
*/
struct PredictorReg
: public dmlc::FunctionRegEntryBase<PredictorReg,
std::function<Predictor*()>> {};
: public dmlc::FunctionRegEntryBase<
PredictorReg, std::function<Predictor*(
GenericParameter const*,
std::shared_ptr<std::unordered_map<DMatrix*, PredictionCacheEntry>>)>> {};

#define XGBOOST_REGISTER_PREDICTOR(UniqueId, Name) \
static DMLC_ATTRIBUTE_UNUSED ::xgboost::PredictorReg& \
Expand Down
2 changes: 1 addition & 1 deletion src/gbm/gblinear.cc
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ class GBLinear : public GradientBooster {
model_.param.InitAllowUnknown(cfg);
}
param_.UpdateAllowUnknown(cfg);
updater_.reset(LinearUpdater::Create(param_.updater, learner_param_));
updater_.reset(LinearUpdater::Create(param_.updater, generic_param_));
updater_->Configure(cfg);
monitor_.Init("GBLinear");
if (param_.updater == "gpu_coord_descent") {
Expand Down
4 changes: 2 additions & 2 deletions src/gbm/gbm.cc
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,15 @@ DMLC_REGISTRY_ENABLE(::xgboost::GradientBoosterReg);
namespace xgboost {
GradientBooster* GradientBooster::Create(
const std::string& name,
GenericParameter const* learner_param,
GenericParameter const* generic_param,
const std::vector<std::shared_ptr<DMatrix> >& cache_mats,
bst_float base_margin) {
auto *e = ::dmlc::Registry< ::xgboost::GradientBoosterReg>::Get()->Find(name);
if (e == nullptr) {
LOG(FATAL) << "Unknown gbm type " << name;
}
auto p_bst = (e->body)(cache_mats, base_margin);
p_bst->learner_param_ = learner_param;
p_bst->generic_param_ = generic_param;
return p_bst;
}

Expand Down
37 changes: 18 additions & 19 deletions src/gbm/gbtree.cc
Original file line number Diff line number Diff line change
Expand Up @@ -46,42 +46,44 @@ void GBTree::Configure(const Args& cfg) {
// configure predictors
if (!cpu_predictor_) {
cpu_predictor_ = std::unique_ptr<Predictor>(
Predictor::Create("cpu_predictor", this->learner_param_));
cpu_predictor_->Configure(cfg, cache_);
Predictor::Create("cpu_predictor", this->generic_param_, cache_));
}
cpu_predictor_->Configure(cfg);
#if defined(XGBOOST_USE_CUDA)
if (!gpu_predictor_) {
auto n_gpus = common::AllVisibleGPUs();
if (!gpu_predictor_ && n_gpus != 0) {
gpu_predictor_ = std::unique_ptr<Predictor>(
Predictor::Create("gpu_predictor", this->learner_param_));
gpu_predictor_->Configure(cfg, cache_);
Predictor::Create("gpu_predictor", this->generic_param_, cache_));
}
if (n_gpus != 0) {
gpu_predictor_->Configure(cfg);
}
#endif // defined(XGBOOST_USE_CUDA)

monitor_.Init("GBTree");

specified_predictor_ = std::any_of(cfg.cbegin(), cfg.cend(),
[](std::pair<std::string, std::string> const& arg) {
return arg.first == "predictor";
});
if (!specified_predictor_ && tparam_.tree_method == TreeMethod::kGPUHist) {
tparam_.predictor = "gpu_predictor";
}

specified_updater_ = std::any_of(cfg.cbegin(), cfg.cend(),
[](std::pair<std::string, std::string> const& arg) {
return arg.first == "updater";
});
if (specified_updater_) {

if (specified_updater_ && !showed_updater_warning_) {
LOG(WARNING) << "DANGER AHEAD: You have manually specified `updater` "
"parameter. The `tree_method` parameter will be ignored. "
"Incorrect sequence of updaters will produce undefined "
"behavior. For common uses, we recommend using "
"behavior. For common uses, we recommend using"
"`tree_method` parameter instead.";
// Don't drive users to silent XGBOost.
showed_updater_warning_ = true;
} else {
this->ConfigureUpdaters();
LOG(DEBUG) << "Using updaters: " << tparam_.updater_seq;
}

for (auto& up : updaters_) {
up->Configure(cfg);
}

configured_ = true;
}

Expand Down Expand Up @@ -162,9 +164,6 @@ void GBTree::ConfigureUpdaters() {
case TreeMethod::kGPUHist:
this->AssertGPUSupport();
tparam_.updater_seq = "grow_gpu_hist";
if (!specified_predictor_) {
tparam_.predictor = "gpu_predictor";
}
break;
default:
LOG(FATAL) << "Unknown tree_method ("
Expand Down Expand Up @@ -239,7 +238,7 @@ void GBTree::InitUpdater(Args const& cfg) {
}

for (const std::string& pstr : ups) {
std::unique_ptr<TreeUpdater> up(TreeUpdater::Create(pstr.c_str(), learner_param_));
std::unique_ptr<TreeUpdater> up(TreeUpdater::Create(pstr.c_str(), generic_param_));
up->Configure(cfg);
updaters_.push_back(std::move(up));
}
Expand Down
Loading