Skip to content

Commit 0c035d7

Browse files
authored
Reduce memory in GPU quantile sketch for external memory (#12047)
1 parent 6dbf362 commit 0c035d7

26 files changed

Lines changed: 267 additions & 382 deletions

include/xgboost/c_api.h

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -529,12 +529,8 @@ XGB_DLL int XGDMatrixCreateFromCallback(DataIterHandle iter, DMatrixHandle proxy
529529
* - nthread (optional): Number of threads used for initializing DMatrix.
530530
* - max_bin (optional): Maximum number of bins for building histogram. Must be consistent with
531531
* the corresponding booster training parameter.
532-
* - max_quantile_blocks (optional): For GPU-based inputs, XGBoost handles incoming
533-
* batches with multiple growing substreams. This parameter sets the maximum number
534-
* of batches before XGBoost can cut the sub-stream and create a new one. This can
535-
* help bound the memory usage. By default, XGBoost grows new sub-streams
536-
* exponentially until batches are exhausted. Only used for the training dataset and
537-
* the default is None (unbounded).
532+
* - max_quantile_blocks (optional, deprecated): This parameter no longer has any effect and
533+
* will be removed in a future release.
538534
* @param out The created Quantile DMatrix.
539535
*
540536
* @return 0 when success, -1 when failure happens
@@ -570,12 +566,8 @@ XGB_DLL int XGQuantileDMatrixCreateFromCallback(DataIterHandle iter, DMatrixHand
570566
* - min_cache_page_bytes (optional): The minimum number of bytes for each internal GPU
571567
* page. Set to 0 to disable page concatenation. Automatic configuration if the
572568
* parameter is not provided or set to None.
573-
* - max_quantile_blocks (optional): For GPU-based inputs, XGBoost handles incoming
574-
* batches with multiple growing substreams. This parameter sets the maximum number
575-
* of batches before XGBoost can cut the sub-stream and create a new one. This can
576-
* help bound the memory usage. By default, XGBoost grows new sub-streams
577-
* exponentially until batches are exhausted. Only used for the training dataset and
578-
* the default is None (unbounded).
569+
* - max_quantile_blocks (optional, deprecated): This parameter no longer has any effect and
570+
* will be removed in a future release.
579571
* - cache_host_ratio (optioinal): For GPU-based inputs, XGBoost can split the cache into
580572
* host and device portitions to reduce the data transfer overhead. This parameter
581573
* specifies the size of host cache compared to the size of the entire cache:

include/xgboost/data.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -673,7 +673,7 @@ class DMatrix {
673673
typename XGDMatrixCallbackNext>
674674
static DMatrix* Create(DataIterHandle iter, DMatrixHandle proxy, std::shared_ptr<DMatrix> ref,
675675
DataIterResetCallback* reset, XGDMatrixCallbackNext* next, float missing,
676-
std::int32_t nthread, bst_bin_t max_bin, std::int64_t max_quantile_blocks);
676+
std::int32_t nthread, bst_bin_t max_bin);
677677

678678
/**
679679
* @brief Create an external memory DMatrix with callbacks.
@@ -707,8 +707,7 @@ class DMatrix {
707707
typename XGDMatrixCallbackNext>
708708
static DMatrix* Create(DataIterHandle iter, DMatrixHandle proxy, std::shared_ptr<DMatrix> ref,
709709
DataIterResetCallback* reset, XGDMatrixCallbackNext* next,
710-
bst_bin_t max_bin, std::int64_t max_quantile_blocks,
711-
ExtMemConfig const& config);
710+
bst_bin_t max_bin, ExtMemConfig const& config);
712711

713712
virtual DMatrix* Slice(common::Span<int32_t const> ridxs) = 0;
714713

python-package/xgboost/core.py

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1465,19 +1465,12 @@ class QuantileDMatrix(DMatrix, _RefMixIn):
14651465
applied to the validation/test data
14661466
14671467
max_quantile_batches :
1468-
For GPU-based inputs from an iterator, XGBoost handles incoming batches with
1469-
multiple growing sub-streams. This parameter sets the maximum number of batches
1470-
before XGBoost can cut a sub-stream and create a new one. This can help bound
1471-
the memory usage. By default, XGBoost grows a sub-stream exponentially until
1472-
batches are exhausted. This option is only used for the training dataset and the
1473-
default is None (unbounded). Lastly, if the `data` is a single batch instead of
1474-
an iterator, this parameter has no effect.
1468+
Deprecated. This parameter no longer has any effect and will be removed in a
1469+
future release.
14751470
14761471
.. versionadded:: 3.0.0
14771472
1478-
.. warning::
1479-
1480-
This is an experimental parameter and subject to change.
1473+
.. deprecated:: 3.3.0
14811474
14821475
"""
14831476

@@ -1642,7 +1635,7 @@ def __init__( # pylint: disable=super-init-not-called
16421635
A user-defined :py:class:`DataIter` for loading data.
16431636
16441637
max_quantile_batches :
1645-
See :py:class:`QuantileDMatrix`.
1638+
Deprecated. See :py:class:`QuantileDMatrix`.
16461639
16471640
cache_host_ratio :
16481641

src/c_api/c_api.cc

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -367,6 +367,15 @@ std::shared_ptr<DMatrix> GetRefDMatrix(DataIterHandle ref) {
367367
}
368368
return _ref;
369369
}
370+
371+
void WarnDeprecatedMaxQuantileBlocks(Json const &config) {
372+
auto const &obj = get<Object const>(config);
373+
auto it = obj.find("max_quantile_blocks");
374+
if (it != obj.cend() && !IsA<Null>(it->second)) {
375+
LOG(WARNING) << "`max_quantile_blocks` is deprecated and has no effect. "
376+
"The parameter will be removed in a future release.";
377+
}
378+
}
370379
} // namespace
371380

372381
XGB_DLL int XGQuantileDMatrixCreateFromCallback(DataIterHandle iter, DMatrixHandle proxy,
@@ -378,18 +387,17 @@ XGB_DLL int XGQuantileDMatrixCreateFromCallback(DataIterHandle iter, DMatrixHand
378387

379388
xgboost_CHECK_C_ARG_PTR(config);
380389
auto jconfig = Json::Load(StringView{config});
390+
WarnDeprecatedMaxQuantileBlocks(jconfig);
381391
auto missing = GetMissing(jconfig);
382392
auto n_threads = OptionalArg<Integer, int64_t>(jconfig, "nthread", 0);
383393
auto max_bin = OptionalArg<Integer, int64_t>(jconfig, "max_bin", 256);
384-
auto max_quantile_blocks = OptionalArg<Integer, std::int64_t>(
385-
jconfig, "max_quantile_blocks", std::numeric_limits<std::int64_t>::max());
386394

387395
xgboost_CHECK_C_ARG_PTR(next);
388396
xgboost_CHECK_C_ARG_PTR(reset);
389397
xgboost_CHECK_C_ARG_PTR(out);
390398

391-
*out = new std::shared_ptr<xgboost::DMatrix>{xgboost::DMatrix::Create(
392-
iter, proxy, p_ref, reset, next, missing, n_threads, max_bin, max_quantile_blocks)};
399+
*out = new std::shared_ptr<xgboost::DMatrix>{
400+
xgboost::DMatrix::Create(iter, proxy, p_ref, reset, next, missing, n_threads, max_bin)};
393401
API_END();
394402
}
395403

@@ -403,15 +411,14 @@ XGB_DLL int XGExtMemQuantileDMatrixCreateFromCallback(DataIterHandle iter, DMatr
403411

404412
xgboost_CHECK_C_ARG_PTR(config);
405413
auto jconfig = Json::Load(StringView{config});
414+
WarnDeprecatedMaxQuantileBlocks(jconfig);
406415
auto missing = GetMissing(jconfig);
407416
std::int32_t n_threads = OptionalArg<Integer, std::int64_t>(jconfig, "nthread", 0);
408417
auto max_bin = OptionalArg<Integer, std::int64_t>(jconfig, "max_bin", 256);
409418
auto on_host = OptionalArg<Boolean>(jconfig, "on_host", false);
410419
std::string cache = RequiredArg<String>(jconfig, "cache_prefix", __func__);
411420
auto min_cache_page_bytes = OptionalArg<Integer, std::int64_t>(jconfig, "min_cache_page_bytes",
412421
cuda_impl::AutoCachePageBytes());
413-
auto max_quantile_blocks = OptionalArg<Integer, std::int64_t>(
414-
jconfig, "max_quantile_blocks", std::numeric_limits<std::int64_t>::max());
415422
auto cache_host_ratio =
416423
OptionalArg<Number, float>(jconfig, "cache_host_ratio", cuda_impl::AutoHostRatio());
417424

@@ -421,8 +428,8 @@ XGB_DLL int XGExtMemQuantileDMatrixCreateFromCallback(DataIterHandle iter, DMatr
421428

422429
auto config =
423430
ExtMemConfig{cache, on_host, cache_host_ratio, min_cache_page_bytes, missing, n_threads};
424-
*out = new std::shared_ptr<xgboost::DMatrix>{xgboost::DMatrix::Create(
425-
iter, proxy, p_ref, reset, next, max_bin, max_quantile_blocks, config)};
431+
*out = new std::shared_ptr<xgboost::DMatrix>{
432+
xgboost::DMatrix::Create(iter, proxy, p_ref, reset, next, max_bin, config)};
426433
API_END();
427434
}
428435

src/common/hist_util.cu

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -367,8 +367,7 @@ HistogramCuts DeviceSketchWithHessian(Context const* ctx, DMatrix* p_fmat, bst_b
367367
auto d_weight = UnifyWeight(cuctx, info, hessian, &weight);
368368

369369
HistogramCuts cuts;
370-
SketchContainer sketch_container(info.feature_types, max_bin, info.num_col_, info.num_row_,
371-
ctx->Device());
370+
SketchContainer sketch_container(info.feature_types, max_bin, info.num_col_, ctx->Device());
372371
CHECK_EQ(has_weight || !hessian.empty(), !d_weight.empty());
373372
for (const auto& page : p_fmat->GetBatches<SparsePage>()) {
374373
std::size_t page_nnz = page.data.Size();

src/common/quantile.cu

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -505,18 +505,14 @@ void SketchContainer::AllReduce(Context const *ctx, bool is_column_split) {
505505
}
506506

507507
timer_.Start(__func__);
508-
// Reduce the overhead on syncing.
509-
bst_idx_t global_sum_rows = num_rows_;
510-
auto rc = collective::Allreduce(ctx, linalg::MakeVec(&global_sum_rows, 1), collective::Op::kSum);
511-
SafeColl(rc);
512-
bst_idx_t intermediate_num_cuts =
513-
std::min(global_sum_rows, static_cast<size_t>(num_bins_ * kFactor));
508+
// Bound local sketch size before exchanging data across workers.
509+
auto intermediate_num_cuts = static_cast<bst_idx_t>(num_bins_ * kFactor);
514510
this->Prune(ctx, intermediate_num_cuts);
515511

516512
auto d_columns_ptr = this->columns_ptr_.ConstDeviceSpan();
517513
CHECK_EQ(d_columns_ptr.size(), num_columns_ + 1);
518514
size_t n = d_columns_ptr.size();
519-
rc = collective::Allreduce(ctx, linalg::MakeVec(&n, 1), collective::Op::kMax);
515+
auto rc = collective::Allreduce(ctx, linalg::MakeVec(&n, 1), collective::Op::kMax);
520516
SafeColl(rc);
521517
CHECK_EQ(n, d_columns_ptr.size()) << "Number of columns differs across workers";
522518

@@ -560,8 +556,7 @@ void SketchContainer::AllReduce(Context const *ctx, bool is_column_split) {
560556
timer_.Stop(__func__);
561557

562558
// Merge them into a new sketch.
563-
SketchContainer new_sketch(this->feature_types_, num_bins_, this->num_columns_, global_sum_rows,
564-
ctx->Device());
559+
SketchContainer new_sketch(this->feature_types_, num_bins_, this->num_columns_, ctx->Device());
565560
for (size_t i = 0; i < allworkers.size(); ++i) {
566561
auto worker = allworkers[i];
567562
auto worker_ptr =

src/common/quantile.cuh

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,6 @@ class SketchContainer {
4646
private:
4747
Monitor timer_;
4848
HostDeviceVector<FeatureType> feature_types_;
49-
bst_idx_t num_rows_;
5049
bst_feature_t num_columns_;
5150
int32_t num_bins_;
5251

@@ -97,12 +96,11 @@ class SketchContainer {
9796
*
9897
* \param max_bin Maximum number of bins per columns
9998
* \param num_columns Total number of columns in dataset.
100-
* \param num_rows Total number of rows in known dataset (typically the rows in current worker).
10199
* \param device GPU ID.
102100
*/
103101
SketchContainer(HostDeviceVector<FeatureType> const& feature_types, bst_bin_t max_bin,
104-
bst_feature_t num_columns, bst_idx_t num_rows, DeviceOrd device)
105-
: num_rows_{num_rows}, num_columns_{num_columns}, num_bins_{max_bin} {
102+
bst_feature_t num_columns, DeviceOrd device)
103+
: num_columns_{num_columns}, num_bins_{max_bin} {
106104
CHECK(device.IsCUDA());
107105
// Initialize Sketches for this dmatrix
108106
this->columns_ptr_.SetDevice(device);

src/data/data.cc

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -974,9 +974,8 @@ template <typename DataIterHandle, typename DMatrixHandle, typename DataIterRese
974974
typename XGDMatrixCallbackNext>
975975
DMatrix* DMatrix::Create(DataIterHandle iter, DMatrixHandle proxy, std::shared_ptr<DMatrix> ref,
976976
DataIterResetCallback* reset, XGDMatrixCallbackNext* next, float missing,
977-
int nthread, bst_bin_t max_bin, std::int64_t max_quantile_blocks) {
978-
return new data::IterativeDMatrix(iter, proxy, ref, reset, next, missing, nthread, max_bin,
979-
max_quantile_blocks);
977+
int nthread, bst_bin_t max_bin) {
978+
return new data::IterativeDMatrix(iter, proxy, ref, reset, next, missing, nthread, max_bin);
980979
}
981980

982981
template <typename DataIterHandle, typename DMatrixHandle, typename DataIterResetCallback,
@@ -990,17 +989,16 @@ template <typename DataIterHandle, typename DMatrixHandle, typename DataIterRese
990989
typename XGDMatrixCallbackNext>
991990
DMatrix* DMatrix::Create(DataIterHandle iter, DMatrixHandle proxy, std::shared_ptr<DMatrix> ref,
992991
DataIterResetCallback* reset, XGDMatrixCallbackNext* next,
993-
bst_bin_t max_bin, std::int64_t max_quantile_blocks,
994-
ExtMemConfig const& config) {
995-
return new data::ExtMemQuantileDMatrix{
996-
iter, proxy, ref, reset, next, max_bin, max_quantile_blocks, config};
992+
bst_bin_t max_bin, ExtMemConfig const& config) {
993+
return new data::ExtMemQuantileDMatrix{iter, proxy, ref, reset, next, max_bin, config};
997994
}
998995

999-
template DMatrix*
1000-
DMatrix::Create<DataIterHandle, DMatrixHandle, DataIterResetCallback, XGDMatrixCallbackNext>(
1001-
DataIterHandle iter, DMatrixHandle proxy, std::shared_ptr<DMatrix> ref,
1002-
DataIterResetCallback* reset, XGDMatrixCallbackNext* next, float missing, int nthread,
1003-
int max_bin, std::int64_t max_quantile_blocks);
996+
template DMatrix* DMatrix::Create<DataIterHandle, DMatrixHandle, DataIterResetCallback,
997+
XGDMatrixCallbackNext>(DataIterHandle iter, DMatrixHandle proxy,
998+
std::shared_ptr<DMatrix> ref,
999+
DataIterResetCallback* reset,
1000+
XGDMatrixCallbackNext* next, float missing,
1001+
int nthread, int max_bin);
10041002

10051003
template DMatrix* DMatrix::Create<DataIterHandle, DMatrixHandle, DataIterResetCallback,
10061004
XGDMatrixCallbackNext>(DataIterHandle iter, DMatrixHandle proxy,
@@ -1011,7 +1009,7 @@ template DMatrix* DMatrix::Create<DataIterHandle, DMatrixHandle, DataIterResetCa
10111009
template DMatrix*
10121010
DMatrix::Create<DataIterHandle, DMatrixHandle, DataIterResetCallback, XGDMatrixCallbackNext>(
10131011
DataIterHandle, DMatrixHandle, std::shared_ptr<DMatrix>, DataIterResetCallback*,
1014-
XGDMatrixCallbackNext*, bst_bin_t, std::int64_t, ExtMemConfig const&);
1012+
XGDMatrixCallbackNext*, bst_bin_t, ExtMemConfig const&);
10151013

10161014
template <typename AdapterT>
10171015
DMatrix* DMatrix::Create(AdapterT* adapter, float missing, int nthread, const std::string&,

src/data/extmem_quantile_dmatrix.cc

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ ExtMemQuantileDMatrix::ExtMemQuantileDMatrix(DataIterHandle iter_handle, DMatrix
2424
std::shared_ptr<DMatrix> ref,
2525
DataIterResetCallback *reset,
2626
XGDMatrixCallbackNext *next, bst_bin_t max_bin,
27-
std::int64_t max_quantile_blocks,
2827
ExtMemConfig const &config)
2928
: cache_prefix_{config.cache}, on_host_{config.on_host} {
3029
cache_prefix_ = MakeCachePrefix(cache_prefix_);
@@ -45,7 +44,7 @@ ExtMemQuantileDMatrix::ExtMemQuantileDMatrix(DataIterHandle iter_handle, DMatrix
4544
this->InitFromCPU(&ctx, iter, proxy, p, config.missing, ref);
4645
} else {
4746
p.n_prefetch_batches = ::xgboost::cuda_impl::DftPrefetchBatches();
48-
this->InitFromCUDA(&ctx, iter, proxy, p, ref, max_quantile_blocks, config);
47+
this->InitFromCUDA(&ctx, iter, proxy, p, ref, config);
4948
}
5049
this->batch_ = p;
5150
this->fmat_ctx_ = ctx;
@@ -144,8 +143,7 @@ BatchSet<GHistIndexMatrix> ExtMemQuantileDMatrix::GetGradientIndex(Context const
144143
#if !defined(XGBOOST_USE_CUDA)
145144
void ExtMemQuantileDMatrix::InitFromCUDA(
146145
Context const *, std::shared_ptr<DataIterProxy<DataIterResetCallback, XGDMatrixCallbackNext>>,
147-
DMatrixHandle, BatchParam const &, std::shared_ptr<DMatrix>, std::int64_t,
148-
ExtMemConfig const &) {
146+
DMatrixHandle, BatchParam const &, std::shared_ptr<DMatrix>, ExtMemConfig const &) {
149147
common::AssertGPUSupport();
150148
}
151149

src/data/extmem_quantile_dmatrix.cu

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ void ExtMemQuantileDMatrix::InitFromCUDA(
4141
Context const *ctx,
4242
std::shared_ptr<DataIterProxy<DataIterResetCallback, XGDMatrixCallbackNext>> iter,
4343
DMatrixHandle proxy_handle, BatchParam const &p, std::shared_ptr<DMatrix> ref,
44-
std::int64_t max_quantile_blocks, ExtMemConfig const &config) {
44+
ExtMemConfig const &config) {
4545
xgboost_NVTX_FN_RANGE();
4646

4747
// A handle passed to external iterator.
@@ -54,7 +54,7 @@ void ExtMemQuantileDMatrix::InitFromCUDA(
5454
auto cuts = std::make_shared<common::HistogramCuts>();
5555
ExternalDataInfo ext_info;
5656
cuda_impl::MakeSketches(ctx, iter.get(), proxy, ref, p, config.missing, cuts, this->info_,
57-
max_quantile_blocks, &ext_info);
57+
&ext_info);
5858
ext_info.SetInfo(ctx, true, &this->info_);
5959

6060
/**

0 commit comments

Comments
 (0)