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

Extract interaction constraint from split evaluator. #5034

Merged
merged 22 commits into from
Nov 14, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions amalgamation/xgboost-all0.cc
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
#include "../src/tree/updater_sync.cc"
#include "../src/tree/updater_histmaker.cc"
#include "../src/tree/updater_skmaker.cc"
#include "../src/tree/constraints.cc"

// linear
#include "../src/linear/linear_updater.cc"
Expand Down
2 changes: 2 additions & 0 deletions doc/parameter.rst
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,8 @@ Parameters for Tree Booster
- ``grow_histmaker``: distributed tree construction with row-based data splitting based on global proposal of histogram counting.
- ``grow_local_histmaker``: based on local histogram counting.
- ``grow_skmaker``: uses the approximate sketching algorithm.
- ``grow_quantile_histmaker``: Grow tree using quantized histogram.
- ``grow_gpu_hist``: Grow tree with GPU.
- ``sync``: synchronizes trees in all distributed nodes.
- ``refresh``: refreshes tree's statistics and/or leaf values based on the current data. Note that no random subsampling of data rows is performed.
- ``prune``: prunes the splits where loss < min_split_loss (or gamma).
Expand Down
6 changes: 3 additions & 3 deletions doc/tutorials/feature_interaction_constraint.rst
Original file line number Diff line number Diff line change
Expand Up @@ -172,9 +172,9 @@ parameter:
early_stopping_rounds = 10)

**Choice of tree construction algorithm**. To use feature interaction constraints, be sure
to set the ``tree_method`` parameter to one of the following: ``exact``, ``hist`` or
``gpu_hist``. Support for ``gpu_hist`` is added after (excluding) version 0.90.

to set the ``tree_method`` parameter to one of the following: ``exact``, ``hist``,
``approx`` or ``gpu_hist``. Support for ``gpu_hist`` and ``approx`` is added only in
1.0.0.

**************
Advanced topic
Expand Down
25 changes: 19 additions & 6 deletions include/xgboost/base.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,17 +100,30 @@

