lint half way

This commit is contained in:
tqchen 2015-07-03 18:31:52 -07:00
parent 2ed40523ab
commit 0162bb7034
21 changed files with 573 additions and 391 deletions

View File

@ -1,11 +1,13 @@
#ifndef XGBOOST_GBM_GBLINEAR_INL_HPP_
#define XGBOOST_GBM_GBLINEAR_INL_HPP_
/*! /*!
* Copyright by Contributors
* \file gblinear-inl.hpp * \file gblinear-inl.hpp
* \brief Implementation of Linear booster, with L1/L2 regularization: Elastic Net * \brief Implementation of Linear booster, with L1/L2 regularization: Elastic Net
* the update rule is parallel coordinate descent (shotgun) * the update rule is parallel coordinate descent (shotgun)
* \author Tianqi Chen * \author Tianqi Chen
*/ */
#ifndef XGBOOST_GBM_GBLINEAR_INL_HPP_
#define XGBOOST_GBM_GBLINEAR_INL_HPP_
#include <vector> #include <vector>
#include <string> #include <string>
#include <sstream> #include <sstream>
@ -33,10 +35,10 @@ class GBLinear : public IGradBooster {
model.param.SetParam(name, val); model.param.SetParam(name, val);
} }
} }
virtual void LoadModel(utils::IStream &fi, bool with_pbuffer) { virtual void LoadModel(utils::IStream &fi, bool with_pbuffer) { // NOLINT(*)
model.LoadModel(fi); model.LoadModel(fi);
} }
virtual void SaveModel(utils::IStream &fo, bool with_pbuffer) const { virtual void SaveModel(utils::IStream &fo, bool with_pbuffer) const { // NOLINT(*)
model.SaveModel(fo); model.SaveModel(fo);
} }
virtual void InitModel(void) { virtual void InitModel(void) {
@ -92,7 +94,8 @@ class GBLinear : public IGradBooster {
sum_hess += p.hess * v * v; sum_hess += p.hess * v * v;
} }
float &w = model[fid][gid]; float &w = model[fid][gid];
bst_float dw = static_cast<bst_float>(param.learning_rate * param.CalcDelta(sum_grad, sum_hess, w)); bst_float dw = static_cast<bst_float>(param.learning_rate *
param.CalcDelta(sum_grad, sum_hess, w));
w += dw; w += dw;
// update grad value // update grad value
for (bst_uint j = 0; j < col.length; ++j) { for (bst_uint j = 0; j < col.length; ++j) {
@ -258,12 +261,12 @@ class GBLinear : public IGradBooster {
std::fill(weight.begin(), weight.end(), 0.0f); std::fill(weight.begin(), weight.end(), 0.0f);
} }
// save the model to file // save the model to file
inline void SaveModel(utils::IStream &fo) const { inline void SaveModel(utils::IStream &fo) const { // NOLINT(*)
fo.Write(&param, sizeof(Param)); fo.Write(&param, sizeof(Param));
fo.Write(weight); fo.Write(weight);
} }
// load model from file // load model from file
inline void LoadModel(utils::IStream &fi) { inline void LoadModel(utils::IStream &fi) { // NOLINT(*)
utils::Assert(fi.Read(&param, sizeof(Param)) != 0, "Load LinearBooster"); utils::Assert(fi.Read(&param, sizeof(Param)) != 0, "Load LinearBooster");
fi.Read(&weight); fi.Read(&weight);
} }

View File

@ -1,3 +1,4 @@
// Copyright by Contributors
#define _CRT_SECURE_NO_WARNINGS #define _CRT_SECURE_NO_WARNINGS
#define _CRT_SECURE_NO_DEPRECATE #define _CRT_SECURE_NO_DEPRECATE
#define NOMINMAX #define NOMINMAX

View File

@ -1,11 +1,14 @@
#ifndef XGBOOST_GBM_GBM_H_
#define XGBOOST_GBM_GBM_H_
/*! /*!
* Copyright by Contributors
* \file gbm.h * \file gbm.h
* \brief interface of gradient booster, that learns through gradient statistics * \brief interface of gradient booster, that learns through gradient statistics
* \author Tianqi Chen * \author Tianqi Chen
*/ */
#ifndef XGBOOST_GBM_GBM_H_
#define XGBOOST_GBM_GBM_H_
#include <vector> #include <vector>
#include <string>
#include "../data.h" #include "../data.h"
#include "../utils/io.h" #include "../utils/io.h"
#include "../utils/fmap.h" #include "../utils/fmap.h"
@ -29,13 +32,13 @@ class IGradBooster {
* \param fi input stream * \param fi input stream
* \param with_pbuffer whether the incoming data contains pbuffer * \param with_pbuffer whether the incoming data contains pbuffer
*/ */
virtual void LoadModel(utils::IStream &fi, bool with_pbuffer) = 0; virtual void LoadModel(utils::IStream &fi, bool with_pbuffer) = 0; // NOLINT(*)
/*! /*!
* \brief save model to stream * \brief save model to stream
* \param fo output stream * \param fo output stream
* \param with_pbuffer whether save out pbuffer * \param with_pbuffer whether save out pbuffer
*/ */
virtual void SaveModel(utils::IStream &fo, bool with_pbuffer) const = 0; virtual void SaveModel(utils::IStream &fo, bool with_pbuffer) const = 0; // NOLINT(*)
/*! /*!
* \brief initialize the model * \brief initialize the model
*/ */

View File

@ -1,13 +1,16 @@
#ifndef XGBOOST_GBM_GBTREE_INL_HPP_
#define XGBOOST_GBM_GBTREE_INL_HPP_
/*! /*!
* Copyright by Contributors
* \file gbtree-inl.hpp * \file gbtree-inl.hpp
* \brief gradient boosted tree implementation * \brief gradient boosted tree implementation
* \author Tianqi Chen * \author Tianqi Chen
*/ */
#ifndef XGBOOST_GBM_GBTREE_INL_HPP_
#define XGBOOST_GBM_GBTREE_INL_HPP_
#include <vector> #include <vector>
#include <utility> #include <utility>
#include <string> #include <string>
#include <limits>
#include "./gbm.h" #include "./gbm.h"
#include "../utils/omp.h" #include "../utils/omp.h"
#include "../tree/updater.h" #include "../tree/updater.h"
@ -39,7 +42,7 @@ class GBTree : public IGradBooster {
tparam.SetParam(name, val); tparam.SetParam(name, val);
if (trees.size() == 0) mparam.SetParam(name, val); if (trees.size() == 0) mparam.SetParam(name, val);
} }
virtual void LoadModel(utils::IStream &fi, bool with_pbuffer) { virtual void LoadModel(utils::IStream &fi, bool with_pbuffer) { // NOLINT(*)
this->Clear(); this->Clear();
utils::Check(fi.Read(&mparam, sizeof(ModelParam)) != 0, utils::Check(fi.Read(&mparam, sizeof(ModelParam)) != 0,
"GBTree: invalid model file"); "GBTree: invalid model file");
@ -62,7 +65,7 @@ class GBTree : public IGradBooster {
"GBTree: invalid model file"); "GBTree: invalid model file");
} }
} }
virtual void SaveModel(utils::IStream &fo, bool with_pbuffer) const { virtual void SaveModel(utils::IStream &fo, bool with_pbuffer) const { // NOLINT(*)
utils::Assert(mparam.num_trees == static_cast<int>(trees.size()), "GBTree"); utils::Assert(mparam.num_trees == static_cast<int>(trees.size()), "GBTree");
if (with_pbuffer) { if (with_pbuffer) {
fo.Write(&mparam, sizeof(ModelParam)); fo.Write(&mparam, sizeof(ModelParam));
@ -196,7 +199,6 @@ class GBTree : public IGradBooster {
thread_temp[i].Init(mparam.num_feature); thread_temp[i].Init(mparam.num_feature);
} }
this->PredPath(p_fmat, info, out_preds, ntree_limit); this->PredPath(p_fmat, info, out_preds, ntree_limit);
} }
virtual std::vector<std::string> DumpModel(const utils::FeatMap& fmap, int option) { virtual std::vector<std::string> DumpModel(const utils::FeatMap& fmap, int option) {
std::vector<std::string> dump; std::vector<std::string> dump;

View File

@ -1,11 +1,13 @@
#ifndef XGBOOST_IO_IO_H_
#define XGBOOST_IO_IO_H_
/*! /*!
* Copyright 2014 by Contributors
* \file io.h * \file io.h
* \brief handles input data format of xgboost * \brief handles input data format of xgboost
* I/O module handles a specific DMatrix format * I/O module handles a specific DMatrix format
* \author Tianqi Chen * \author Tianqi Chen
*/ */
#ifndef XGBOOST_IO_IO_H_
#define XGBOOST_IO_IO_H_
#include "../data.h" #include "../data.h"
#include "../learner/dmatrix.h" #include "../learner/dmatrix.h"
@ -40,7 +42,6 @@ DataMatrix* LoadDataMatrix(const char *fname,
* \param silent whether print message during saving * \param silent whether print message during saving
*/ */
void SaveDataMatrix(const DataMatrix &dmat, const char *fname, bool silent = false); void SaveDataMatrix(const DataMatrix &dmat, const char *fname, bool silent = false);
} // namespace io } // namespace io
} // namespace xgboost } // namespace xgboost
#endif // XGBOOST_IO_IO_H_ #endif // XGBOOST_IO_IO_H_

View File

@ -1,10 +1,12 @@
#ifndef XGBOOST_TREE_MODEL_H_
#define XGBOOST_TREE_MODEL_H_
/*! /*!
* Copyright 2014 by Contributors
* \file model.h * \file model.h
* \brief model structure for tree * \brief model structure for tree
* \author Tianqi Chen * \author Tianqi Chen
*/ */
#ifndef XGBOOST_TREE_MODEL_H_
#define XGBOOST_TREE_MODEL_H_
#include <string> #include <string>
#include <cstring> #include <cstring>
#include <sstream> #include <sstream>
@ -292,7 +294,7 @@ class TreeModel {
* \brief load model from stream * \brief load model from stream
* \param fi input stream * \param fi input stream
*/ */
inline void LoadModel(utils::IStream &fi) { inline void LoadModel(utils::IStream &fi) { // NOLINT(*)
utils::Check(fi.Read(&param, sizeof(Param)) > 0, utils::Check(fi.Read(&param, sizeof(Param)) > 0,
"TreeModel: wrong format"); "TreeModel: wrong format");
nodes.resize(param.num_nodes); stats.resize(param.num_nodes); nodes.resize(param.num_nodes); stats.resize(param.num_nodes);
@ -317,7 +319,7 @@ class TreeModel {
* \brief save model to stream * \brief save model to stream
* \param fo output stream * \param fo output stream
*/ */
inline void SaveModel(utils::IStream &fo) const { inline void SaveModel(utils::IStream &fo) const { // NOLINT(*)
utils::Assert(param.num_nodes == static_cast<int>(nodes.size()), utils::Assert(param.num_nodes == static_cast<int>(nodes.size()),
"Tree::SaveModel"); "Tree::SaveModel");
utils::Assert(param.num_nodes == static_cast<int>(stats.size()), utils::Assert(param.num_nodes == static_cast<int>(stats.size()),
@ -400,7 +402,7 @@ class TreeModel {
} }
private: private:
void Dump(int nid, std::stringstream &fo, void Dump(int nid, std::stringstream &fo, // NOLINT(*)
const utils::FeatMap& fmap, int depth, bool with_stats) { const utils::FeatMap& fmap, int depth, bool with_stats) {
for (int i = 0; i < depth; ++i) { for (int i = 0; i < depth; ++i) {
fo << '\t'; fo << '\t';
@ -469,7 +471,7 @@ struct RTreeNodeStat {
/*! \brief number of child that is leaf node known up to now */ /*! \brief number of child that is leaf node known up to now */
int leaf_child_cnt; int leaf_child_cnt;
/*! \brief print information of current stats to fo */ /*! \brief print information of current stats to fo */
inline void Print(std::stringstream &fo, bool is_leaf) const { inline void Print(std::stringstream &fo, bool is_leaf) const { // NOLINT(*)
if (!is_leaf) { if (!is_leaf) {
fo << ",gain=" << loss_chg << ",cover=" << sum_hess; fo << ",gain=" << loss_chg << ",cover=" << sum_hess;
} else { } else {

View File

@ -1,10 +1,13 @@
#ifndef XGBOOST_TREE_PARAM_H_
#define XGBOOST_TREE_PARAM_H_
/*! /*!
* Copyright 2014 by Contributors
* \file param.h * \file param.h
* \brief training parameters, statistics used to support tree construction * \brief training parameters, statistics used to support tree construction
* \author Tianqi Chen * \author Tianqi Chen
*/ */
#ifndef XGBOOST_TREE_PARAM_H_
#define XGBOOST_TREE_PARAM_H_
#include <vector>
#include <cstring> #include <cstring>
#include "../data.h" #include "../data.h"
@ -244,7 +247,7 @@ struct GradStats {
this->Add(b.sum_grad, b.sum_hess); this->Add(b.sum_grad, b.sum_hess);
} }
/*! \brief same as add, reduce is used in All Reduce */ /*! \brief same as add, reduce is used in All Reduce */
inline static void Reduce(GradStats &a, const GradStats &b) { inline static void Reduce(GradStats &a, const GradStats &b) { // NOLINT(*)
a.Add(b); a.Add(b);
} }
/*! \brief set current value to a - b */ /*! \brief set current value to a - b */
@ -324,7 +327,7 @@ struct CVGradStats : public GradStats {
} }
} }
/*! \brief same as add, reduce is used in All Reduce */ /*! \brief same as add, reduce is used in All Reduce */
inline static void Reduce(CVGradStats &a, const CVGradStats &b) { inline static void Reduce(CVGradStats &a, const CVGradStats &b) { // NOLINT(*)
a.Add(b); a.Add(b);
} }
/*! \brief set current value to a - b */ /*! \brief set current value to a - b */
@ -407,7 +410,7 @@ struct SplitEntry{
} }
} }
/*! \brief same as update, used by AllReduce*/ /*! \brief same as update, used by AllReduce*/
inline static void Reduce(SplitEntry &dst, const SplitEntry &src) { inline static void Reduce(SplitEntry &dst, const SplitEntry &src) { // NOLINT(*)
dst.Update(src); dst.Update(src);
} }
/*!\return feature index to split on */ /*!\return feature index to split on */

View File

@ -1,3 +1,4 @@
// Copyright 2014 by Contributors
#define _CRT_SECURE_NO_WARNINGS #define _CRT_SECURE_NO_WARNINGS
#define _CRT_SECURE_NO_DEPRECATE #define _CRT_SECURE_NO_DEPRECATE
#define NOMINMAX #define NOMINMAX

View File

@ -1,10 +1,12 @@
#ifndef XGBOOST_TREE_UPDATER_H_
#define XGBOOST_TREE_UPDATER_H_
/*! /*!
* Copyright 2014 by Contributors
* \file updater.h * \file updater.h
* \brief interface to update the tree * \brief interface to update the tree
* \author Tianqi Chen * \author Tianqi Chen
*/ */
#ifndef XGBOOST_TREE_UPDATER_H_
#define XGBOOST_TREE_UPDATER_H_
#include <vector> #include <vector>
#include "../data.h" #include "../data.h"

View File

@ -1,12 +1,14 @@
#ifndef XGBOOST_TREE_UPDATER_BASEMAKER_INL_HPP_
#define XGBOOST_TREE_UPDATER_BASEMAKER_INL_HPP_
/*! /*!
* Copyright 2014 by Contributors
* \file updater_basemaker-inl.hpp * \file updater_basemaker-inl.hpp
* \brief implement a common tree constructor * \brief implement a common tree constructor
* \author Tianqi Chen * \author Tianqi Chen
*/ */
#ifndef XGBOOST_TREE_UPDATER_BASEMAKER_INL_HPP_
#define XGBOOST_TREE_UPDATER_BASEMAKER_INL_HPP_
#include <vector> #include <vector>
#include <algorithm> #include <algorithm>
#include <string>
#include <limits> #include <limits>
#include "../sync/sync.h" #include "../sync/sync.h"
#include "../utils/random.h" #include "../utils/random.h"
@ -60,8 +62,11 @@ class BaseMaker: public IUpdater {
bst_float a = fminmax[fid * 2]; bst_float a = fminmax[fid * 2];
bst_float b = fminmax[fid * 2 + 1]; bst_float b = fminmax[fid * 2 + 1];
if (a == -std::numeric_limits<bst_float>::max()) return 0; if (a == -std::numeric_limits<bst_float>::max()) return 0;
if (-a == b) return 1; if (-a == b) {
else return 2; return 1;
} else {
return 2;
}
} }
inline bst_float MaxValue(bst_uint fid) const { inline bst_float MaxValue(bst_uint fid) const {
return fminmax[fid *2 + 1]; return fminmax[fid *2 + 1];
@ -124,7 +129,8 @@ class BaseMaker: public IUpdater {
const RegTree &tree) { const RegTree &tree) {
utils::Assert(tree.param.num_nodes == tree.param.num_roots, utils::Assert(tree.param.num_nodes == tree.param.num_roots,
"TreeMaker: can only grow new tree"); "TreeMaker: can only grow new tree");
{// setup position {
// setup position
position.resize(gpair.size()); position.resize(gpair.size());
if (root_index.size() == 0) { if (root_index.size() == 0) {
std::fill(position.begin(), position.end(), 0); std::fill(position.begin(), position.end(), 0);
@ -147,7 +153,8 @@ class BaseMaker: public IUpdater {
} }
} }
} }
{// expand query {
// expand query
qexpand.reserve(256); qexpand.clear(); qexpand.reserve(256); qexpand.clear();
for (int i = 0; i < tree.param.num_roots; ++i) { for (int i = 0; i < tree.param.num_roots; ++i) {
qexpand.push_back(i); qexpand.push_back(i);
@ -189,7 +196,8 @@ class BaseMaker: public IUpdater {
* \param p_fmat feature matrix needed for tree construction * \param p_fmat feature matrix needed for tree construction
* \param tree the regression tree structure * \param tree the regression tree structure
*/ */
inline void ResetPositionCol(const std::vector<int> &nodes, IFMatrix *p_fmat, const RegTree &tree) { inline void ResetPositionCol(const std::vector<int> &nodes,
IFMatrix *p_fmat, const RegTree &tree) {
// set the positions in the nondefault // set the positions in the nondefault
this->SetNonDefaultPositionCol(nodes, p_fmat, tree); this->SetNonDefaultPositionCol(nodes, p_fmat, tree);
// set rest of instances to default position // set rest of instances to default position
@ -339,7 +347,8 @@ class BaseMaker: public IUpdater {
if (last_fvalue != fvalue) { if (last_fvalue != fvalue) {
double rmax = rmin + wmin; double rmax = rmin + wmin;
if (rmax >= next_goal && sketch->temp.size != max_size) { if (rmax >= next_goal && sketch->temp.size != max_size) {
if (sketch->temp.size == 0 || last_fvalue > sketch->temp.data[sketch->temp.size-1].value) { if (sketch->temp.size == 0 ||
last_fvalue > sketch->temp.data[sketch->temp.size-1].value) {
// push to sketch // push to sketch
sketch->temp.data[sketch->temp.size] = sketch->temp.data[sketch->temp.size] =
utils::WXQuantileSketch<bst_float, bst_float>:: utils::WXQuantileSketch<bst_float, bst_float>::

View File

@ -1,10 +1,12 @@
#ifndef XGBOOST_TREE_UPDATER_COLMAKER_INL_HPP_
#define XGBOOST_TREE_UPDATER_COLMAKER_INL_HPP_
/*! /*!
* Copyright 2014 by Contributors
* \file updater_colmaker-inl.hpp * \file updater_colmaker-inl.hpp
* \brief use columnwise update to construct a tree * \brief use columnwise update to construct a tree
* \author Tianqi Chen * \author Tianqi Chen
*/ */
#ifndef XGBOOST_TREE_UPDATER_COLMAKER_INL_HPP_
#define XGBOOST_TREE_UPDATER_COLMAKER_INL_HPP_
#include <vector> #include <vector>
#include <cmath> #include <cmath>
#include <algorithm> #include <algorithm>
@ -114,10 +116,13 @@ class ColMaker: public IUpdater {
// initialize temp data structure // initialize temp data structure
inline void InitData(const std::vector<bst_gpair> &gpair, inline void InitData(const std::vector<bst_gpair> &gpair,
const IFMatrix &fmat, const IFMatrix &fmat,
const std::vector<unsigned> &root_index, const RegTree &tree) { const std::vector<unsigned> &root_index,
utils::Assert(tree.param.num_nodes == tree.param.num_roots, "ColMaker: can only grow new tree"); const RegTree &tree) {
utils::Assert(tree.param.num_nodes == tree.param.num_roots,
"ColMaker: can only grow new tree");
const std::vector<bst_uint> &rowset = fmat.buffered_rowset(); const std::vector<bst_uint> &rowset = fmat.buffered_rowset();
{// setup position {
// setup position
position.resize(gpair.size()); position.resize(gpair.size());
if (root_index.size() == 0) { if (root_index.size() == 0) {
for (size_t i = 0; i < rowset.size(); ++i) { for (size_t i = 0; i < rowset.size(); ++i) {
@ -127,7 +132,8 @@ class ColMaker: public IUpdater {
for (size_t i = 0; i < rowset.size(); ++i) { for (size_t i = 0; i < rowset.size(); ++i) {
const bst_uint ridx = rowset[i]; const bst_uint ridx = rowset[i];
position[ridx] = root_index[ridx]; position[ridx] = root_index[ridx];
utils::Assert(root_index[ridx] < (unsigned)tree.param.num_roots, "root index exceed setting"); utils::Assert(root_index[ridx] < (unsigned)tree.param.num_roots,
"root index exceed setting");
} }
} }
// mark delete for the deleted datas // mark delete for the deleted datas
@ -154,11 +160,12 @@ class ColMaker: public IUpdater {
} }
unsigned n = static_cast<unsigned>(param.colsample_bytree * feat_index.size()); unsigned n = static_cast<unsigned>(param.colsample_bytree * feat_index.size());
random::Shuffle(feat_index); random::Shuffle(feat_index);
//utils::Check(n > 0, "colsample_bytree is too small that no feature can be included"); utils::Check(n > 0, "colsample_bytree=%g is too small that no feature can be included",
utils::Check(n > 0, "colsample_bytree=%g is too small that no feature can be included", param.colsample_bytree); param.colsample_bytree);
feat_index.resize(n); feat_index.resize(n);
} }
{// setup temp space for each thread {
// setup temp space for each thread
#pragma omp parallel #pragma omp parallel
{ {
this->nthread = omp_get_num_threads(); this->nthread = omp_get_num_threads();
@ -171,20 +178,25 @@ class ColMaker: public IUpdater {
} }
snode.reserve(256); snode.reserve(256);
} }
{// expand query {
// expand query
qexpand_.reserve(256); qexpand_.clear(); qexpand_.reserve(256); qexpand_.clear();
for (int i = 0; i < tree.param.num_roots; ++i) { for (int i = 0; i < tree.param.num_roots; ++i) {
qexpand_.push_back(i); qexpand_.push_back(i);
} }
} }
} }
/*! \brief initialize the base_weight, root_gain, and NodeEntry for all the new nodes in qexpand */ /*!
* \brief initialize the base_weight, root_gain,
* and NodeEntry for all the new nodes in qexpand
*/
inline void InitNewNode(const std::vector<int> &qexpand, inline void InitNewNode(const std::vector<int> &qexpand,
const std::vector<bst_gpair> &gpair, const std::vector<bst_gpair> &gpair,
const IFMatrix &fmat, const IFMatrix &fmat,
const BoosterInfo &info, const BoosterInfo &info,
const RegTree &tree) { const RegTree &tree) {
{// setup statistics space for each tree node {
// setup statistics space for each tree node
for (size_t i = 0; i < stemp.size(); ++i) { for (size_t i = 0; i < stemp.size(); ++i) {
stemp[i].resize(tree.param.num_nodes, ThreadEntry(param)); stemp[i].resize(tree.param.num_nodes, ThreadEntry(param));
} }
@ -290,16 +302,20 @@ class ColMaker: public IUpdater {
} }
if (need_forward && tid != 0) { if (need_forward && tid != 0) {
c.SetSubstract(snode[nid].stats, e.stats); c.SetSubstract(snode[nid].stats, e.stats);
if (c.sum_hess >= param.min_child_weight && e.stats.sum_hess >= param.min_child_weight) { if (c.sum_hess >= param.min_child_weight &&
bst_float loss_chg = static_cast<bst_float>(e.stats.CalcGain(param) + c.CalcGain(param) - snode[nid].root_gain); e.stats.sum_hess >= param.min_child_weight) {
bst_float loss_chg = static_cast<bst_float>(e.stats.CalcGain(param) +
c.CalcGain(param) - snode[nid].root_gain);
e.best.Update(loss_chg, fid, fsplit, false); e.best.Update(loss_chg, fid, fsplit, false);
} }
} }
if (need_backward) { if (need_backward) {
tmp.SetSubstract(sum, e.stats); tmp.SetSubstract(sum, e.stats);
c.SetSubstract(snode[nid].stats, tmp); c.SetSubstract(snode[nid].stats, tmp);
if (c.sum_hess >= param.min_child_weight && tmp.sum_hess >= param.min_child_weight) { if (c.sum_hess >= param.min_child_weight &&
bst_float loss_chg = static_cast<bst_float>(tmp.CalcGain(param) + c.CalcGain(param) - snode[nid].root_gain); tmp.sum_hess >= param.min_child_weight) {
bst_float loss_chg = static_cast<bst_float>(tmp.CalcGain(param) +
c.CalcGain(param) - snode[nid].root_gain);
e.best.Update(loss_chg, fid, fsplit, true); e.best.Update(loss_chg, fid, fsplit, true);
} }
} }
@ -308,8 +324,10 @@ class ColMaker: public IUpdater {
tmp = sum; tmp = sum;
ThreadEntry &e = stemp[nthread-1][nid]; ThreadEntry &e = stemp[nthread-1][nid];
c.SetSubstract(snode[nid].stats, tmp); c.SetSubstract(snode[nid].stats, tmp);
if (c.sum_hess >= param.min_child_weight && tmp.sum_hess >= param.min_child_weight) { if (c.sum_hess >= param.min_child_weight &&
bst_float loss_chg = static_cast<bst_float>(tmp.CalcGain(param) + c.CalcGain(param) - snode[nid].root_gain); tmp.sum_hess >= param.min_child_weight) {
bst_float loss_chg = static_cast<bst_float>(tmp.CalcGain(param) +
c.CalcGain(param) - snode[nid].root_gain);
e.best.Update(loss_chg, fid, e.last_fvalue + rt_eps, true); e.best.Update(loss_chg, fid, e.last_fvalue + rt_eps, true);
} }
} }
@ -338,16 +356,22 @@ class ColMaker: public IUpdater {
if (std::abs(fvalue - e.first_fvalue) > rt_2eps) { if (std::abs(fvalue - e.first_fvalue) > rt_2eps) {
if (need_forward) { if (need_forward) {
c.SetSubstract(snode[nid].stats, e.stats); c.SetSubstract(snode[nid].stats, e.stats);
if (c.sum_hess >= param.min_child_weight && e.stats.sum_hess >= param.min_child_weight) { if (c.sum_hess >= param.min_child_weight &&
bst_float loss_chg = static_cast<bst_float>(e.stats.CalcGain(param) + c.CalcGain(param) - snode[nid].root_gain); e.stats.sum_hess >= param.min_child_weight) {
bst_float loss_chg = static_cast<bst_float>(e.stats.CalcGain(param) +
c.CalcGain(param) -
snode[nid].root_gain);
e.best.Update(loss_chg, fid, (fvalue + e.first_fvalue) * 0.5f, false); e.best.Update(loss_chg, fid, (fvalue + e.first_fvalue) * 0.5f, false);
} }
} }
if (need_backward) { if (need_backward) {
cright.SetSubstract(e.stats_extra, e.stats); cright.SetSubstract(e.stats_extra, e.stats);
c.SetSubstract(snode[nid].stats, cright); c.SetSubstract(snode[nid].stats, cright);
if (c.sum_hess >= param.min_child_weight && cright.sum_hess >= param.min_child_weight) { if (c.sum_hess >= param.min_child_weight &&
bst_float loss_chg = static_cast<bst_float>(cright.CalcGain(param) + c.CalcGain(param) - snode[nid].root_gain); cright.sum_hess >= param.min_child_weight) {
bst_float loss_chg = static_cast<bst_float>(cright.CalcGain(param) +
c.CalcGain(param) -
snode[nid].root_gain);
e.best.Update(loss_chg, fid, (fvalue + e.first_fvalue) * 0.5f, true); e.best.Update(loss_chg, fid, (fvalue + e.first_fvalue) * 0.5f, true);
} }
} }
@ -361,7 +385,7 @@ class ColMaker: public IUpdater {
// update enumeration solution // update enumeration solution
inline void UpdateEnumeration(int nid, bst_gpair gstats, inline void UpdateEnumeration(int nid, bst_gpair gstats,
float fvalue, int d_step, bst_uint fid, float fvalue, int d_step, bst_uint fid,
TStats &c, std::vector<ThreadEntry> &temp) { TStats &c, std::vector<ThreadEntry> &temp) { // NOLINT(*)
// get the statistics of nid // get the statistics of nid
ThreadEntry &e = temp[nid]; ThreadEntry &e = temp[nid];
// test if first hit, this is fine, because we set 0 during init // test if first hit, this is fine, because we set 0 during init
@ -370,10 +394,12 @@ class ColMaker: public IUpdater {
e.last_fvalue = fvalue; e.last_fvalue = fvalue;
} else { } else {
// try to find a split // try to find a split
if (std::abs(fvalue - e.last_fvalue) > rt_2eps && e.stats.sum_hess >= param.min_child_weight) { if (std::abs(fvalue - e.last_fvalue) > rt_2eps &&
e.stats.sum_hess >= param.min_child_weight) {
c.SetSubstract(snode[nid].stats, e.stats); c.SetSubstract(snode[nid].stats, e.stats);
if (c.sum_hess >= param.min_child_weight) { if (c.sum_hess >= param.min_child_weight) {
bst_float loss_chg = static_cast<bst_float>(e.stats.CalcGain(param) + c.CalcGain(param) - snode[nid].root_gain); bst_float loss_chg = static_cast<bst_float>(e.stats.CalcGain(param) +
c.CalcGain(param) - snode[nid].root_gain);
e.best.Update(loss_chg, fid, (fvalue + e.last_fvalue) * 0.5f, d_step == -1); e.best.Update(loss_chg, fid, (fvalue + e.last_fvalue) * 0.5f, d_step == -1);
} }
} }
@ -388,7 +414,7 @@ class ColMaker: public IUpdater {
int d_step, int d_step,
bst_uint fid, bst_uint fid,
const std::vector<bst_gpair> &gpair, const std::vector<bst_gpair> &gpair,
std::vector<ThreadEntry> &temp) { std::vector<ThreadEntry> &temp) { // NOLINT(*)
const std::vector<int> &qexpand = qexpand_; const std::vector<int> &qexpand = qexpand_;
// clear all the temp statistics // clear all the temp statistics
for (size_t j = 0; j < qexpand.size(); ++j) { for (size_t j = 0; j < qexpand.size(); ++j) {
@ -443,7 +469,8 @@ class ColMaker: public IUpdater {
ThreadEntry &e = temp[nid]; ThreadEntry &e = temp[nid];
c.SetSubstract(snode[nid].stats, e.stats); c.SetSubstract(snode[nid].stats, e.stats);
if (e.stats.sum_hess >= param.min_child_weight && c.sum_hess >= param.min_child_weight) { if (e.stats.sum_hess >= param.min_child_weight && c.sum_hess >= param.min_child_weight) {
bst_float loss_chg = static_cast<bst_float>(e.stats.CalcGain(param) + c.CalcGain(param) - snode[nid].root_gain); bst_float loss_chg = static_cast<bst_float>(e.stats.CalcGain(param) +
c.CalcGain(param) - snode[nid].root_gain);
const float gap = std::abs(e.last_fvalue) + rt_eps; const float gap = std::abs(e.last_fvalue) + rt_eps;
const float delta = d_step == +1 ? gap: -gap; const float delta = d_step == +1 ? gap: -gap;
e.best.Update(loss_chg, fid, e.last_fvalue + delta, d_step == -1); e.best.Update(loss_chg, fid, e.last_fvalue + delta, d_step == -1);
@ -458,7 +485,7 @@ class ColMaker: public IUpdater {
bst_uint fid, bst_uint fid,
const std::vector<bst_gpair> &gpair, const std::vector<bst_gpair> &gpair,
const BoosterInfo &info, const BoosterInfo &info,
std::vector<ThreadEntry> &temp) { std::vector<ThreadEntry> &temp) { // NOLINT(*)
// use cacheline aware optimization // use cacheline aware optimization
if (TStats::kSimpleStats != 0 && param.cache_opt != 0) { if (TStats::kSimpleStats != 0 && param.cache_opt != 0) {
EnumerateSplitCacheOpt(begin, end, d_step, fid, gpair, temp); EnumerateSplitCacheOpt(begin, end, d_step, fid, gpair, temp);
@ -485,10 +512,12 @@ class ColMaker: public IUpdater {
e.last_fvalue = fvalue; e.last_fvalue = fvalue;
} else { } else {
// try to find a split // try to find a split
if (std::abs(fvalue - e.last_fvalue) > rt_2eps && e.stats.sum_hess >= param.min_child_weight) { if (std::abs(fvalue - e.last_fvalue) > rt_2eps &&
e.stats.sum_hess >= param.min_child_weight) {
c.SetSubstract(snode[nid].stats, e.stats); c.SetSubstract(snode[nid].stats, e.stats);
if (c.sum_hess >= param.min_child_weight) { if (c.sum_hess >= param.min_child_weight) {
bst_float loss_chg = static_cast<bst_float>(e.stats.CalcGain(param) + c.CalcGain(param) - snode[nid].root_gain); bst_float loss_chg = static_cast<bst_float>(e.stats.CalcGain(param) +
c.CalcGain(param) - snode[nid].root_gain);
e.best.Update(loss_chg, fid, (fvalue + e.last_fvalue) * 0.5f, d_step == -1); e.best.Update(loss_chg, fid, (fvalue + e.last_fvalue) * 0.5f, d_step == -1);
} }
} }
@ -503,7 +532,8 @@ class ColMaker: public IUpdater {
ThreadEntry &e = temp[nid]; ThreadEntry &e = temp[nid];
c.SetSubstract(snode[nid].stats, e.stats); c.SetSubstract(snode[nid].stats, e.stats);
if (e.stats.sum_hess >= param.min_child_weight && c.sum_hess >= param.min_child_weight) { if (e.stats.sum_hess >= param.min_child_weight && c.sum_hess >= param.min_child_weight) {
bst_float loss_chg = static_cast<bst_float>(e.stats.CalcGain(param) + c.CalcGain(param) - snode[nid].root_gain); bst_float loss_chg = static_cast<bst_float>(e.stats.CalcGain(param) +
c.CalcGain(param) - snode[nid].root_gain);
const float gap = std::abs(e.last_fvalue) + rt_eps; const float gap = std::abs(e.last_fvalue) + rt_eps;
const float delta = d_step == +1 ? gap: -gap; const float delta = d_step == +1 ? gap: -gap;
e.best.Update(loss_chg, fid, e.last_fvalue + delta, d_step == -1); e.best.Update(loss_chg, fid, e.last_fvalue + delta, d_step == -1);
@ -585,7 +615,8 @@ class ColMaker: public IUpdater {
} }
} }
// reset position of each data points after split is created in the tree // reset position of each data points after split is created in the tree
inline void ResetPosition(const std::vector<int> &qexpand, IFMatrix *p_fmat, const RegTree &tree) { inline void ResetPosition(const std::vector<int> &qexpand,
IFMatrix *p_fmat, const RegTree &tree) {
// set the positions in the nondefault // set the positions in the nondefault
this->SetNonDefaultPosition(qexpand, p_fmat, tree); this->SetNonDefaultPosition(qexpand, p_fmat, tree);
// set rest of instances to default position // set rest of instances to default position

View File

@ -1,11 +1,15 @@
#ifndef XGBOOST_TREE_UPDATER_DISTCOL_INL_HPP_
#define XGBOOST_TREE_UPDATER_DISTCOL_INL_HPP_
/*! /*!
* Copyright 2014 by Contributors
* \file updater_distcol-inl.hpp * \file updater_distcol-inl.hpp
* \brief beta distributed version that takes a sub-column * \brief beta distributed version that takes a sub-column
* and construct a tree * and construct a tree
* \author Tianqi Chen * \author Tianqi Chen
*/ */
#ifndef XGBOOST_TREE_UPDATER_DISTCOL_INL_HPP_
#define XGBOOST_TREE_UPDATER_DISTCOL_INL_HPP_
#include <vector>
#include <algorithm>
#include "../sync/sync.h" #include "../sync/sync.h"
#include "../utils/bitmap.h" #include "../utils/bitmap.h"
#include "../utils/io.h" #include "../utils/io.h"
@ -40,10 +44,11 @@ class DistColMaker : public ColMaker<TStats> {
virtual const int* GetLeafPosition(void) const { virtual const int* GetLeafPosition(void) const {
return builder.GetLeafPosition(); return builder.GetLeafPosition();
} }
private: private:
struct Builder : public ColMaker<TStats>::Builder { struct Builder : public ColMaker<TStats>::Builder {
public: public:
Builder(const TrainParam &param) explicit Builder(const TrainParam &param)
: ColMaker<TStats>::Builder(param) { : ColMaker<TStats>::Builder(param) {
} }
inline void UpdatePosition(IFMatrix *p_fmat, const RegTree &tree) { inline void UpdatePosition(IFMatrix *p_fmat, const RegTree &tree) {
@ -63,6 +68,7 @@ class DistColMaker : public ColMaker<TStats> {
virtual const int* GetLeafPosition(void) const { virtual const int* GetLeafPosition(void) const {
return BeginPtr(this->position); return BeginPtr(this->position);
} }
protected: protected:
virtual void SetNonDefaultPosition(const std::vector<int> &qexpand, virtual void SetNonDefaultPosition(const std::vector<int> &qexpand,
IFMatrix *p_fmat, const RegTree &tree) { IFMatrix *p_fmat, const RegTree &tree) {
@ -142,7 +148,7 @@ class DistColMaker : public ColMaker<TStats> {
} }
vec.push_back(this->snode[nid].best); vec.push_back(this->snode[nid].best);
} }
// TODO, lazy version // TODO(tqchen) lazy version
// communicate best solution // communicate best solution
reducer.Allreduce(BeginPtr(vec), vec.size()); reducer.Allreduce(BeginPtr(vec), vec.size());
// assign solution back // assign solution back
@ -166,4 +172,4 @@ class DistColMaker : public ColMaker<TStats> {
}; };
} // namespace tree } // namespace tree
} // namespace xgboost } // namespace xgboost
#endif #endif // XGBOOST_TREE_UPDATER_DISTCOL_INL_HPP_

View File

@ -1,10 +1,12 @@
#ifndef XGBOOST_TREE_UPDATER_HISTMAKER_INL_HPP_
#define XGBOOST_TREE_UPDATER_HISTMAKER_INL_HPP_
/*! /*!
* Copyright 2014 by Contributors
* \file updater_histmaker-inl.hpp * \file updater_histmaker-inl.hpp
* \brief use histogram counting to construct a tree * \brief use histogram counting to construct a tree
* \author Tianqi Chen * \author Tianqi Chen
*/ */
#ifndef XGBOOST_TREE_UPDATER_HISTMAKER_INL_HPP_
#define XGBOOST_TREE_UPDATER_HISTMAKER_INL_HPP_
#include <vector> #include <vector>
#include <algorithm> #include <algorithm>
#include "../sync/sync.h" #include "../sync/sync.h"
@ -171,6 +173,7 @@ class HistMaker: public BaseMaker {
const BoosterInfo &info, const BoosterInfo &info,
const std::vector <bst_uint> &fset, const std::vector <bst_uint> &fset,
const RegTree &tree) = 0; const RegTree &tree) = 0;
private: private:
inline void EnumerateSplit(const HistUnit &hist, inline void EnumerateSplit(const HistUnit &hist,
const TStats &node_sum, const TStats &node_sum,
@ -187,7 +190,7 @@ class HistMaker: public BaseMaker {
c.SetSubstract(node_sum, s); c.SetSubstract(node_sum, s);
if (c.sum_hess >= param.min_child_weight) { if (c.sum_hess >= param.min_child_weight) {
double loss_chg = s.CalcGain(param) + c.CalcGain(param) - root_gain; double loss_chg = s.CalcGain(param) + c.CalcGain(param) - root_gain;
if (best->Update((float)loss_chg, fid, hist.cut[i], false)) { if (best->Update(static_cast<float>(loss_chg), fid, hist.cut[i], false)) {
*left_sum = s; *left_sum = s;
} }
} }
@ -200,7 +203,7 @@ class HistMaker: public BaseMaker {
c.SetSubstract(node_sum, s); c.SetSubstract(node_sum, s);
if (c.sum_hess >= param.min_child_weight) { if (c.sum_hess >= param.min_child_weight) {
double loss_chg = s.CalcGain(param) + c.CalcGain(param) - root_gain; double loss_chg = s.CalcGain(param) + c.CalcGain(param) - root_gain;
if (best->Update((float)loss_chg, fid, hist.cut[i-1], true)) { if (best->Update(static_cast<float>(loss_chg), fid, hist.cut[i-1], true)) {
*left_sum = c; *left_sum = c;
} }
} }
@ -394,7 +397,8 @@ class CQHistMaker: public HistMaker<TStats> {
#if __cplusplus >= 201103L #if __cplusplus >= 201103L
auto lazy_get_summary = [&]() auto lazy_get_summary = [&]()
#endif #endif
{// get smmary {
// get smmary
thread_sketch.resize(this->get_nthread()); thread_sketch.resize(this->get_nthread());
// number of rows in // number of rows in
const size_t nrows = p_fmat->buffered_rowset().size(); const size_t nrows = p_fmat->buffered_rowset().size();

View File

@ -1,10 +1,12 @@
#ifndef XGBOOST_TREE_UPDATER_PRUNE_INL_HPP_
#define XGBOOST_TREE_UPDATER_PRUNE_INL_HPP_
/*! /*!
* Copyright 2014 by Contributors
* \file updater_prune-inl.hpp * \file updater_prune-inl.hpp
* \brief prune a tree given the statistics * \brief prune a tree given the statistics
* \author Tianqi Chen * \author Tianqi Chen
*/ */
#ifndef XGBOOST_TREE_UPDATER_PRUNE_INL_HPP_
#define XGBOOST_TREE_UPDATER_PRUNE_INL_HPP_
#include <vector> #include <vector>
#include "./param.h" #include "./param.h"
#include "./updater.h" #include "./updater.h"
@ -37,9 +39,10 @@ class TreePruner: public IUpdater {
param.learning_rate = lr; param.learning_rate = lr;
syncher.Update(gpair, p_fmat, info, trees); syncher.Update(gpair, p_fmat, info, trees);
} }
private: private:
// try to prune off current leaf // try to prune off current leaf
inline int TryPruneLeaf(RegTree &tree, int nid, int depth, int npruned) { inline int TryPruneLeaf(RegTree &tree, int nid, int depth, int npruned) { // NOLINT(*)
if (tree[nid].is_root()) return npruned; if (tree[nid].is_root()) return npruned;
int pid = tree[nid].parent(); int pid = tree[nid].parent();
RegTree::NodeStat &s = tree.stat(pid); RegTree::NodeStat &s = tree.stat(pid);
@ -54,7 +57,7 @@ class TreePruner: public IUpdater {
} }
} }
/*! \brief do prunning of a tree */ /*! \brief do prunning of a tree */
inline void DoPrune(RegTree &tree) { inline void DoPrune(RegTree &tree) { // NOLINT(*)
int npruned = 0; int npruned = 0;
// initialize auxiliary statistics // initialize auxiliary statistics
for (int nid = 0; nid < tree.param.num_nodes; ++nid) { for (int nid = 0; nid < tree.param.num_nodes; ++nid) {

View File

@ -1,10 +1,12 @@
#ifndef XGBOOST_TREE_UPDATER_REFRESH_INL_HPP_
#define XGBOOST_TREE_UPDATER_REFRESH_INL_HPP_
/*! /*!
* Copyright 2014 by Contributors
* \file updater_refresh-inl.hpp * \file updater_refresh-inl.hpp
* \brief refresh the statistics and leaf value on the tree on the dataset * \brief refresh the statistics and leaf value on the tree on the dataset
* \author Tianqi Chen * \author Tianqi Chen
*/ */
#ifndef XGBOOST_TREE_UPDATER_REFRESH_INL_HPP_
#define XGBOOST_TREE_UPDATER_REFRESH_INL_HPP_
#include <vector> #include <vector>
#include <limits> #include <limits>
#include "../sync/sync.h" #include "../sync/sync.h"

View File

@ -1,11 +1,13 @@
#ifndef XGBOOST_TREE_UPDATER_SKMAKER_INL_HPP_
#define XGBOOST_TREE_UPDATER_SKMAKER_INL_HPP_
/*! /*!
* Copyright 2014 by Contributors
* \file updater_skmaker-inl.hpp * \file updater_skmaker-inl.hpp
* \brief use approximation sketch to construct a tree, * \brief use approximation sketch to construct a tree,
a refresh is needed to make the statistics exactly correct a refresh is needed to make the statistics exactly correct
* \author Tianqi Chen * \author Tianqi Chen
*/ */
#ifndef XGBOOST_TREE_UPDATER_SKMAKER_INL_HPP_
#define XGBOOST_TREE_UPDATER_SKMAKER_INL_HPP_
#include <vector> #include <vector>
#include <algorithm> #include <algorithm>
#include "../sync/sync.h" #include "../sync/sync.h"
@ -81,7 +83,7 @@ class SketchMaker: public BaseMaker {
double neg_grad; double neg_grad;
/*! \brief sum of hessian statistics */ /*! \brief sum of hessian statistics */
double sum_hess; double sum_hess;
explicit SKStats(void) {} SKStats(void) {}
// constructor // constructor
explicit SKStats(const TrainParam &param) { explicit SKStats(const TrainParam &param) {
this->Clear(); this->Clear();
@ -123,7 +125,7 @@ class SketchMaker: public BaseMaker {
sum_hess += b.sum_hess; sum_hess += b.sum_hess;
} }
/*! \brief same as add, reduce is used in All Reduce */ /*! \brief same as add, reduce is used in All Reduce */
inline static void Reduce(SKStats &a, const SKStats &b) { inline static void Reduce(SKStats &a, const SKStats &b) { // NOLINT(*)
a.Add(b); a.Add(b);
} }
/*! \brief set leaf vector value based on statistics */ /*! \brief set leaf vector value based on statistics */
@ -217,7 +219,9 @@ class SketchMaker: public BaseMaker {
for (size_t i = 0; i < this->qexpand.size(); ++i) { for (size_t i = 0; i < this->qexpand.size(); ++i) {
const int nid = this->qexpand[i]; const int nid = this->qexpand[i];
for (int k = 0; k < 3; ++k) { for (int k = 0; k < 3; ++k) {
sbuilder[3 * nid + k].sketch->Push(c[0].fvalue, static_cast<bst_float>(sbuilder[3 * nid + k].sum_total)); sbuilder[3 * nid + k].sketch->Push(c[0].fvalue,
static_cast<bst_float>(
sbuilder[3 * nid + k].sum_total));
} }
} }
return; return;
@ -361,7 +365,8 @@ class SketchMaker: public BaseMaker {
best->Update(static_cast<bst_float>(loss_chg), fid, fsplits[i], true); best->Update(static_cast<bst_float>(loss_chg), fid, fsplits[i], true);
} }
} }
{// all including {
// all including
SKStats s = feat_sum, c; SKStats s = feat_sum, c;
c.SetSubstract(node_sum, s); c.SetSubstract(node_sum, s);
if (s.sum_hess >= param.min_child_weight && if (s.sum_hess >= param.min_child_weight &&
@ -389,6 +394,6 @@ class SketchMaker: public BaseMaker {
// per node, per feature sketch // per node, per feature sketch
std::vector< utils::WXQuantileSketch<bst_float, bst_float> > sketchs; std::vector< utils::WXQuantileSketch<bst_float, bst_float> > sketchs;
}; };
} // tree } // namespace tree
} // xgboost } // namespace xgboost
#endif #endif // XGBOOST_TREE_UPDATER_SKMAKER_INL_HPP_

View File

@ -1,11 +1,14 @@
#ifndef XGBOOST_TREE_UPDATER_SYNC_INL_HPP_
#define XGBOOST_TREE_UPDATER_SYNC_INL_HPP_
/*! /*!
* Copyright 2014 by Contributors
* \file updater_sync-inl.hpp * \file updater_sync-inl.hpp
* \brief synchronize the tree in all distributed nodes * \brief synchronize the tree in all distributed nodes
* \author Tianqi Chen * \author Tianqi Chen
*/ */
#ifndef XGBOOST_TREE_UPDATER_SYNC_INL_HPP_
#define XGBOOST_TREE_UPDATER_SYNC_INL_HPP_
#include <vector> #include <vector>
#include <string>
#include <limits> #include <limits>
#include "../sync/sync.h" #include "../sync/sync.h"
#include "./updater.h" #include "./updater.h"

View File

@ -1,10 +1,12 @@
#ifndef XGBOOST_UTILS_CONFIG_H_
#define XGBOOST_UTILS_CONFIG_H_
/*! /*!
* Copyright 2014 by Contributors
* \file config.h * \file config.h
* \brief helper class to load in configures from file * \brief helper class to load in configures from file
* \author Tianqi Chen * \author Tianqi Chen
*/ */
#ifndef XGBOOST_UTILS_CONFIG_H_
#define XGBOOST_UTILS_CONFIG_H_
#include <cstdio> #include <cstdio>
#include <cstring> #include <cstring>
#include <string> #include <string>

View File

@ -1,6 +1,5 @@
#ifndef XGBOOST_UTILS_GROUP_DATA_H_
#define XGBOOST_UTILS_GROUP_DATA_H_
/*! /*!
* Copyright 2014 by Contributors
* \file group_data.h * \file group_data.h
* \brief this file defines utils to group data by integer keys * \brief this file defines utils to group data by integer keys
* Input: given input sequence (key,value), (k1,v1), (k2,v2) * Input: given input sequence (key,value), (k1,v1), (k2,v2)
@ -12,6 +11,11 @@
* The major algorithm is a two pass linear scan algorithm that requires two pass scan over the data * The major algorithm is a two pass linear scan algorithm that requires two pass scan over the data
* \author Tianqi Chen * \author Tianqi Chen
*/ */
#ifndef XGBOOST_UTILS_GROUP_DATA_H_
#define XGBOOST_UTILS_GROUP_DATA_H_
#include <vector>
namespace xgboost { namespace xgboost {
namespace utils { namespace utils {
/*! /*!

View File

@ -1,16 +1,19 @@
#ifndef XGBOOST_UTILS_IO_H /*!
#define XGBOOST_UTILS_IO_H * Copyright 2014 by Contributors
* \file io.h
* \brief general stream interface for serialization, I/O
* \author Tianqi Chen
*/
#ifndef XGBOOST_UTILS_IO_H_
#define XGBOOST_UTILS_IO_H_
#include <cstdio> #include <cstdio>
#include <vector> #include <vector>
#include <string> #include <string>
#include <cstring> #include <cstring>
#include "./utils.h" #include "./utils.h"
#include "../sync/sync.h" #include "../sync/sync.h"
/*!
* \file io.h
* \brief general stream interface for serialization, I/O
* \author Tianqi Chen
*/
namespace xgboost { namespace xgboost {
namespace utils { namespace utils {
// reuse the definitions of streams // reuse the definitions of streams
@ -23,7 +26,7 @@ typedef rabit::utils::MemoryBufferStream MemoryBufferStream;
class FileStream : public ISeekStream { class FileStream : public ISeekStream {
public: public:
explicit FileStream(std::FILE *fp) : fp(fp) {} explicit FileStream(std::FILE *fp) : fp(fp) {}
explicit FileStream(void) { FileStream(void) {
this->fp = NULL; this->fp = NULL;
} }
virtual size_t Read(void *ptr, size_t size) { virtual size_t Read(void *ptr, size_t size) {
@ -33,7 +36,7 @@ class FileStream : public ISeekStream {
std::fwrite(ptr, size, 1, fp); std::fwrite(ptr, size, 1, fp);
} }
virtual void Seek(size_t pos) { virtual void Seek(size_t pos) {
std::fseek(fp, static_cast<long>(pos), SEEK_SET); std::fseek(fp, static_cast<long>(pos), SEEK_SET); // NOLINT(*)
} }
virtual size_t Tell(void) { virtual size_t Tell(void) {
return std::ftell(fp); return std::ftell(fp);
@ -52,6 +55,5 @@ class FileStream : public ISeekStream {
}; };
} // namespace utils } // namespace utils
} // namespace xgboost } // namespace xgboost
#include "./base64-inl.h" #include "./base64-inl.h"
#endif #endif // XGBOOST_UTILS_IO_H_

View File

@ -1,16 +1,17 @@
#ifndef XGBOOST_UTILS_THREAD_H
#define XGBOOST_UTILS_THREAD_H
/*! /*!
* Copyright by Contributors
* \file thread.h * \file thread.h
* \brief this header include the minimum necessary resource for multi-threading * \brief this header include the minimum necessary resource
* for multi-threading that can be compiled in windows, linux, mac
* \author Tianqi Chen * \author Tianqi Chen
* Acknowledgement: this file is adapted from SVDFeature project, by same author.
* The MAC support part of this code is provided by Artemy Kolchinsky
*/ */
#ifndef XGBOOST_UTILS_THREAD_H_ // NOLINT(*)
#define XGBOOST_UTILS_THREAD_H_ // NOLINT(*)
#ifdef _MSC_VER #ifdef _MSC_VER
#include "utils.h"
#include <windows.h> #include <windows.h>
#include <process.h> #include <process.h>
#include "../xgboost/utils.h"
namespace xgboost { namespace xgboost {
namespace utils { namespace utils {
/*! \brief simple semaphore used for synchronization */ /*! \brief simple semaphore used for synchronization */
@ -18,27 +19,78 @@ class Semaphore {
public : public :
inline void Init(int init_val) { inline void Init(int init_val) {
sem = CreateSemaphore(NULL, init_val, 10, NULL); sem = CreateSemaphore(NULL, init_val, 10, NULL);
utils::Assert(sem != NULL, "create Semaphore error"); utils::Check(sem != NULL, "create Semaphore error");
} }
inline void Destroy(void) { inline void Destroy(void) {
CloseHandle(sem); CloseHandle(sem);
} }
inline void Wait(void) { inline void Wait(void) {
utils::Assert(WaitForSingleObject(sem, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject error"); utils::Check(WaitForSingleObject(sem, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject error");
} }
inline void Post(void) { inline void Post(void) {
utils::Assert(ReleaseSemaphore(sem, 1, NULL) != 0, "ReleaseSemaphore error"); utils::Check(ReleaseSemaphore(sem, 1, NULL) != 0, "ReleaseSemaphore error");
} }
private: private:
HANDLE sem; HANDLE sem;
}; };
/*! \brief mutex under windows */
class Mutex {
public:
inline void Init(void) {
utils::Check(InitializeCriticalSectionAndSpinCount(&mutex, 0x00000400) != 0,
"Mutex::Init fail");
}
inline void Lock(void) {
EnterCriticalSection(&mutex);
}
inline void Unlock(void) {
LeaveCriticalSection(&mutex);
}
inline void Destroy(void) {
DeleteCriticalSection(&mutex);
}
private:
friend class ConditionVariable;
CRITICAL_SECTION mutex;
};
// conditional variable that uses pthread
class ConditionVariable {
public:
// initialize conditional variable
inline void Init(void) {
InitializeConditionVariable(&cond);
}
// destroy the thread
inline void Destroy(void) {
// DeleteConditionVariable(&cond);
}
// wait on the conditional variable
inline void Wait(Mutex *mutex) {
utils::Check(SleepConditionVariableCS(&cond, &(mutex->mutex), INFINITE) != 0,
"ConditionVariable:Wait fail");
}
inline void Broadcast(void) {
WakeAllConditionVariable(&cond);
}
inline void Signal(void) {
WakeConditionVariable(&cond);
}
private:
CONDITION_VARIABLE cond;
};
/*! \brief simple thread that wraps windows thread */ /*! \brief simple thread that wraps windows thread */
class Thread { class Thread {
private: private:
HANDLE thread_handle; HANDLE thread_handle;
unsigned thread_id; unsigned thread_id;
public: public:
inline void Start(unsigned int __stdcall entry(void*), void *param) { inline void Start(unsigned int __stdcall entry(void*p), void *param) {
thread_handle = (HANDLE)_beginthreadex(NULL, 0, entry, param, 0, &thread_id); thread_handle = (HANDLE)_beginthreadex(NULL, 0, entry, param, 0, &thread_id);
} }
inline int Join(void) { inline int Join(void) {
@ -55,18 +107,19 @@ inline void ThreadExit(void *status) {
} // namespace xgboost } // namespace xgboost
#else #else
// thread interface using g++ // thread interface using g++
extern "C" {
#include <semaphore.h> #include <semaphore.h>
#include <pthread.h> #include <pthread.h>
} #include <errno.h>
namespace xgboost { namespace xgboost {
namespace utils { namespace utils {
/*!\brief semaphore class */ /*!\brief semaphore class */
class Semaphore { class Semaphore {
#ifdef __APPLE__ #ifdef __APPLE__
private: private:
sem_t* semPtr; sem_t* semPtr;
char sema_name[20]; char sema_name[20];
private: private:
inline void GenRandomString(char *s, const int len) { inline void GenRandomString(char *s, const int len) {
static const char alphanum[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; static const char alphanum[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
@ -75,6 +128,7 @@ class Semaphore {
} }
s[len] = 0; s[len] = 0;
} }
public: public:
inline void Init(int init_val) { inline void Init(int init_val) {
sema_name[0] = '/'; sema_name[0] = '/';
@ -86,7 +140,7 @@ class Semaphore {
perror("sem_open"); perror("sem_open");
exit(1); exit(1);
} }
utils::Assert(semPtr != NULL, "create Semaphore error"); utils::Check(semPtr != NULL, "create Semaphore error");
} }
inline void Destroy(void) { inline void Destroy(void) {
if (sem_close(semPtr) == -1) { if (sem_close(semPtr) == -1) {
@ -105,51 +159,91 @@ class Semaphore {
sem_post(semPtr); sem_post(semPtr);
} }
#else #else
private: private:
sem_t sem; sem_t sem;
public: public:
inline void Init(int init_val) { inline void Init(int init_val) {
sem_init(&sem, 0, init_val); if (sem_init(&sem, 0, init_val) != 0) {
utils::Error("Semaphore.Init:%s", strerror(errno));
}
} }
inline void Destroy(void) { inline void Destroy(void) {
sem_destroy(&sem); if (sem_destroy(&sem) != 0) {
utils::Error("Semaphore.Destroy:%s", strerror(errno));
}
} }
inline void Wait(void) { inline void Wait(void) {
sem_wait(&sem); if (sem_wait(&sem) != 0) {
utils::Error("Semaphore.Wait:%s", strerror(errno));
}
} }
inline void Post(void) { inline void Post(void) {
sem_post(&sem); if (sem_post(&sem) != 0) {
utils::Error("Semaphore.Post:%s", strerror(errno));
}
} }
#endif #endif
}; };
// helper for c thread // mutex that works with pthread
// used to strictly call c++ function from pthread class Mutex {
struct ThreadContext { public:
void *(*entry)(void*); inline void Init(void) {
void *param; pthread_mutex_init(&mutex, NULL);
}
inline void Lock(void) {
pthread_mutex_lock(&mutex);
}
inline void Unlock(void) {
pthread_mutex_unlock(&mutex);
}
inline void Destroy(void) {
pthread_mutex_destroy(&mutex);
}
private:
friend class ConditionVariable;
pthread_mutex_t mutex;
}; };
extern "C" {
inline void *RunThreadContext(void *ctx_) { // conditional variable that uses pthread
ThreadContext *ctx = reinterpret_cast<ThreadContext*>(ctx_); class ConditionVariable {
void *ret = (*ctx->entry)(ctx->param); public:
delete ctx; // initialize conditional variable
return ret; inline void Init(void) {
pthread_cond_init(&cond, NULL);
} }
// destroy the thread
inline void Destroy(void) {
pthread_cond_destroy(&cond);
} }
// wait on the conditional variable
inline void Wait(Mutex *mutex) {
pthread_cond_wait(&cond, &(mutex->mutex));
}
inline void Broadcast(void) {
pthread_cond_broadcast(&cond);
}
inline void Signal(void) {
pthread_cond_signal(&cond);
}
private:
pthread_cond_t cond;
};
/*!\brief simple thread class */ /*!\brief simple thread class */
class Thread { class Thread {
private: private:
pthread_t thread; pthread_t thread;
public : public :
inline void Start(void *entry(void*), void *param) { inline void Start(void * entry(void*), void *param) { // NOLINT(*)
pthread_attr_t attr; pthread_attr_t attr;
pthread_attr_init(&attr); pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
ThreadContext *ctx = new ThreadContext(); pthread_create(&thread, &attr, entry, param);
ctx->entry = entry; ctx->param = param;
pthread_create(&thread, &attr, RunThreadContext, ctx);
} }
inline int Join(void) { inline int Join(void) {
void *status; void *status;
@ -159,9 +253,8 @@ class Thread {
inline void ThreadExit(void *status) { inline void ThreadExit(void *status) {
pthread_exit(status); pthread_exit(status);
} }
} // namespace utils } // namespace utils
} // namespace xgboost } // namespace xgboost
#define XGBOOST_THREAD_PREFIX void * #define XGBOOST_THREAD_PREFIX void *
#endif #endif // Linux
#endif #endif // XGBOOST_UTILS_THREAD_H_ NOLINT(*)