Fix race condition in CPU shap. (#7050)

This commit is contained in:
Jiaming Yuan
2021-06-21 10:03:15 +08:00
committed by GitHub
parent 29f8fd6fee
commit bbfffb444d
5 changed files with 68 additions and 64 deletions

View File

@@ -213,6 +213,32 @@ void PredictBatchByBlockOfRowsKernel(
});
}
float FillNodeMeanValues(RegTree const *tree, bst_node_t nidx, std::vector<float> *mean_values) {
bst_float result;
auto &node = (*tree)[nidx];
auto &node_mean_values = *mean_values;
if (node.IsLeaf()) {
result = node.LeafValue();
} else {
result = FillNodeMeanValues(tree, node.LeftChild(), mean_values) *
tree->Stat(node.LeftChild()).sum_hess;
result += FillNodeMeanValues(tree, node.RightChild(), mean_values) *
tree->Stat(node.RightChild()).sum_hess;
result /= tree->Stat(nidx).sum_hess;
}
node_mean_values[nidx] = result;
return result;
}
void FillNodeMeanValues(RegTree const* tree, std::vector<float>* mean_values) {
size_t num_nodes = tree->param.num_nodes;
if (mean_values->size() == num_nodes) {
return;
}
mean_values->resize(num_nodes);
FillNodeMeanValues(tree, 0, mean_values);
}
class CPUPredictor : public Predictor {
protected:
// init thread buffers
@@ -396,9 +422,10 @@ class CPUPredictor : public Predictor {
}
}
void PredictContribution(DMatrix* p_fmat, HostDeviceVector<float>* out_contribs,
const gbm::GBTreeModel& model, uint32_t ntree_limit,
std::vector<bst_float>* tree_weights,
void PredictContribution(DMatrix *p_fmat,
HostDeviceVector<float> *out_contribs,
const gbm::GBTreeModel &model, uint32_t ntree_limit,
std::vector<bst_float> const *tree_weights,
bool approximate, int condition,
unsigned condition_feature) const override {
const int nthread = omp_get_max_threads();
@@ -421,8 +448,9 @@ class CPUPredictor : public Predictor {
// allocated one
std::fill(contribs.begin(), contribs.end(), 0);
// initialize tree node mean values
std::vector<std::vector<float>> mean_values(ntree_limit);
common::ParallelFor(bst_omp_uint(ntree_limit), [&](bst_omp_uint i) {
model.trees[i]->FillNodeMeanValues();
FillNodeMeanValues(model.trees[i].get(), &(mean_values[i]));
});
const std::vector<bst_float>& base_margin = info.base_margin_.HostVector();
// start collecting the contributions
@@ -443,19 +471,23 @@ class CPUPredictor : public Predictor {
feats.Fill(page[i]);
// calculate contributions
for (unsigned j = 0; j < ntree_limit; ++j) {
auto *tree_mean_values = &mean_values.at(j);
std::fill(this_tree_contribs.begin(), this_tree_contribs.end(), 0);
if (model.tree_info[j] != gid) {
continue;
}
if (!approximate) {
model.trees[j]->CalculateContributions(feats, &this_tree_contribs[0],
condition, condition_feature);
model.trees[j]->CalculateContributions(
feats, tree_mean_values, &this_tree_contribs[0], condition,
condition_feature);
} else {
model.trees[j]->CalculateContributionsApprox(feats, &this_tree_contribs[0]);
model.trees[j]->CalculateContributionsApprox(
feats, tree_mean_values, &this_tree_contribs[0]);
}
for (size_t ci = 0 ; ci < ncolumns ; ++ci) {
p_contribs[ci] += this_tree_contribs[ci] *
(tree_weights == nullptr ? 1 : (*tree_weights)[j]);
for (size_t ci = 0; ci < ncolumns; ++ci) {
p_contribs[ci] +=
this_tree_contribs[ci] *
(tree_weights == nullptr ? 1 : (*tree_weights)[j]);
}
}
feats.Drop(page[i]);
@@ -470,10 +502,11 @@ class CPUPredictor : public Predictor {
}
}
void PredictInteractionContributions(DMatrix* p_fmat, HostDeviceVector<bst_float>* out_contribs,
const gbm::GBTreeModel& model, unsigned ntree_limit,
std::vector<bst_float>* tree_weights,
bool approximate) const override {
void PredictInteractionContributions(
DMatrix *p_fmat, HostDeviceVector<bst_float> *out_contribs,
const gbm::GBTreeModel &model, unsigned ntree_limit,
std::vector<bst_float> const *tree_weights,
bool approximate) const override {
const MetaInfo& info = p_fmat->Info();
const int ngroup = model.learner_model_param->num_output_group;
size_t const ncolumns = model.learner_model_param->num_feature;

View File

@@ -696,7 +696,7 @@ class GPUPredictor : public xgboost::Predictor {
void PredictContribution(DMatrix* p_fmat,
HostDeviceVector<bst_float>* out_contribs,
const gbm::GBTreeModel& model, unsigned tree_end,
std::vector<bst_float>*,
std::vector<bst_float> const*,
bool approximate, int,
unsigned) const override {
if (approximate) {
@@ -746,7 +746,7 @@ class GPUPredictor : public xgboost::Predictor {
HostDeviceVector<bst_float>* out_contribs,
const gbm::GBTreeModel& model,
unsigned tree_end,
std::vector<bst_float>*,
std::vector<bst_float> const*,
bool approximate) const override {
if (approximate) {
LOG(FATAL) << "[Internal error]: " << __func__