| 520 | class OverflowTest : public ::testing::TestWithParam<std::tuple<bool, bool>> { |
| 521 | public: |
| 522 | std::vector<GradientPairPrecise> TestOverflow(bool limit, bool is_distributed, |
| 523 | bool is_col_split) { |
| 524 | bst_bin_t constexpr kBins = 256; |
| 525 | Context ctx; |
| 526 | HistMakerTrainParam hist_param; |
| 527 | if (limit) { |
| 528 | hist_param.Init(Args{{"max_cached_hist_node", "1"}}); |
| 529 | } |
| 530 | |
| 531 | std::shared_ptr<DMatrix> Xy = |
| 532 | is_col_split ? RandomDataGenerator{8192, 16, 0.5}.GenerateDMatrix(true) |
| 533 | : RandomDataGenerator{8192, 16, 0.5}.Bins(kBins).GenerateQuantileDMatrix(true); |
| 534 | if (is_col_split) { |
| 535 | Xy = |
| 536 | std::shared_ptr<DMatrix>{Xy->SliceCol(collective::GetWorldSize(), collective::GetRank())}; |
| 537 | } |
| 538 | |
| 539 | double sparse_thresh{TrainParam::DftSparseThreshold()}; |
| 540 | auto batch = BatchParam{kBins, sparse_thresh}; |
| 541 | bst_bin_t n_total_bins{0}; |
| 542 | float split_cond{0}; |
| 543 | for (auto const &page : Xy->GetBatches<GHistIndexMatrix>(&ctx, batch)) { |
| 544 | n_total_bins = page.cut.TotalBins(); |
| 545 | // use a cut point in the second column for split |
| 546 | split_cond = page.cut.Values()[kBins + kBins / 2]; |
| 547 | } |
| 548 | |
| 549 | RegTree tree; |
| 550 | MultiHistogramBuilder hist_builder; |
| 551 | CHECK_EQ(Xy->Info().IsColumnSplit(), is_col_split); |
| 552 | |
| 553 | hist_builder.Reset(&ctx, n_total_bins, tree.NumTargets(), batch, is_distributed, |
| 554 | Xy->Info().IsColumnSplit(), &hist_param); |
| 555 | |
| 556 | std::vector<CommonRowPartitioner> partitioners; |
| 557 | partitioners.emplace_back(&ctx, Xy->Info().num_row_, /*base_rowid=*/0, |
| 558 | Xy->Info().IsColumnSplit()); |
| 559 | |
| 560 | auto gpair = GenerateRandomGradients(Xy->Info().num_row_, 0.0, 1.0); |
| 561 | |
| 562 | CPUExpandEntry best; |
| 563 | hist_builder.BuildRootHist(Xy.get(), tree.HostScView(), partitioners, |
| 564 | linalg::MakeTensorView(&ctx, gpair.ConstHostSpan(), gpair.Size(), 1), |
| 565 | best, batch); |
| 566 | |
| 567 | best.split.Update(1.0f, 1, split_cond, false, false, GradStats{1.0, 1.0}, GradStats{1.0, 1.0}); |
| 568 | tree.ExpandNode(best.nid, best.split.SplitIndex(), best.split.split_value, false, |
| 569 | /*base_weight=*/2.0f, |
| 570 | /*left_leaf_weight=*/1.0f, /*right_leaf_weight=*/1.0f, best.GetLossChange(), |
| 571 | /*sum_hess=*/2.0f, best.split.left_sum.GetHess(), |
| 572 | best.split.right_sum.GetHess()); |
| 573 | |
| 574 | std::vector<CPUExpandEntry> valid_candidates{best}; |
| 575 | for (auto const &page : Xy->GetBatches<GHistIndexMatrix>(&ctx, batch)) { |
| 576 | partitioners.front().UpdatePosition(&ctx, page, valid_candidates, tree.HostScView()); |
| 577 | } |
| 578 | CHECK_NE(partitioners.front()[tree.LeftChild(best.nid)].Size(), 0); |
| 579 | CHECK_NE(partitioners.front()[tree.RightChild(best.nid)].Size(), 0); |
no test coverage detected