116 const PadCrsAction action,
117 const RowPtr& row_ptr_beg,
118 const RowPtr& row_ptr_end,
119 Indices& indices_wdv,
121 const Padding& padding,
123 const bool verbose) {
125 using Kokkos::view_alloc;
126 using Kokkos::WithoutInitializing;
128 std::unique_ptr<std::string> prefix;
132 std::ostringstream os;
133 os <<
"Proc " << my_rank <<
": Tpetra::...::pad_crs_arrays: ";
134 prefix = std::unique_ptr<std::string>(
new std::string(os.str()));
135 os <<
"Start" << endl;
136 std::cerr << os.str();
138 Kokkos::HostSpace hostSpace;
141 std::ostringstream os;
142 os << *prefix <<
"On input: ";
144 Kokkos::create_mirror_view(hostSpace, row_ptr_beg);
146 Kokkos::deep_copy(row_ptr_beg_h, row_ptr_beg);
151 Kokkos::create_mirror_view(hostSpace, row_ptr_end);
153 Kokkos::deep_copy(row_ptr_end_h, row_ptr_end);
156 os <<
", indices.extent(0): " << indices_wdv.extent(0)
157 <<
", values.extent(0): " << values_wdv.extent(0)
161 std::cerr << os.str();
164 if (row_ptr_beg.size() == 0) {
166 std::ostringstream os;
167 os << *prefix <<
"Done; local matrix has no rows" << endl;
168 std::cerr << os.str();
173 const size_t lclNumRows(row_ptr_beg.size() - 1);
174 RowPtr newAllocPerRow =
175 make_uninitialized_view<RowPtr>(
"newAllocPerRow", lclNumRows,
176 verbose, prefix.get());
178 std::ostringstream os;
179 os << *prefix <<
"Fill newAllocPerRow & compute increase" << endl;
180 std::cerr << os.str();
186 auto row_ptr_end_h = create_mirror_view(
187 hostSpace, row_ptr_end, verbose, prefix.get());
189 Kokkos::deep_copy(exec_space_instance, row_ptr_end_h, row_ptr_end);
190 auto row_ptr_beg_h = create_mirror_view(
191 hostSpace, row_ptr_beg, verbose, prefix.get());
193 Kokkos::deep_copy(exec_space_instance, row_ptr_beg_h, row_ptr_beg);
201 exec_space_instance.fence();
203 auto newAllocPerRow_h = create_mirror_view(
204 hostSpace, newAllocPerRow, verbose, prefix.get());
205 using host_range_type = Kokkos::RangePolicy<
206 Kokkos::DefaultHostExecutionSpace,
size_t>;
207 Kokkos::parallel_reduce(
208 "Tpetra::CrsGraph: Compute new allocation size per row",
209 host_range_type(0, lclNumRows),
210 [&](
const size_t lclRowInd,
size_t& lclIncrease) {
211 const size_t start = row_ptr_beg_h[lclRowInd];
212 const size_t end = row_ptr_beg_h[lclRowInd + 1];
213 TEUCHOS_ASSERT(end >= start);
214 const size_t oldAllocSize = end - start;
215 const size_t oldNumEnt = row_ptr_end_h[lclRowInd] - start;
216 TEUCHOS_ASSERT(oldNumEnt <= oldAllocSize);
223 auto result = padding.get_result(lclRowInd);
224 const size_t newNumEnt = oldNumEnt + result.numInSrcNotInTgt;
225 if (newNumEnt > oldAllocSize) {
226 lclIncrease += (newNumEnt - oldAllocSize);
227 newAllocPerRow_h[lclRowInd] = newNumEnt;
229 newAllocPerRow_h[lclRowInd] = oldAllocSize;
235 std::ostringstream os;
236 os << *prefix <<
"increase: " << increase <<
", ";
240 std::cerr << os.str();
247 Kokkos::deep_copy(
execution_space(), newAllocPerRow, newAllocPerRow_h);
250 using inds_value_type =
251 typename Indices::t_dev::non_const_value_type;
252 using vals_value_type =
typename Values::t_dev::non_const_value_type;
255 auto indices_old = indices_wdv.getDeviceView(Access::ReadOnly);
256 const size_t newIndsSize = size_t(indices_old.size()) + increase;
257 auto indices_new = make_uninitialized_view<typename Indices::t_dev>(
258 "Tpetra::CrsGraph column indices", newIndsSize, verbose,
261 typename Values::t_dev values_new;
262 auto values_old = values_wdv.getDeviceView(Access::ReadOnly);
263 if (action == PadCrsAction::INDICES_AND_VALUES) {
264 const size_t newValsSize = newIndsSize;
267 values_new = make_initialized_view<typename Values::t_dev>(
268 "Tpetra::CrsMatrix values", newValsSize, verbose, prefix.get());
272 std::ostringstream os;
273 os << *prefix <<
"Repack" << endl;
274 std::cerr << os.str();
277 using range_type = Kokkos::RangePolicy<execution_space, size_t>;
278 Kokkos::parallel_scan(
279 "Tpetra::CrsGraph or CrsMatrix repack",
280 range_type(
size_t(0),
size_t(lclNumRows + 1)),
281 KOKKOS_LAMBDA(
const size_t lclRow,
size_t& newRowBeg,
282 const bool finalPass) {
286 const size_t row_beg = row_ptr_beg[lclRow];
287 const size_t row_end =
288 lclRow < lclNumRows ? row_ptr_end[lclRow] : row_beg;
289 const size_t numEnt = row_end - row_beg;
290 const size_t newRowAllocSize =
291 lclRow < lclNumRows ? newAllocPerRow[lclRow] : size_t(0);
293 if (lclRow < lclNumRows) {
294 const Kokkos::pair<size_t, size_t> oldRange(
295 row_beg, row_beg + numEnt);
296 const Kokkos::pair<size_t, size_t> newRange(
297 newRowBeg, newRowBeg + numEnt);
298 auto oldColInds = Kokkos::subview(indices_old, oldRange);
299 auto newColInds = Kokkos::subview(indices_new, newRange);
302 memcpy(newColInds.data(), oldColInds.data(),
303 numEnt *
sizeof(inds_value_type));
304 if (action == PadCrsAction::INDICES_AND_VALUES) {
306 Kokkos::subview(values_old, oldRange);
307 auto newVals = Kokkos::subview(values_new, newRange);
308 memcpy((
void*)newVals.data(), oldVals.data(),
309 numEnt *
sizeof(vals_value_type));
313 row_ptr_beg[lclRow] = newRowBeg;
314 if (lclRow < lclNumRows) {
315 row_ptr_end[lclRow] = newRowBeg + numEnt;
318 newRowBeg += newRowAllocSize;
322 std::ostringstream os;
326 Kokkos::create_mirror_view(hostSpace, row_ptr_beg);
328 Kokkos::deep_copy(row_ptr_beg_h, row_ptr_beg);
335 Kokkos::create_mirror_view(hostSpace, row_ptr_end);
337 Kokkos::deep_copy(row_ptr_end_h, row_ptr_end);
342 std::cout << os.str();
345 indices_wdv = Indices(indices_new);
346 values_wdv = Values(values_new);
350 auto indices_h = indices_wdv.getHostView(Access::ReadOnly);
351 auto values_h = values_wdv.getHostView(Access::ReadOnly);
352 std::ostringstream os;
363 std::ostringstream os;
364 os << *prefix <<
"Done" << endl;
365 std::cerr << os.str();
373 typename Pointers::value_type
const row,
374 Pointers
const& row_ptrs,
375 InOutIndices& cur_indices,
376 size_t& num_assigned,
377 InIndices
const& new_indices,
379 std::function<
void(
size_t const,
size_t const,
size_t const)> cb) {
380 if (new_indices.size() == 0) {
384 if (cur_indices.size() == 0) {
386 return Teuchos::OrdinalTraits<size_t>::invalid();
389 using offset_type =
typename std::decay<
decltype(row_ptrs[0])>::type;
390 using ordinal_type =
typename std::decay<
decltype(cur_indices[0])>::type;
392 const offset_type start = row_ptrs[row];
393 offset_type end = start +
static_cast<offset_type
>(num_assigned);
394 const size_t num_avail = (row_ptrs[row + 1] < end) ?
size_t(0) : row_ptrs[row + 1] - end;
395 const size_t num_new_indices =
static_cast<size_t>(new_indices.size());
396 size_t num_inserted = 0;
398 size_t numIndicesLookup = num_assigned + num_new_indices;
401 const size_t useLookUpTableThreshold = 400;
403 if (numIndicesLookup <= useLookUpTableThreshold || num_new_indices == 1) {
406 for (
size_t k = 0; k < num_new_indices; ++k) {
407 const ordinal_type idx = std::forward<IndexMap>(map)(new_indices[k]);
408 offset_type row_offset = start;
409 for (; row_offset < end; ++row_offset) {
410 if (idx == cur_indices[row_offset]) {
415 if (row_offset == end) {
416 if (num_inserted >= num_avail) {
417 return Teuchos::OrdinalTraits<size_t>::invalid();
420 cur_indices[end++] = idx;
424 cb(k, start, row_offset - start);
429 std::unordered_map<ordinal_type, offset_type> idxLookup(numIndicesLookup);
432 for (
size_t k = 0; k < num_assigned; k++) {
433 idxLookup[cur_indices[start + k]] = start + k;
437 for (
size_t k = 0; k < num_new_indices; k++) {
438 const ordinal_type idx = std::forward<IndexMap>(map)(new_indices[k]);
439 offset_type row_offset;
441 auto it = idxLookup.find(idx);
442 if (it == idxLookup.end()) {
443 if (num_inserted >= num_avail) {
444 return Teuchos::OrdinalTraits<size_t>::invalid();
448 cur_indices[end++] = idx;
449 idxLookup[idx] = row_offset;
453 row_offset = it->second;
456 cb(k, start, row_offset - start);
460 num_assigned += num_inserted;