Skip to content

Commit a0d3573

Browse files
authored
[backport] Fix device dispatch for linear updater. (dmlc#9507) (dmlc#9532)
1 parent 4301558 commit a0d3573

File tree

6 files changed

+80
-35
lines changed

6 files changed

+80
-35
lines changed

doc/parameter.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -329,7 +329,7 @@ Parameters for Linear Booster (``booster=gblinear``)
329329
- Choice of algorithm to fit linear model
330330

331331
- ``shotgun``: Parallel coordinate descent algorithm based on shotgun algorithm. Uses 'hogwild' parallelism and therefore produces a nondeterministic solution on each run.
332-
- ``coord_descent``: Ordinary coordinate descent algorithm. Also multithreaded but still produces a deterministic solution.
332+
- ``coord_descent``: Ordinary coordinate descent algorithm. Also multithreaded but still produces a deterministic solution. When the ``device`` parameter is set to ``cuda`` or ``gpu``, a GPU variant would be used.
333333

334334
* ``feature_selector`` [default= ``cyclic``]
335335

include/xgboost/global_config.h

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,28 @@
1-
/*!
2-
* Copyright 2020 by Contributors
1+
/**
2+
* Copyright 2020-2023, XGBoost Contributors
33
* \file global_config.h
44
* \brief Global configuration for XGBoost
55
* \author Hyunsu Cho
66
*/
77
#ifndef XGBOOST_GLOBAL_CONFIG_H_
88
#define XGBOOST_GLOBAL_CONFIG_H_
99

10-
#include <xgboost/parameter.h>
11-
#include <vector>
12-
#include <string>
10+
#include <dmlc/thread_local.h> // for ThreadLocalStore
11+
#include <xgboost/parameter.h> // for XGBoostParameter
1312

14-
namespace xgboost {
15-
class Json;
13+
#include <cstdint> // for int32_t
1614

15+
namespace xgboost {
1716
struct GlobalConfiguration : public XGBoostParameter<GlobalConfiguration> {
18-
int verbosity { 1 };
19-
bool use_rmm { false };
17+
std::int32_t verbosity{1};
18+
bool use_rmm{false};
2019
DMLC_DECLARE_PARAMETER(GlobalConfiguration) {
2120
DMLC_DECLARE_FIELD(verbosity)
2221
.set_range(0, 3)
2322
.set_default(1) // shows only warning
2423
.describe("Flag to print out detailed breakdown of runtime.");
25-
DMLC_DECLARE_FIELD(use_rmm)
26-
.set_default(false)
27-
.describe("Whether to use RAPIDS Memory Manager to allocate GPU memory in XGBoost");
24+
DMLC_DECLARE_FIELD(use_rmm).set_default(false).describe(
25+
"Whether to use RAPIDS Memory Manager to allocate GPU memory in XGBoost");
2826
}
2927
};
3028

src/gbm/gblinear.cc

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
/*!
2-
* Copyright 2014-2022 by XGBoost Contributors
1+
/**
2+
* Copyright 2014-2023, XGBoost Contributors
33
* \file gblinear.cc
44
* \brief Implementation of Linear booster, with L1/L2 regularization: Elastic Net
55
* the update rule is parallel coordinate descent (shotgun)
@@ -26,9 +26,9 @@
2626
#include "../common/timer.h"
2727
#include "../common/common.h"
2828
#include "../common/threading_utils.h"
29+
#include "../common/error_msg.h"
2930

30-
namespace xgboost {
31-
namespace gbm {
31+
namespace xgboost::gbm {
3232

3333
DMLC_REGISTRY_FILE_TAG(gblinear);
3434

@@ -83,7 +83,16 @@ class GBLinear : public GradientBooster {
8383
}
8484
param_.UpdateAllowUnknown(cfg);
8585
param_.CheckGPUSupport();
86-
updater_.reset(LinearUpdater::Create(param_.updater, ctx_));
86+
if (param_.updater == "gpu_coord_descent") {
87+
LOG(WARNING) << error::DeprecatedFunc("gpu_coord_descent", "2.0.0",
88+
R"(device="cuda", updater="coord_descent")");
89+
}
90+
91+
if (param_.updater == "coord_descent" && ctx_->IsCUDA()) {
92+
updater_.reset(LinearUpdater::Create("gpu_coord_descent", ctx_));
93+
} else {
94+
updater_.reset(LinearUpdater::Create(param_.updater, ctx_));
95+
}
8796
updater_->Configure(cfg);
8897
monitor_.Init("GBLinear");
8998
}
@@ -354,5 +363,4 @@ XGBOOST_REGISTER_GBM(GBLinear, "gblinear")
354363
.set_body([](LearnerModelParam const* booster_config, Context const* ctx) {
355364
return new GBLinear(booster_config, ctx);
356365
});
357-
} // namespace gbm
358-
} // namespace xgboost
366+
} // namespace xgboost::gbm

src/linear/updater_coordinate.cc

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,7 @@
99
#include "coordinate_common.h"
1010
#include "xgboost/json.h"
1111

12-
namespace xgboost {
13-
namespace linear {
12+
namespace xgboost::linear {
1413

1514
DMLC_REGISTER_PARAMETER(CoordinateParam);
1615
DMLC_REGISTRY_FILE_TAG(updater_coordinate);
@@ -39,8 +38,9 @@ class CoordinateUpdater : public LinearUpdater {
3938
FromJson(config.at("linear_train_param"), &tparam_);
4039
FromJson(config.at("coordinate_param"), &cparam_);
4140
}
42-
void SaveConfig(Json* p_out) const override {
43-
auto& out = *p_out;
41+
void SaveConfig(Json *p_out) const override {
42+
LOG(DEBUG) << "Save config for CPU updater.";
43+
auto &out = *p_out;
4444
out["linear_train_param"] = ToJson(tparam_);
4545
out["coordinate_param"] = ToJson(cparam_);
4646
}
@@ -99,5 +99,4 @@ class CoordinateUpdater : public LinearUpdater {
9999
XGBOOST_REGISTER_LINEAR_UPDATER(CoordinateUpdater, "coord_descent")
100100
.describe("Update linear model according to coordinate descent algorithm.")
101101
.set_body([]() { return new CoordinateUpdater(); });
102-
} // namespace linear
103-
} // namespace xgboost
102+
} // namespace xgboost::linear

src/linear/updater_gpu_coordinate.cu

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,7 @@
1515
#include "../common/timer.h"
1616
#include "./param.h"
1717

18-
namespace xgboost {
19-
namespace linear {
18+
namespace xgboost::linear {
2019

2120
DMLC_REGISTRY_FILE_TAG(updater_gpu_coordinate);
2221

@@ -29,7 +28,7 @@ DMLC_REGISTRY_FILE_TAG(updater_gpu_coordinate);
2928
class GPUCoordinateUpdater : public LinearUpdater { // NOLINT
3029
public:
3130
// set training parameter
32-
void Configure(Args const& args) override {
31+
void Configure(Args const &args) override {
3332
tparam_.UpdateAllowUnknown(args);
3433
coord_param_.UpdateAllowUnknown(args);
3534
selector_.reset(FeatureSelector::Create(tparam_.feature_selector));
@@ -41,8 +40,9 @@ class GPUCoordinateUpdater : public LinearUpdater { // NOLINT
4140
FromJson(config.at("linear_train_param"), &tparam_);
4241
FromJson(config.at("coordinate_param"), &coord_param_);
4342
}
44-
void SaveConfig(Json* p_out) const override {
45-
auto& out = *p_out;
43+
void SaveConfig(Json *p_out) const override {
44+
LOG(DEBUG) << "Save config for GPU updater.";
45+
auto &out = *p_out;
4646
out["linear_train_param"] = ToJson(tparam_);
4747
out["coordinate_param"] = ToJson(coord_param_);
4848
}
@@ -101,10 +101,9 @@ class GPUCoordinateUpdater : public LinearUpdater { // NOLINT
101101
monitor_.Stop("LazyInitDevice");
102102

103103
monitor_.Start("UpdateGpair");
104-
auto &in_gpair_host = in_gpair->ConstHostVector();
105104
// Update gpair
106105
if (ctx_->gpu_id >= 0) {
107-
this->UpdateGpair(in_gpair_host);
106+
this->UpdateGpair(in_gpair->ConstHostVector());
108107
}
109108
monitor_.Stop("UpdateGpair");
110109

@@ -249,5 +248,4 @@ XGBOOST_REGISTER_LINEAR_UPDATER(GPUCoordinateUpdater, "gpu_coord_descent")
249248
"Update linear model according to coordinate descent algorithm. GPU "
250249
"accelerated.")
251250
.set_body([]() { return new GPUCoordinateUpdater(); });
252-
} // namespace linear
253-
} // namespace xgboost
251+
} // namespace xgboost::linear

tests/cpp/gbm/test_gblinear.cu

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/**
2+
* Copyright 2023, XGBoost Contributors
3+
*/
4+
#include <gtest/gtest.h>
5+
#include <xgboost/global_config.h> // for GlobalConfigThreadLocalStore
6+
#include <xgboost/json.h> // for Json, Object
7+
#include <xgboost/learner.h> // for Learner
8+
9+
#include <algorithm> // for transform
10+
#include <string> // for string
11+
#include <utility> // for swap
12+
13+
#include "../helpers.h" // for RandomDataGenerator
14+
15+
namespace xgboost {
16+
TEST(GBlinear, DispatchUpdater) {
17+
auto verbosity = 3;
18+
std::swap(GlobalConfigThreadLocalStore::Get()->verbosity, verbosity);
19+
20+
auto test = [](std::string device) {
21+
auto p_fmat = RandomDataGenerator{10, 10, 0.0f}.GenerateDMatrix(true);
22+
std::unique_ptr<Learner> learner{Learner::Create({p_fmat})};
23+
learner->SetParams(
24+
Args{{"booster", "gblinear"}, {"updater", "coord_descent"}, {"device", device}});
25+
learner->Configure();
26+
for (std::int32_t iter = 0; iter < 3; ++iter) {
27+
learner->UpdateOneIter(iter, p_fmat);
28+
}
29+
Json config{Object{}};
30+
::testing::internal::CaptureStderr();
31+
learner->SaveConfig(&config);
32+
auto str = ::testing::internal::GetCapturedStderr();
33+
std::transform(device.cbegin(), device.cend(), device.begin(),
34+
[](char c) { return std::toupper(c); });
35+
ASSERT_NE(str.find(device), std::string::npos);
36+
};
37+
test("cpu");
38+
test("gpu");
39+
40+
std::swap(GlobalConfigThreadLocalStore::Get()->verbosity, verbosity);
41+
}
42+
} // namespace xgboost

0 commit comments

Comments
 (0)