Skip to content

Commit 5046112

Browse files
authored
Add sycl python tests to public CI (#19)
* initial * install dpcpp with conda * add env file for sycl * fixing missprint * fixing env file name * rename device sycl:gpu->sycl in predictor tests * set env variables to use g++ for xgboost compilation in sycl tests * modify tests * make predictor tests training on cpu * fixes for predictor tests * add zero buffer check to predictor * add zero buffer size chack to updater * add zero buffer check to SetIndexData() * fix error * add more checks for zero buffers * add zero buffer check to PredTransform --------- Co-authored-by: Dmitry Razdoburdin <>
1 parent 6aa6a39 commit 5046112

File tree

11 files changed

+90
-17
lines changed

11 files changed

+90
-17
lines changed

.github/workflows/python_tests.yml

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,51 @@ jobs:
256256
run: |
257257
pytest -s -v -rxXs --durations=0 ./tests/test_distributed/test_with_spark
258258
259+
python-sycl-tests-on-ubuntu:
260+
name: Test XGBoost Python package with SYCL on ${{ matrix.config.os }}
261+
runs-on: ${{ matrix.config.os }}
262+
timeout-minutes: 90
263+
strategy:
264+
matrix:
265+
config:
266+
- {os: ubuntu-latest, python-version: "3.8"}
267+
268+
steps:
269+
- uses: actions/checkout@v2
270+
with:
271+
submodules: 'true'
272+
273+
- uses: mamba-org/provision-with-micromamba@f347426e5745fe3dfc13ec5baf20496990d0281f # v14
274+
with:
275+
cache-downloads: true
276+
cache-env: true
277+
environment-name: linux_sycl_test
278+
environment-file: tests/ci_build/conda_env/linux_sycl_test.yml
279+
280+
- name: Display Conda env
281+
run: |
282+
conda info
283+
conda list
284+
285+
- name: Build XGBoost on Ubuntu
286+
run: |
287+
mkdir build
288+
cd build
289+
export CXX=g++
290+
export CC=gcc
291+
cmake .. -DPLUGIN_SYCL=ON -DCMAKE_PREFIX_PATH=$CONDA_PREFIX
292+
make -j$(nproc)
293+
294+
- name: Install Python package
295+
run: |
296+
cd python-package
297+
python --version
298+
pip install -v .
299+
300+
- name: Test Python package
301+
run: |
302+
pytest -s -v -rxXs --durations=0 ./tests/python-sycl/
303+
259304
python-system-installation-on-ubuntu:
260305
name: Test XGBoost Python package System Installation on ${{ matrix.os }}
261306
runs-on: ${{ matrix.os }}

plugin/sycl/common/hist_util.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ void GHistIndexMatrix::SetIndexData(::sycl::queue qu,
5555
size_t nbins,
5656
size_t row_stride,
5757
uint32_t* offsets) {
58+
if (hit_count.size() == 0) return;
5859
const xgboost::Entry *data_ptr = dmat_device.data.DataConst();
5960
const bst_row_t *offset_vec = dmat_device.row_ptr.DataConst();
6061
const size_t num_rows = dmat_device.row_ptr.Size() - 1;

plugin/sycl/objective/multiclass_obj.cc

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -102,9 +102,9 @@ class SoftmaxMultiClassObj : public ObjFunction {
102102
const MetaInfo& info,
103103
int iter,
104104
HostDeviceVector<GradientPair>* out_gpair) override {
105-
if (info.labels.Size() == 0) {
106-
return;
107-
}
105+
if (preds.Size() == 0) return;
106+
if (info.labels.Size() == 0) return;
107+
108108
CHECK(preds.Size() == (static_cast<size_t>(param_.num_class) * info.labels.Size()))
109109
<< "SoftmaxMultiClassObj: label size and pred size does not match.\n"
110110
<< "label.Size() * num_class: "
@@ -187,6 +187,7 @@ class SoftmaxMultiClassObj : public ObjFunction {
187187

188188

189189
inline void Transform(HostDeviceVector<bst_float> *io_preds, bool prob) const {
190+
if (io_preds->Size() == 0) return;
190191
const int nclass = param_.num_class;
191192
const auto ndata = static_cast<int64_t>(io_preds->Size() / nclass);
192193
max_preds_.Resize(ndata);

plugin/sycl/objective/regression_obj.cc

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,9 +53,7 @@ class RegLossObj : public ObjFunction {
5353
const MetaInfo &info,
5454
int iter,
5555
HostDeviceVector<GradientPair>* out_gpair) override {
56-
if (info.labels.Size() == 0U) {
57-
LOG(WARNING) << "Label set is empty.";
58-
}
56+
if (info.labels.Size() == 0) return;
5957
CHECK_EQ(preds.Size(), info.labels.Size())
6058
<< " " << "labels are not correctly provided"
6159
<< "preds.size=" << preds.Size() << ", label.size=" << info.labels.Size() << ", "
@@ -125,6 +123,7 @@ class RegLossObj : public ObjFunction {
125123

126124
void PredTransform(HostDeviceVector<float> *io_preds) const override {
127125
size_t const ndata = io_preds->Size();
126+
if (ndata == 0) return;
128127
::sycl::buffer<bst_float, 1> io_preds_buf(io_preds->HostPointer(), io_preds->Size());
129128

130129
qu_.submit([&](::sycl::handler& cgh) {

plugin/sycl/predictor/predictor.cc

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -184,9 +184,9 @@ void DevicePredictInternal(::sycl::queue qu,
184184
const gbm::GBTreeModel& model,
185185
size_t tree_begin,
186186
size_t tree_end) {
187-
if (tree_end - tree_begin == 0) {
188-
return;
189-
}
187+
if (tree_end - tree_begin == 0) return;
188+
if (out_preds->HostVector().size() == 0) return;
189+
190190
DeviceModel device_model;
191191
device_model.Init(qu, model, tree_begin, tree_end);
192192

plugin/sycl/tree/updater_quantile_hist.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -627,6 +627,7 @@ bool QuantileHistMaker::Builder<GradientSumT>::UpdatePredictionCache(
627627

628628
const size_t stride = out_preds.Stride(0);
629629
const int buffer_size = out_preds.Size()*stride - stride + 1;
630+
if (buffer_size == 0) return true;
630631
::sycl::buffer<float, 1> out_preds_buf(&out_preds(0), buffer_size);
631632

632633
size_t n_nodes = row_set_collection_.Size();
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
name: linux_sycl_test
2+
channels:
3+
- conda-forge
4+
- intel
5+
dependencies:
6+
- python=3.8
7+
- cmake
8+
- c-compiler
9+
- cxx-compiler
10+
- pip
11+
- wheel
12+
- numpy
13+
- scipy
14+
- scikit-learn
15+
- pandas
16+
- hypothesis>=6.46
17+
- pytest
18+
- pytest-timeout
19+
- pytest-cov
20+
- dpcpp_linux-64

tests/python-sycl/test_sycl_prediction.py

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ def test_predict(self):
4848
cpu_pred_test = bst.predict(dtest, output_margin=True)
4949
cpu_pred_val = bst.predict(dval, output_margin=True)
5050

51-
bst.set_param({"device": "sycl:gpu"})
51+
bst.set_param({"device": "sycl"})
5252
sycl_pred_train = bst.predict(dtrain, output_margin=True)
5353
sycl_pred_test = bst.predict(dtest, output_margin=True)
5454
sycl_pred_val = bst.predict(dval, output_margin=True)
@@ -82,7 +82,7 @@ def test_multi_predict(self):
8282
bst = xgb.train(params, dtrain)
8383
cpu_predict = bst.predict(dtest)
8484

85-
bst.set_param({"device": "sycl:gpu"})
85+
bst.set_param({"device": "sycl"})
8686

8787
predict0 = bst.predict(dtest)
8888
predict1 = bst.predict(dtest)
@@ -110,7 +110,7 @@ def test_sklearn(self):
110110
cpu_test_score = m.score(X_test, y_test)
111111

112112
# Now with sycl_predictor
113-
params['device'] = 'sycl:gpu'
113+
params['device'] = 'sycl'
114114
m.set_params(**params)
115115

116116
# m = xgb.XGBRegressor(**params).fit(X_train, y_train)
@@ -125,11 +125,14 @@ def test_sklearn(self):
125125
tm.make_dataset_strategy(), shap_parameter_strategy)
126126
@settings(deadline=None)
127127
def test_shap(self, num_rounds, dataset, param):
128-
param.update({"device": "sycl:gpu"})
128+
if dataset.name.endswith("-l1"): # not supported by the exact tree method
129+
return
130+
param.update({"tree_method": "hist", "device": "cpu"})
129131
param = dataset.set_params(param)
130132
dmat = dataset.get_dmat()
131133
bst = xgb.train(param, dmat, num_rounds)
132134
test_dmat = xgb.DMatrix(dataset.X, dataset.y, dataset.w, dataset.margin)
135+
bst.set_param({"device": "sycl"})
133136
shap = bst.predict(test_dmat, pred_contribs=True)
134137
margin = bst.predict(test_dmat, output_margin=True)
135138
assume(len(dataset.y) > 0)
@@ -139,11 +142,14 @@ def test_shap(self, num_rounds, dataset, param):
139142
tm.make_dataset_strategy(), shap_parameter_strategy)
140143
@settings(deadline=None, max_examples=20)
141144
def test_shap_interactions(self, num_rounds, dataset, param):
142-
param.update({"device": "sycl:gpu"})
145+
if dataset.name.endswith("-l1"): # not supported by the exact tree method
146+
return
147+
param.update({"tree_method": "hist", "device": "cpu"})
143148
param = dataset.set_params(param)
144149
dmat = dataset.get_dmat()
145150
bst = xgb.train(param, dmat, num_rounds)
146151
test_dmat = xgb.DMatrix(dataset.X, dataset.y, dataset.w, dataset.margin)
152+
bst.set_param({"device": "sycl"})
147153
shap = bst.predict(test_dmat, pred_interactions=True)
148154
margin = bst.predict(test_dmat, output_margin=True)
149155
assume(len(dataset.y) > 0)

tests/python-sycl/test_sycl_training_continuation.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ def run_training_continuation(self, use_json):
1212
X = np.random.randn(kRows, kCols)
1313
y = np.random.randn(kRows)
1414
dtrain = xgb.DMatrix(X, y)
15-
params = {'device': 'sycl:gpu', 'max_depth': '2',
15+
params = {'device': 'sycl', 'max_depth': '2',
1616
'gamma': '0.1', 'alpha': '0.01',
1717
'enable_experimental_json_serialization': use_json}
1818
bst_0 = xgb.train(params, dtrain, num_boost_round=64)

tests/python-sycl/test_sycl_updaters.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ class TestSYCLUpdaters:
3939
@settings(deadline=None)
4040
def test_sycl_hist(self, param, num_rounds, dataset):
4141
param['tree_method'] = 'hist'
42-
param['device'] = 'sycl:gpu'
42+
param['device'] = 'sycl'
4343
param['verbosity'] = 0
4444
param = dataset.set_params(param)
4545
result = train_result(param, dataset.get_dmat(), num_rounds)

0 commit comments

Comments
 (0)