| 282 | common::Monitor monitor_; |
| 283 | |
| 284 | [[nodiscard]] bool ReadCache() { |
| 285 | if (!cache_info_->written) { |
| 286 | return false; |
| 287 | } |
| 288 | auto n_batches = this->cache_info_->Size(); |
| 289 | if (ring_->empty()) { |
| 290 | ring_->resize(n_batches); |
| 291 | } |
| 292 | |
| 293 | std::int32_t n_prefetches = |
| 294 | std::min(this->workers_.NumWorkers(), this->param_.n_prefetch_batches); |
| 295 | n_prefetches = std::max(n_prefetches, 1); |
| 296 | std::int32_t n_prefetch_batches = std::min(static_cast<bst_idx_t>(n_prefetches), n_batches); |
| 297 | CHECK_GT(n_prefetch_batches, 0); |
| 298 | CHECK_LE(n_prefetch_batches, this->param_.n_prefetch_batches); |
| 299 | std::size_t fetch_it = this->count_; |
| 300 | |
| 301 | exce_.Rethrow(); |
| 302 | // Clear out the existing page before loading new ones. This helps reduce memory usage |
| 303 | // when page is not loaded with mmap. The destruction policy handles any necessary |
| 304 | // synchronizations (e.g., CUDA stream sync for Ellpack pages). |
| 305 | this->DestroyPage(&page_); |
| 306 | |
| 307 | for (std::int32_t i = 0; i < n_prefetch_batches; ++i, ++fetch_it) { |
| 308 | bool restart = fetch_it == n_batches; |
| 309 | fetch_it %= n_batches; // ring |
| 310 | if (ring_->at(fetch_it).valid()) { |
| 311 | continue; |
| 312 | } |
| 313 | auto const* self = this; // make sure it's const |
| 314 | CHECK_LT(fetch_it, cache_info_->offset.size()); |
| 315 | // Make sure the new iteration starts with a copy to avoid spilling configuration. |
| 316 | if (restart) { |
| 317 | this->param_.prefetch_copy = true; |
| 318 | } |
| 319 | auto p = this->param_; |
| 320 | ring_->at(fetch_it) = this->workers_.Submit([fetch_it, self, p, this] { |
| 321 | auto page = std::make_shared<S>(); |
| 322 | this->exce_.Run([&] { |
| 323 | std::unique_ptr<typename FormatStreamPolicy::FormatT> fmt{self->CreatePageFormat(p)}; |
| 324 | auto name = self->cache_info_->ShardName(); |
| 325 | auto [offset, length] = self->cache_info_->View(fetch_it); |
| 326 | std::unique_ptr<typename FormatStreamPolicy::ReaderT> fi{ |
| 327 | self->CreateReader(name, offset, length)}; |
| 328 | CHECK(fmt->Read(page.get(), fi.get())); |
| 329 | }); |
| 330 | return page; |
| 331 | }); |
| 332 | this->fetch_cnt_++; |
| 333 | } |
| 334 | |
| 335 | CHECK_EQ(std::count_if(ring_->cbegin(), ring_->cend(), [](auto const& f) { return f.valid(); }), |
| 336 | n_prefetch_batches) |
| 337 | << "Sparse DMatrix assumes forward iteration."; |
| 338 | |
| 339 | monitor_.Start("Wait-" + std::to_string(count_)); |
| 340 | CHECK((*ring_)[count_].valid()); |
| 341 | page_ = (*ring_)[count_].get(); |
no test coverage detected