| 85 | } |
| 86 | |
| 87 | void GetDataShape(Context const* ctx, DMatrixProxy* proxy, |
| 88 | DataIterProxy<DataIterResetCallback, XGDMatrixCallbackNext>* iter, float missing, |
| 89 | ExternalDataInfo* p_info) { |
| 90 | auto& info = *p_info; |
| 91 | |
| 92 | auto const is_valid = data::IsValidFunctor{missing}; |
| 93 | auto nnz_cnt = [&]() { |
| 94 | return DispatchAny(proxy, [&](auto const& value) { |
| 95 | bst_idx_t n_threads = ctx->Threads(); |
| 96 | bst_idx_t n_features = info.column_sizes.size(); |
| 97 | linalg::Tensor<bst_idx_t, 2> column_sizes_tloc({n_threads, n_features}, DeviceOrd::CPU()); |
| 98 | column_sizes_tloc.Data()->Fill(0ul); |
| 99 | auto view = column_sizes_tloc.HostView(); |
| 100 | common::ParallelFor(value.Size(), n_threads, common::Sched::Static(256), [&](auto i) { |
| 101 | auto const& line = value.GetLine(i); |
| 102 | for (bst_idx_t j = 0; j < line.Size(); ++j) { |
| 103 | data::COOTuple const& elem = line.GetElement(j); |
| 104 | if (is_valid(elem)) { |
| 105 | view(omp_get_thread_num(), elem.column_idx)++; |
| 106 | } |
| 107 | } |
| 108 | }); |
| 109 | auto ptr = column_sizes_tloc.Data()->HostPointer(); |
| 110 | auto result = std::accumulate(ptr, ptr + column_sizes_tloc.Size(), static_cast<bst_idx_t>(0)); |
| 111 | for (bst_idx_t tidx = 0; tidx < n_threads; ++tidx) { |
| 112 | for (bst_idx_t fidx = 0; fidx < n_features; ++fidx) { |
| 113 | info.column_sizes[fidx] += view(tidx, fidx); |
| 114 | } |
| 115 | } |
| 116 | return result; |
| 117 | }); |
| 118 | }; |
| 119 | |
| 120 | /** |
| 121 | * CPU impl needs an additional loop for accumulating the column size. |
| 122 | */ |
| 123 | do { |
| 124 | // We use do while here as the first batch is fetched in ctor |
| 125 | if (info.n_features == 0) { |
| 126 | info.n_features = BatchColumns(proxy); |
| 127 | collective::SafeColl(collective::Allreduce(ctx, &info.n_features, collective::Op::kMax)); |
| 128 | info.column_sizes.clear(); |
| 129 | info.column_sizes.resize(info.n_features, 0); |
| 130 | p_info->cats = |
| 131 | std::make_shared<CatContainer>(cpu_impl::BatchCats(proxy), BatchCatsIsRef(proxy)); |
| 132 | } else { |
| 133 | CHECK_EQ(info.n_features, BatchColumns(proxy)) << "Inconsistent number of columns."; |
| 134 | auto cats = cpu_impl::BatchCats(proxy); |
| 135 | CHECK_EQ(cats.n_total_cats, p_info->cats->NumCatsTotal()) << error::InconsistentCategories(); |
| 136 | } |
| 137 | bst_idx_t batch_size = BatchSamples(proxy); |
| 138 | info.batch_nnz.push_back(nnz_cnt()); |
| 139 | info.base_rowids.push_back(batch_size); |
| 140 | info.nnz += info.batch_nnz.back(); |
| 141 | info.accumulated_rows += batch_size; |
| 142 | info.n_batches++; |
| 143 | } while (iter->Next()); |
| 144 | iter->Reset(); |
no test coverage detected