121 const PadCrsAction action,
122 const RowPtr& row_ptr_beg,
123 const RowPtr& row_ptr_end,
124 Indices& indices_wdv,
126 const Padding& padding,
128 const bool verbose) {
130 using Kokkos::view_alloc;
131 using Kokkos::WithoutInitializing;
133 std::unique_ptr<std::string> prefix;
137 std::ostringstream os;
138 os <<
"Proc " << my_rank <<
": Tpetra::...::pad_crs_arrays: ";
139 prefix = std::unique_ptr<std::string>(
new std::string(os.str()));
140 os <<
"Start" << endl;
141 std::cerr << os.str();
143 Kokkos::HostSpace hostSpace;
146 std::ostringstream os;
147 os << *prefix <<
"On input: ";
149 Kokkos::create_mirror_view(hostSpace, row_ptr_beg);
151 Kokkos::deep_copy(row_ptr_beg_h, row_ptr_beg);
156 Kokkos::create_mirror_view(hostSpace, row_ptr_end);
158 Kokkos::deep_copy(row_ptr_end_h, row_ptr_end);
161 os <<
", indices.extent(0): " << indices_wdv.extent(0)
162 <<
", values.extent(0): " << values_wdv.extent(0)
166 std::cerr << os.str();
169 if (row_ptr_beg.size() == 0) {
171 std::ostringstream os;
172 os << *prefix <<
"Done; local matrix has no rows" << endl;
173 std::cerr << os.str();
178 const size_t lclNumRows(row_ptr_beg.size() - 1);
179 RowPtr newAllocPerRow =
180 make_uninitialized_view<RowPtr>(
"newAllocPerRow", lclNumRows,
181 verbose, prefix.get());
183 std::ostringstream os;
184 os << *prefix <<
"Fill newAllocPerRow & compute increase" << endl;
185 std::cerr << os.str();
191 auto row_ptr_end_h = create_mirror_view(
192 hostSpace, row_ptr_end, verbose, prefix.get());
194 Kokkos::deep_copy(exec_space_instance, row_ptr_end_h, row_ptr_end);
195 auto row_ptr_beg_h = create_mirror_view(
196 hostSpace, row_ptr_beg, verbose, prefix.get());
198 Kokkos::deep_copy(exec_space_instance, row_ptr_beg_h, row_ptr_beg);
206 exec_space_instance.fence();
208 auto newAllocPerRow_h = create_mirror_view(
209 hostSpace, newAllocPerRow, verbose, prefix.get());
210 using host_range_type = Kokkos::RangePolicy<
211 Kokkos::DefaultHostExecutionSpace,
size_t>;
212 Kokkos::parallel_reduce(
213 "Tpetra::CrsGraph: Compute new allocation size per row",
214 host_range_type(0, lclNumRows),
215 [&](
const size_t lclRowInd,
size_t& lclIncrease) {
216 const size_t start = row_ptr_beg_h[lclRowInd];
217 const size_t end = row_ptr_beg_h[lclRowInd + 1];
218 TEUCHOS_ASSERT(end >= start);
219 const size_t oldAllocSize = end - start;
220 const size_t oldNumEnt = row_ptr_end_h[lclRowInd] - start;
221 TEUCHOS_ASSERT(oldNumEnt <= oldAllocSize);
228 auto result = padding.get_result(lclRowInd);
229 const size_t newNumEnt = oldNumEnt + result.numInSrcNotInTgt;
230 if (newNumEnt > oldAllocSize) {
231 lclIncrease += (newNumEnt - oldAllocSize);
232 newAllocPerRow_h[lclRowInd] = newNumEnt;
234 newAllocPerRow_h[lclRowInd] = oldAllocSize;
240 std::ostringstream os;
241 os << *prefix <<
"increase: " << increase <<
", ";
245 std::cerr << os.str();
252 Kokkos::deep_copy(
execution_space(), newAllocPerRow, newAllocPerRow_h);
255 using inds_value_type =
256 typename Indices::t_dev::non_const_value_type;
257 using vals_value_type =
typename Values::t_dev::non_const_value_type;
260 auto indices_old = indices_wdv.getDeviceView(Access::ReadOnly);
261 const size_t newIndsSize = size_t(indices_old.size()) + increase;
262 auto indices_new = make_uninitialized_view<typename Indices::t_dev>(
263 "Tpetra::CrsGraph column indices", newIndsSize, verbose,
266 typename Values::t_dev values_new;
267 auto values_old = values_wdv.getDeviceView(Access::ReadOnly);
268 if (action == PadCrsAction::INDICES_AND_VALUES) {
269 const size_t newValsSize = newIndsSize;
272 values_new = make_initialized_view<typename Values::t_dev>(
273 "Tpetra::CrsMatrix values", newValsSize, verbose, prefix.get());
277 std::ostringstream os;
278 os << *prefix <<
"Repack" << endl;
279 std::cerr << os.str();
282 using range_type = Kokkos::RangePolicy<execution_space, size_t>;
283 Kokkos::parallel_scan(
284 "Tpetra::CrsGraph or CrsMatrix repack",
285 range_type(
size_t(0),
size_t(lclNumRows + 1)),
286 KOKKOS_LAMBDA(
const size_t lclRow,
size_t& newRowBeg,
287 const bool finalPass) {
291 const size_t row_beg = row_ptr_beg[lclRow];
292 const size_t row_end =
293 lclRow < lclNumRows ? row_ptr_end[lclRow] : row_beg;
294 const size_t numEnt = row_end - row_beg;
295 const size_t newRowAllocSize =
296 lclRow < lclNumRows ? newAllocPerRow[lclRow] : size_t(0);
298 if (lclRow < lclNumRows) {
299 const Kokkos::pair<size_t, size_t> oldRange(
300 row_beg, row_beg + numEnt);
301 const Kokkos::pair<size_t, size_t> newRange(
302 newRowBeg, newRowBeg + numEnt);
303 auto oldColInds = Kokkos::subview(indices_old, oldRange);
304 auto newColInds = Kokkos::subview(indices_new, newRange);
307 memcpy(newColInds.data(), oldColInds.data(),
308 numEnt *
sizeof(inds_value_type));
309 if (action == PadCrsAction::INDICES_AND_VALUES) {
311 Kokkos::subview(values_old, oldRange);
312 auto newVals = Kokkos::subview(values_new, newRange);
313 memcpy((
void*)newVals.data(), oldVals.data(),
314 numEnt *
sizeof(vals_value_type));
318 row_ptr_beg[lclRow] = newRowBeg;
319 if (lclRow < lclNumRows) {
320 row_ptr_end[lclRow] = newRowBeg + numEnt;
323 newRowBeg += newRowAllocSize;
327 std::ostringstream os;
331 Kokkos::create_mirror_view(hostSpace, row_ptr_beg);
333 Kokkos::deep_copy(row_ptr_beg_h, row_ptr_beg);
340 Kokkos::create_mirror_view(hostSpace, row_ptr_end);
342 Kokkos::deep_copy(row_ptr_end_h, row_ptr_end);
347 std::cout << os.str();
350 indices_wdv = Indices(indices_new);
351 values_wdv = Values(values_new);
355 auto indices_h = indices_wdv.getHostView(Access::ReadOnly);
356 auto values_h = values_wdv.getHostView(Access::ReadOnly);
357 std::ostringstream os;
368 std::ostringstream os;
369 os << *prefix <<
"Done" << endl;
370 std::cerr << os.str();
378 typename Pointers::value_type
const row,
379 Pointers
const& row_ptrs,
380 InOutIndices& cur_indices,
381 size_t& num_assigned,
382 InIndices
const& new_indices,
384 std::function<
void(
size_t const,
size_t const,
size_t const)> cb) {
385 if (new_indices.size() == 0) {
389 if (cur_indices.size() == 0) {
391 return Teuchos::OrdinalTraits<size_t>::invalid();
394 using offset_type =
typename std::decay<
decltype(row_ptrs[0])>::type;
395 using ordinal_type =
typename std::decay<
decltype(cur_indices[0])>::type;
397 const offset_type start = row_ptrs[row];
398 offset_type end = start +
static_cast<offset_type
>(num_assigned);
399 const size_t num_avail = (row_ptrs[row + 1] < end) ?
size_t(0) : row_ptrs[row + 1] - end;
400 const size_t num_new_indices =
static_cast<size_t>(new_indices.size());
401 size_t num_inserted = 0;
403 size_t numIndicesLookup = num_assigned + num_new_indices;
406 const size_t useLookUpTableThreshold = 400;
408 if (numIndicesLookup <= useLookUpTableThreshold || num_new_indices == 1) {
411 for (
size_t k = 0; k < num_new_indices; ++k) {
412 const ordinal_type idx = std::forward<IndexMap>(map)(new_indices[k]);
413 offset_type row_offset = start;
414 for (; row_offset < end; ++row_offset) {
415 if (idx == cur_indices[row_offset]) {
420 if (row_offset == end) {
421 if (num_inserted >= num_avail) {
422 return Teuchos::OrdinalTraits<size_t>::invalid();
425 cur_indices[end++] = idx;
429 cb(k, start, row_offset - start);
434 std::unordered_map<ordinal_type, offset_type> idxLookup(numIndicesLookup);
437 for (
size_t k = 0; k < num_assigned; k++) {
438 idxLookup[cur_indices[start + k]] = start + k;
442 for (
size_t k = 0; k < num_new_indices; k++) {
443 const ordinal_type idx = std::forward<IndexMap>(map)(new_indices[k]);
444 offset_type row_offset;
446 auto it = idxLookup.find(idx);
447 if (it == idxLookup.end()) {
448 if (num_inserted >= num_avail) {
449 return Teuchos::OrdinalTraits<size_t>::invalid();
453 cur_indices[end++] = idx;
454 idxLookup[idx] = row_offset;
458 row_offset = it->second;
461 cb(k, start, row_offset - start);
465 num_assigned += num_inserted;