/*! \brief namespace of xgboost*/
namespace xgboost {
/*!
* \brief unsigned integer type used in boost,
* used for feature index and row index.
*/

/*! \brief unsigned integer type used for feature index. */
using bst_uint = uint32_t; // NOLINT
/*! \brief integer type. */
using bst_int = int32_t; // NOLINT
/*! \brief long integers */
typedef uint64_t bst_ulong; // NOLINT(*)
/*! \brief unsigned long integers */
using bst_ulong = uint64_t;
/*! \brief float type, used for storing statistics */
using bst_float = float; // NOLINT

/*! \brief Type for data column (feature) index. */
using bst_feature_t = uint32_t; // NOLINT
/*! \breif Type for data row index.
*
* Be careful `std::size_t' is implementation-defined. Meaning that the binary
* representation of DMatrix might not be portable across platform. Booster model should
* be portable as parameters are floating points.
*/
using bst_row_t = std::size_t; // NOLINT
/*! \brief Type for tree node index. */
using bst_node_t = int32_t; // NOLINT
/*! \brief Type for ranking group index. */
using bst_group_t = uint32_t; // NOLINT

namespace detail {
/*! \brief Implementation of gradient statistics pair. Template specialisation
* may be used to overload different gradients types e.g. low precision, high
Expand Down
8 changes: 4 additions & 4 deletions include/xgboost/data.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ class MetaInfo {
* \brief the index of begin and end of a group
* needed when the learning task is ranking.
*/
std::vector<bst_uint> group_ptr_;
std::vector<bst_group_t> group_ptr_;
/*! \brief weights of each instance, optional */
HostDeviceVector<bst_float> weights_;
/*!
Expand Down Expand Up @@ -136,7 +136,7 @@ class MetaInfo {
/*! \brief Element from a sparse vector */
struct Entry {
/*! \brief feature index */
bst_uint index;
bst_feature_t index;
/*! \brief feature value */
bst_float fvalue;
/*! \brief default constructor */
Expand All @@ -146,7 +146,7 @@ struct Entry {
* \param index The feature or row index.
* \param fvalue The feature value.
*/
Entry(bst_uint index, bst_float fvalue) : index(index), fvalue(fvalue) {}
Entry(bst_feature_t index, bst_float fvalue) : index(index), fvalue(fvalue) {}
/*! \brief reversely compare feature values */
inline static bool CmpValue(const Entry& a, const Entry& b) {
return a.fvalue < b.fvalue;
Expand Down Expand Up @@ -174,7 +174,7 @@ struct BatchParam {
class SparsePage {
public:
// Offset for each row.
HostDeviceVector<size_t> offset;
HostDeviceVector<bst_row_t> offset;
/*! \brief the data of the segments */
HostDeviceVector<Entry> data;

Expand Down
2 changes: 1 addition & 1 deletion include/xgboost/predictor.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
namespace xgboost {
class TreeUpdater;
namespace gbm {
class GBTreeModel;
struct GBTreeModel;
} // namespace gbm
}

Expand Down
16 changes: 9 additions & 7 deletions src/c_api/c_api.cc
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,9 @@ XGB_DLL int XGDMatrixCreateFromCSCEx(const size_t* col_ptr,
data::SimpleCSRSource& mat = *source;
auto& offset_vec = mat.page_.offset.HostVector();
auto& data_vec = mat.page_.data.HostVector();
common::ParallelGroupBuilder<Entry> builder(&offset_vec, &data_vec);
common::ParallelGroupBuilder<
Entry, std::remove_reference<decltype(offset_vec)>::type::value_type>
builder(&offset_vec, &data_vec);
builder.InitBudget(0, nthread);
size_t ncol = nindptr - 1; // NOLINT(*)
#pragma omp parallel for schedule(static)
Expand Down Expand Up @@ -362,19 +364,20 @@ XGB_DLL int XGDMatrixCreateFromMat(const bst_float* data,
API_END();
}

void PrefixSum(size_t *x, size_t N) {
size_t *suma;
template <typename T>
void PrefixSum(T *x, size_t N) {
std::vector<T> suma;
#pragma omp parallel
{
const int ithread = omp_get_thread_num();
const int nthreads = omp_get_num_threads();
#pragma omp single
{
suma = new size_t[nthreads+1];
suma.resize(nthreads+1);
suma[0] = 0;
}
size_t sum = 0;
size_t offset = 0;
T sum = 0;
T offset = 0;
#pragma omp for schedule(static)
for (omp_ulong i = 0; i < N; i++) {
sum += x[i];
Expand All @@ -390,7 +393,6 @@ void PrefixSum(size_t *x, size_t N) {
x[i] += offset;
}
}
delete[] suma;
}

XGB_DLL int XGDMatrixCreateFromMat_omp(const bst_float* data, // NOLINT
Expand Down
4 changes: 3 additions & 1 deletion src/common/group_data.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,16 @@

#include <vector>

#include "xgboost/base.h"

namespace xgboost {
namespace common {
/*!
* \brief multi-thread version of group builder
* \tparam ValueType type of entries in the sparse matrix
* \tparam SizeType type of the index range holder
*/
template<typename ValueType, typename SizeType = std::size_t>
template<typename ValueType, typename SizeType = bst_ulong>
struct ParallelGroupBuilder {
public:
// parallel group builder of data
Expand Down
2 changes: 1 addition & 1 deletion src/common/hist_util.cc
Original file line number Diff line number Diff line change
Expand Up @@ -421,7 +421,7 @@ void GHistIndexMatrix::Init(DMatrix* p_fmat, int max_num_bins) {

#pragma omp parallel for num_threads(nthread) schedule(static)
for (bst_omp_uint idx = 0; idx < bst_omp_uint(nbins); ++idx) {
for (size_t tid = 0; tid < nthread; ++tid) {
for (int32_t tid = 0; tid < nthread; ++tid) {
hit_count[idx] += hit_count_tloc_[tid * nbins + idx];
}
}
Expand Down
16 changes: 14 additions & 2 deletions src/common/host_device_vector.cc
Original file line number Diff line number Diff line change
Expand Up @@ -157,9 +157,21 @@ void HostDeviceVector<T>::SetDevice(int device) const {}
// explicit instantiations are required, as HostDeviceVector isn't header-only
template class HostDeviceVector<bst_float>;
template class HostDeviceVector<GradientPair>;
template class HostDeviceVector<int>;
template class HostDeviceVector<int32_t>; // bst_node_t
template class HostDeviceVector<Entry>;
template class HostDeviceVector<size_t>;
template class HostDeviceVector<uint64_t>; // bst_row_t
template class HostDeviceVector<uint32_t>; // bst_feature_t

#if defined(__APPLE__)
/*
* On OSX:
*
* typedef unsigned int uint32_t;
* typedef unsigned long long uint64_t;
* typedef unsigned long __darwin_size_t;
*/
template class HostDeviceVector<std::size_t>;
#endif // defined(__APPLE__)

} // namespace xgboost

Expand Down
16 changes: 14 additions & 2 deletions src/common/host_device_vector.cu
Original file line number Diff line number Diff line change
Expand Up @@ -351,8 +351,20 @@ void HostDeviceVector<T>::Resize(size_t new_size, T v) {
// explicit instantiations are required, as HostDeviceVector isn't header-only
template class HostDeviceVector<bst_float>;
template class HostDeviceVector<GradientPair>;
template class HostDeviceVector<int>;
template class HostDeviceVector<int32_t>; // bst_node_t
template class HostDeviceVector<Entry>;
template class HostDeviceVector<size_t>;
template class HostDeviceVector<uint64_t>; // bst_row_t
template class HostDeviceVector<uint32_t>; // bst_feature_t

#if defined(__APPLE__)
/*
* On OSX:
*
* typedef unsigned int uint32_t;
* typedef unsigned long long uint64_t;
* typedef unsigned long __darwin_size_t;
*/
template class HostDeviceVector<std::size_t>;
#endif // defined(__APPLE__)

} // namespace xgboost
14 changes: 7 additions & 7 deletions src/common/random.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,20 +85,20 @@ GlobalRandomEngine& GlobalRandom(); // NOLINT(*)
*/

class ColumnSampler {
std::shared_ptr<HostDeviceVector<int>> feature_set_tree_;
std::map<int, std::shared_ptr<HostDeviceVector<int>>> feature_set_level_;
std::shared_ptr<HostDeviceVector<bst_feature_t>> feature_set_tree_;
std::map<int, std::shared_ptr<HostDeviceVector<bst_feature_t>>> feature_set_level_;
float colsample_bylevel_{1.0f};
float colsample_bytree_{1.0f};
float colsample_bynode_{1.0f};
GlobalRandomEngine rng_;

std::shared_ptr<HostDeviceVector<int>> ColSample(
std::shared_ptr<HostDeviceVector<int>> p_features, float colsample) {
std::shared_ptr<HostDeviceVector<bst_feature_t>> ColSample(
std::shared_ptr<HostDeviceVector<bst_feature_t>> p_features, float colsample) {
if (colsample == 1.0f) return p_features;
const auto& features = p_features->HostVector();
CHECK_GT(features.size(), 0);
int n = std::max(1, static_cast<int>(colsample * features.size()));
auto p_new_features = std::make_shared<HostDeviceVector<int>>();
auto p_new_features = std::make_shared<HostDeviceVector<bst_feature_t>>();
auto& new_features = *p_new_features;
new_features.Resize(features.size());
std::copy(features.begin(), features.end(),
Expand Down Expand Up @@ -147,7 +147,7 @@ class ColumnSampler {
colsample_bynode_ = colsample_bynode;

if (feature_set_tree_ == nullptr) {
feature_set_tree_ = std::make_shared<HostDeviceVector<int>>();
feature_set_tree_ = std::make_shared<HostDeviceVector<bst_feature_t>>();
}
Reset();

Expand Down Expand Up @@ -178,7 +178,7 @@ class ColumnSampler {
* construction of each tree node, and must be called the same number of times in each
* process and with the same parameters to return the same feature set across processes.
*/
std::shared_ptr<HostDeviceVector<int>> GetFeatureSet(int depth) {
std::shared_ptr<HostDeviceVector<bst_feature_t>> GetFeatureSet(int depth) {
if (colsample_bylevel_ == 1.0f && colsample_bynode_ == 1.0f) {
return feature_set_tree_;
}
Expand Down
13 changes: 6 additions & 7 deletions src/data/data.cc
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ DMatrix* DMatrix::Load(const std::string& uri,

std::unique_ptr<dmlc::Parser<uint32_t> > parser(
dmlc::Parser<uint32_t>::Create(fname.c_str(), partid, npart, file_format.c_str()));
DMatrix* dmat;
DMatrix* dmat {nullptr};

try {
dmat = DMatrix::Create(parser.get(), cache_file, page_size);
Expand All @@ -253,9 +253,8 @@ DMatrix* DMatrix::Load(const std::string& uri,
<< "Choosing default parser in dmlc-core. "
<< "Consider providing a uri parameter like: filename?format=csv";
}

LOG(FATAL) << "Encountered parser error:\n" << e.what();
}
LOG(FATAL) << "Encountered parser error:\n" << e.what();
}

if (!silent) {
Expand Down Expand Up @@ -361,8 +360,8 @@ DMatrix* DMatrix::Create(std::unique_ptr<DataSource<SparsePage>>&& source,
namespace xgboost {
SparsePage SparsePage::GetTranspose(int num_columns) const {
SparsePage transpose;
common::ParallelGroupBuilder<Entry> builder(&transpose.offset.HostVector(),
&transpose.data.HostVector());
common::ParallelGroupBuilder<Entry, bst_row_t> builder(&transpose.offset.HostVector(),
&transpose.data.HostVector());
const int nthread = omp_get_max_threads();
builder.InitBudget(num_columns, nthread);
long batch_size = static_cast<long>(this->Size()); // NOLINT(*)
Expand Down Expand Up @@ -424,7 +423,7 @@ void SparsePage::Push(const dmlc::RowBlock<uint32_t>& batch) {

void SparsePage::PushCSC(const SparsePage &batch) {
std::vector<xgboost::Entry>& self_data = data.HostVector();
std::vector<size_t>& self_offset = offset.HostVector();
std::vector<bst_row_t>& self_offset = offset.HostVector();

auto const& other_data = batch.data.ConstHostVector();
auto const& other_offset = batch.offset.ConstHostVector();
Expand All @@ -442,7 +441,7 @@ void SparsePage::PushCSC(const SparsePage &batch) {
return;
}

std::vector<size_t> offset(other_offset.size());
std::vector<bst_row_t> offset(other_offset.size());
offset[0] = 0;

std::vector<xgboost::Entry> data(self_data.size() + other_data.size());
Expand Down
16 changes: 8 additions & 8 deletions src/data/simple_csr_source.cu
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ namespace data {
template <typename T>
__global__ void CountValidKernel(Columnar<T> const column,
bool has_missing, float missing,
int32_t* flag, common::Span<size_t> offsets) {
int32_t* flag, common::Span<bst_row_t> offsets) {
auto const tid = threadIdx.x + blockDim.x * blockIdx.x;
bool const missing_is_nan = common::CheckNAN(missing);

Expand Down Expand Up @@ -59,7 +59,7 @@ __global__ void CountValidKernel(Columnar<T> const column,

template <typename T>
__device__ void AssignValue(T fvalue, int32_t colid,
common::Span<size_t> out_offsets, common::Span<Entry> out_data) {
common::Span<bst_row_t> out_offsets, common::Span<Entry> out_data) {
auto const tid = threadIdx.x + blockDim.x * blockIdx.x;
int32_t oid = out_offsets[tid];
out_data[oid].fvalue = fvalue;
Expand All @@ -70,7 +70,7 @@ __device__ void AssignValue(T fvalue, int32_t colid,
template <typename T>
__global__ void CreateCSRKernel(Columnar<T> const column,
int32_t colid, bool has_missing, float missing,
common::Span<size_t> offsets, common::Span<Entry> out_data) {
common::Span<bst_row_t> offsets, common::Span<Entry> out_data) {
auto const tid = threadIdx.x + blockDim.x * blockIdx.x;
if (column.size <= tid) {
return;
Expand Down Expand Up @@ -98,7 +98,7 @@ __global__ void CreateCSRKernel(Columnar<T> const column,
template <typename T>
void CountValid(std::vector<Json> const& j_columns, uint32_t column_id,
bool has_missing, float missing,
HostDeviceVector<size_t>* out_offset,
HostDeviceVector<bst_row_t>* out_offset,
dh::caching_device_vector<int32_t>* out_d_flag,
uint32_t* out_n_rows) {
uint32_t constexpr kThreads = 256;
Expand All @@ -121,7 +121,7 @@ void CountValid(std::vector<Json> const& j_columns, uint32_t column_id,
CHECK_EQ(out_offset->Size(), n_rows + 1)
<< "All columns should have same number of rows.";

common::Span<size_t> s_offsets = out_offset->DeviceSpan();
common::Span<bst_row_t> s_offsets = out_offset->DeviceSpan();

uint32_t const kBlocks = common::DivRoundUp(n_rows, kThreads);
dh::LaunchKernel {kBlocks, kThreads} (
Expand All @@ -135,7 +135,7 @@ void CountValid(std::vector<Json> const& j_columns, uint32_t column_id,
template <typename T>
void CreateCSR(std::vector<Json> const& j_columns, uint32_t column_id, uint32_t n_rows,
bool has_missing, float missing,
dh::device_vector<size_t>* tmp_offset, common::Span<Entry> s_data) {
dh::device_vector<bst_row_t>* tmp_offset, common::Span<Entry> s_data) {
uint32_t constexpr kThreads = 256;
auto const& j_column = j_columns[column_id];
auto const& column_obj = get<Object const>(j_column);
Expand Down Expand Up @@ -174,13 +174,13 @@ void SimpleCSRSource::FromDeviceColumnar(std::vector<Json> const& columns,
info.num_row_ = n_rows;

auto s_offsets = this->page_.offset.DeviceSpan();
thrust::device_ptr<size_t> p_offsets(s_offsets.data());
thrust::device_ptr<bst_row_t> p_offsets(s_offsets.data());
CHECK_GE(s_offsets.size(), n_rows + 1);

thrust::inclusive_scan(p_offsets, p_offsets + n_rows + 1, p_offsets);
// Created for building csr matrix, where we need to change index after processing each
// column.
dh::device_vector<size_t> tmp_offset(this->page_.offset.Size());
dh::device_vector<bst_row_t> tmp_offset(this->page_.offset.Size());
dh::safe_cuda(cudaMemcpy(tmp_offset.data().get(), s_offsets.data(),
s_offsets.size_bytes(), cudaMemcpyDeviceToDevice));

Expand Down
Loading