Tpetra parallel linear algebra Version of the Day
Loading...
Searching...
No Matches
Tpetra_Details_unpackCrsMatrixAndCombine_def.hpp
Go to the documentation of this file.
1// @HEADER
2// *****************************************************************************
3// Tpetra: Templated Linear Algebra Services Package
4//
5// Copyright 2008 NTESS and the Tpetra contributors.
6// SPDX-License-Identifier: BSD-3-Clause
7// *****************************************************************************
8// @HEADER
9
10#ifndef TPETRA_DETAILS_UNPACKCRSMATRIXANDCOMBINE_DEF_HPP
11#define TPETRA_DETAILS_UNPACKCRSMATRIXANDCOMBINE_DEF_HPP
12
13#include <memory>
14#include <string>
15#include "TpetraCore_config.h"
16#include "Kokkos_Core.hpp"
17#include "Teuchos_Array.hpp"
18#include "Teuchos_ArrayView.hpp"
19#include "Teuchos_OrdinalTraits.hpp"
20#include "Teuchos_TimeMonitor.hpp"
28#include "Tpetra_Details_DefaultTypes.hpp"
30
51
52namespace Tpetra {
53
54//
55// Users must never rely on anything in the Details namespace.
56//
57namespace Details {
58
59namespace UnpackAndCombineCrsMatrixImpl {
60
70template <class ST, class LO, class GO>
71KOKKOS_FUNCTION int
75 const char imports[],
76 const size_t offset,
77 const size_t /* num_bytes */,
78 const size_t num_ent,
79 const size_t bytes_per_value) {
80 if (num_ent == 0) {
81 // Empty rows always take zero bytes, to ensure sparsity.
82 return 0;
83 }
84 bool unpack_pids = pids_out.size() > 0;
85
86 const size_t num_ent_beg = offset;
87 const size_t num_ent_len = PackTraits<LO>::packValueCount(LO(0));
88
89 const size_t gids_beg = num_ent_beg + num_ent_len;
90 const size_t gids_len =
92
93 const size_t pids_beg = gids_beg + gids_len;
94 const size_t pids_len = unpack_pids ? size_t(num_ent * PackTraits<int>::packValueCount(int(0))) : size_t(0);
95
96 const size_t vals_beg = gids_beg + gids_len + pids_len;
97 const size_t vals_len = num_ent * bytes_per_value;
98
99 const char* const num_ent_in = imports + num_ent_beg;
100 const char* const gids_in = imports + gids_beg;
101 const char* const pids_in = unpack_pids ? imports + pids_beg : nullptr;
102 const char* const vals_in = imports + vals_beg;
103
104 size_t num_bytes_out = 0;
105 LO num_ent_out;
107 if (static_cast<size_t>(num_ent_out) != num_ent) {
108 return 20; // error code
109 }
110
111 {
112 Kokkos::pair<int, size_t> p;
114 if (p.first != 0) {
115 return 21; // error code
116 }
117 num_bytes_out += p.second;
118
119 if (unpack_pids) {
121 if (p.first != 0) {
122 return 22; // error code
123 }
124 num_bytes_out += p.second;
125 }
126
128 if (p.first != 0) {
129 return 23; // error code
130 }
131 num_bytes_out += p.second;
132 }
133
136 return 24; // error code
137 }
138 return 0; // no errors
139} // unpackRow
140
151template <class LocalMatrix, class LocalMap, class BufferDeviceType>
154 typedef LocalMap local_map_type;
155
156 typedef typename local_matrix_type::value_type ST;
157 typedef typename local_map_type::local_ordinal_type LO;
159 typedef typename local_map_type::device_type DT;
160 typedef typename DT::execution_space XS;
161
162 typedef Kokkos::View<const size_t*, BufferDeviceType>
163 num_packets_per_lid_type;
164 typedef Kokkos::View<const size_t*, DT> offsets_type;
165 typedef Kokkos::View<const char*, BufferDeviceType> input_buffer_type;
166 typedef Kokkos::View<const LO*, BufferDeviceType> import_lids_type;
167
168 typedef Kokkos::View<int, DT> error_type;
169 using member_type = typename Kokkos::TeamPolicy<XS>::member_type;
170
171 static_assert(std::is_same<LO, typename local_matrix_type::ordinal_type>::value,
172 "LocalMap::local_ordinal_type and "
173 "LocalMatrix::ordinal_type must be the same.");
174
175 local_matrix_type local_matrix;
176 local_map_type local_col_map;
177 input_buffer_type imports;
178 num_packets_per_lid_type num_packets_per_lid;
179 import_lids_type import_lids;
180 Kokkos::View<const LO* [2], DT> batch_info;
181 offsets_type offsets;
182 Tpetra::CombineMode combine_mode;
183 size_t batch_size;
184 size_t bytes_per_value;
185 bool atomic;
186 error_type error_code;
187
191 const input_buffer_type& imports_in,
192 const num_packets_per_lid_type& num_packets_per_lid_in,
193 const import_lids_type& import_lids_in,
194 const Kokkos::View<const LO* [2], DT>& batch_info_in,
195 const offsets_type& offsets_in,
197 const size_t batch_size_in,
198 const size_t bytes_per_value_in,
199 const bool atomic_in)
200 : local_matrix(local_matrix_in)
201 , local_col_map(local_col_map_in)
202 , imports(imports_in)
203 , num_packets_per_lid(num_packets_per_lid_in)
204 , import_lids(import_lids_in)
205 , batch_info(batch_info_in)
206 , offsets(offsets_in)
207 , combine_mode(combine_mode_in)
208 , batch_size(batch_size_in)
209 , bytes_per_value(bytes_per_value_in)
210 , atomic(atomic_in)
211 , error_code("error") {}
212
214 void operator()(member_type team_member) const {
215 using Kokkos::MemoryUnmanaged;
216 using Kokkos::subview;
217 using Kokkos::View;
218
219 const LO batch = team_member.league_rank();
220 const LO lid_no = batch_info(batch, 0);
221 const LO batch_no = batch_info(batch, 1);
222
223 const size_t num_bytes = num_packets_per_lid(lid_no);
224
225 // Only unpack data if there is a nonzero number of bytes.
226 if (num_bytes == 0)
227 return;
228
229 // there is actually something in the row
230 const LO import_lid = import_lids(lid_no);
231 const size_t buf_size = imports.size();
232 const size_t offset = offsets(lid_no);
233
234 // Get the number of entries to expect in the received data for this row.
235 LO num_ent_LO = 0;
236 const char* const in_buf = imports.data() + offset;
238 const size_t num_entries_in_row = static_cast<size_t>(num_ent_LO);
239
240 // Count the number of bytes expected to unpack
241 size_t expected_num_bytes = 0;
242 {
246 }
247
249 Kokkos::printf(
250 "*** Error: UnpackCrsMatrixAndCombineFunctor: "
251 "At row %d, the expected number of bytes (%d) != number of unpacked bytes (%d)\n",
252 (int)lid_no, (int)expected_num_bytes, (int)num_bytes);
253
254 Kokkos::atomic_compare_exchange(error_code.data(), 0, 21);
255 return;
256 }
257
258 if (offset > buf_size || offset + num_bytes > buf_size) {
259 Kokkos::printf(
260 "*** Error: UnpackCrsMatrixAndCombineFunctor: "
261 "At row %d, the offset (%d) > buffer size (%d)\n",
262 (int)lid_no, (int)offset, (int)buf_size);
263
264 Kokkos::atomic_compare_exchange(error_code.data(), 0, 22);
265 return;
266 }
267
268 // Determine the number of entries to unpack in this batch
269 size_t num_entries_in_batch = 0;
270 if (num_entries_in_row <= batch_size)
272 else if (num_entries_in_row >= (batch_no + 1) * batch_size)
273 num_entries_in_batch = batch_size;
274 else
276
277 const size_t bytes_per_lid = PackTraits<LO>::packValueCount(LO(0));
278 const size_t num_ent_start = offset;
279 const size_t num_ent_end = num_ent_start + bytes_per_lid;
280
282 const size_t gids_start = num_ent_end;
284
285 const size_t vals_start = gids_end;
286
287 const size_t shift = batch_no * batch_size;
288 const char* const num_ent_in = imports.data() + num_ent_start;
289 const char* const gids_in = imports.data() + gids_start + shift * bytes_per_gid;
290 const char* const vals_in = imports.data() + vals_start + shift * bytes_per_value;
291
292 LO num_ent_out;
294 if (static_cast<size_t>(num_ent_out) != num_entries_in_row) {
295 Kokkos::printf(
296 "*** Error: UnpackCrsMatrixAndCombineFunctor: "
297 "At row %d, number of entries (%d) != number of entries unpacked (%d)\n",
298 (int)lid_no, (int)num_entries_in_row, (int)num_ent_out);
299
300 Kokkos::atomic_compare_exchange(error_code.data(), 0, 23);
301 }
302
303 constexpr bool matrix_has_sorted_rows = true; // see #6282
304 // Note BMK 6-22: this lambda must use capture-by-value [=] and not capture-by-ref [&].
305 // By ref triggers compiler bug in CUDA 10.
306 Kokkos::parallel_for(
307 Kokkos::TeamThreadRange(team_member, num_entries_in_batch),
308 [=, *this](const LO& j) {
309 size_t distance = 0;
310
311 GO gid_out;
314 auto lid_out = local_col_map.getLocalElement(gid_out);
315
316 // Column indices come in as global indices, in case the
317 // source object's column Map differs from the target object's
318 // (this's) column Map, and must be converted local index values
319
320 // assume that ST is default constructible
321 ST val_out;
322 distance = j * bytes_per_value;
324
325 if (combine_mode == ADD) {
326 // NOTE (mfh 20 Nov 2019) Must assume atomic is required, unless
327 // different threads don't touch the same row (i.e., no
328 // duplicates in incoming LIDs list).
329 const bool use_atomic_updates = atomic;
330 (void)local_matrix.sumIntoValues(
332 &lid_out,
333 1,
334 &val_out,
337 } else if (combine_mode == REPLACE) {
338 // NOTE (mfh 20 Nov 2019): It's never correct to use REPLACE
339 // combine mode with multiple incoming rows that touch the same
340 // target matrix entries, so we never need atomic updates.
341 const bool use_atomic_updates = false;
342 (void)local_matrix.replaceValues(
344 &lid_out,
345 1,
346 &val_out,
349 } else {
350 // should never get here
351 Kokkos::printf(
352 "*** Error: UnpackCrsMatrixAndCombineFunctor: "
353 "At row %d, an unknown error occurred during unpack\n",
354 (int)lid_no);
355 Kokkos::atomic_compare_exchange(error_code.data(), 0, 31);
356 }
357 });
358
359 team_member.team_barrier();
360 }
361
363 int error() const {
364 auto error_code_h = Kokkos::create_mirror_view_and_copy(
365 Kokkos::HostSpace(), error_code);
366 return error_code_h();
367 }
368
369}; // UnpackCrsMatrixAndCombineFunctor
370
371struct MaxNumEntTag {};
372struct TotNumEntTag {};
373
382template <class LO, class DT, class BDT>
384 public:
385 typedef Kokkos::View<const size_t*, BDT> num_packets_per_lid_type;
386 typedef Kokkos::View<const size_t*, DT> offsets_type;
387 typedef Kokkos::View<const char*, BDT> input_buffer_type;
388 // This needs to be public, since it appears in the argument list of
389 // public methods (see below). Otherwise, build errors may happen.
390 typedef size_t value_type;
391
392 private:
393 num_packets_per_lid_type num_packets_per_lid;
394 offsets_type offsets;
395 input_buffer_type imports;
396
397 public:
398 NumEntriesFunctor(const num_packets_per_lid_type num_packets_per_lid_in,
399 const offsets_type& offsets_in,
400 const input_buffer_type& imports_in)
401 : num_packets_per_lid(num_packets_per_lid_in)
402 , offsets(offsets_in)
403 , imports(imports_in) {}
404
406 operator()(const MaxNumEntTag, const LO i, value_type& update) const {
407 // Get how many entries to expect in the received data for this row.
408 const size_t num_bytes = num_packets_per_lid(i);
409 if (num_bytes > 0) {
410 LO num_ent_LO = 0; // output argument of unpackValue
411 const char* const in_buf = imports.data() + offsets(i);
413 const size_t num_ent = static_cast<size_t>(num_ent_LO);
414
415 update = (update < num_ent) ? num_ent : update;
416 }
417 }
418
420 join(const MaxNumEntTag,
421 value_type& dst,
422 const value_type& src) const {
423 if (dst < src) dst = src;
424 }
425
427 operator()(const TotNumEntTag, const LO i, value_type& tot_num_ent) const {
428 // Get how many entries to expect in the received data for this row.
429 const size_t num_bytes = num_packets_per_lid(i);
430 if (num_bytes > 0) {
431 LO num_ent_LO = 0; // output argument of unpackValue
432 const char* const in_buf = imports.data() + offsets(i);
434 tot_num_ent += static_cast<size_t>(num_ent_LO);
435 }
436 }
437}; // NumEntriesFunctor
438
446template <class LO, class DT, class BDT>
447size_t
449 const Kokkos::View<const size_t*, BDT>& num_packets_per_lid,
450 const Kokkos::View<const size_t*, DT>& offsets,
451 const Kokkos::View<const char*, BDT>& imports) {
452 typedef typename DT::execution_space XS;
453 typedef Kokkos::RangePolicy<XS, Kokkos::IndexType<LO>,
454 MaxNumEntTag>
455 range_policy;
456
457 NumEntriesFunctor<LO, DT, BDT> functor(num_packets_per_lid, offsets,
458 imports);
459 const LO numRowsToUnpack =
460 static_cast<LO>(num_packets_per_lid.extent(0));
461 size_t max_num_ent = 0;
462 Kokkos::parallel_reduce("Max num entries in CRS",
463 range_policy(0, numRowsToUnpack),
464 functor, max_num_ent);
465 return max_num_ent;
466}
467
475template <class LO, class DT, class BDT>
476size_t
478 const Kokkos::View<const size_t*, BDT>& num_packets_per_lid,
479 const Kokkos::View<const size_t*, DT>& offsets,
480 const Kokkos::View<const char*, BDT>& imports) {
481 typedef typename DT::execution_space XS;
482 typedef Kokkos::RangePolicy<XS, Kokkos::IndexType<LO>, TotNumEntTag> range_policy;
483 size_t tot_num_ent = 0;
484 NumEntriesFunctor<LO, DT, BDT> functor(num_packets_per_lid, offsets,
485 imports);
486 const LO numRowsToUnpack =
487 static_cast<LO>(num_packets_per_lid.extent(0));
488 Kokkos::parallel_reduce("Total num entries in CRS to unpack",
489 range_policy(0, numRowsToUnpack),
491 return tot_num_ent;
492}
493
494template <class LO>
496 size_t
497 unpackRowCount(const char imports[],
498 const size_t offset,
499 const size_t num_bytes) {
500 using PT = PackTraits<LO>;
501
502 LO num_ent_LO = 0;
503 if (num_bytes > 0) {
504 const size_t p_num_bytes = PT::packValueCount(num_ent_LO);
505 if (p_num_bytes > num_bytes) {
507 }
508 const char* const in_buf = imports + offset;
509 (void)PT::unpackValue(num_ent_LO, in_buf);
510 }
511 return static_cast<size_t>(num_ent_LO);
512}
513
518template <class View1, class View2>
519inline bool
521 const View1& batches_per_lid,
522 View2& batch_info) {
523 using LO = typename View2::value_type;
524 size_t batch = 0;
525 for (size_t i = 0; i < batches_per_lid.extent(0); i++) {
526 for (size_t batch_no = 0; batch_no < batches_per_lid(i); batch_no++) {
527 batch_info(batch, 0) = static_cast<LO>(i);
528 batch_info(batch, 1) = batch_no;
529 batch++;
530 }
531 }
532 return batch == batch_info.extent(0);
533}
534
542template <class LocalMatrix, class LocalMap, class BufferDeviceType>
544 const LocalMatrix& local_matrix,
545 const LocalMap& local_map,
546 const Kokkos::View<const char*, BufferDeviceType>& imports,
547 const Kokkos::View<const size_t*, BufferDeviceType>& num_packets_per_lid,
549 const Tpetra::CombineMode combine_mode) {
550 using ST = typename LocalMatrix::value_type;
551 using LO = typename LocalMap::local_ordinal_type;
552 using DT = typename LocalMap::device_type;
553 using XS = typename DT::execution_space;
554 const char prefix[] =
555 "Tpetra::Details::UnpackAndCombineCrsMatrixImpl::"
556 "unpackAndCombineIntoCrsMatrix: ";
557
558 const size_t num_import_lids = static_cast<size_t>(import_lids.extent(0));
559 if (num_import_lids == 0) {
560 // Nothing to unpack
561 return;
562 }
563
564 {
565 // Check for correct input
566 TEUCHOS_TEST_FOR_EXCEPTION(combine_mode == ABSMAX,
567 std::invalid_argument,
568 prefix << "ABSMAX combine mode is not yet implemented for a matrix that has a "
569 "static graph (i.e., was constructed with the CrsMatrix constructor "
570 "that takes a const CrsGraph pointer).");
571
572 TEUCHOS_TEST_FOR_EXCEPTION(combine_mode == INSERT,
573 std::invalid_argument,
574 prefix << "INSERT combine mode is not allowed if the matrix has a static graph "
575 "(i.e., was constructed with the CrsMatrix constructor that takes a "
576 "const CrsGraph pointer).");
577
578 // Unknown combine mode!
579 TEUCHOS_TEST_FOR_EXCEPTION(!(combine_mode == ADD || combine_mode == REPLACE),
580 std::invalid_argument,
581 prefix << "Invalid combine mode; should never get "
582 "here! Please report this bug to the Tpetra developers.");
583
584 // Check that sizes of input objects are consistent.
586 num_import_lids != static_cast<size_t>(num_packets_per_lid.extent(0));
588 std::invalid_argument,
589 prefix << "importLIDs.size() (" << num_import_lids << ") != "
590 "numPacketsPerLID.size() ("
591 << num_packets_per_lid.extent(0) << ").");
592 } // end QA error checking
593
594 // Get the offsets
595 Kokkos::View<size_t*, DT> offsets("offsets", num_import_lids + 1);
596 computeOffsetsFromCounts(offsets, num_packets_per_lid);
597
598 // Determine the sizes of the unpack batches
599 size_t max_num_ent = compute_maximum_num_entries<LO, DT>(num_packets_per_lid, offsets, imports);
601 const size_t batch_size = std::min(default_batch_size, max_num_ent);
602
603 // To achieve some balance amongst threads, unpack each row in equal size batches
604 size_t num_batches = 0;
605 Kokkos::View<LO* [2], DT> batch_info("", num_batches);
606 Kokkos::View<size_t*, DT> batches_per_lid("", num_import_lids);
607 // Compute meta data that allows batch unpacking
608 Kokkos::parallel_reduce(
609 Kokkos::RangePolicy<XS, Kokkos::IndexType<size_t>>(0, num_import_lids),
610 KOKKOS_LAMBDA(const size_t i, size_t& batches) {
612 imports.data(), offsets(i), num_packets_per_lid(i));
614 (num_entries_in_row <= batch_size) ? 1 : num_entries_in_row / batch_size + (num_entries_in_row % batch_size != 0);
616 },
618 Kokkos::resize(batch_info, num_batches);
619
620 Kokkos::HostSpace host_space;
621 auto batches_per_lid_h = Kokkos::create_mirror_view(host_space, batches_per_lid);
622 // DEEP_COPY REVIEW - DEVICE-TO-HOSTMIRROR
623 Kokkos::deep_copy(XS(), batches_per_lid_h, batches_per_lid);
624
625 auto batch_info_h = Kokkos::create_mirror_view(host_space, batch_info);
626
627 XS().fence();
629 // DEEP_COPY REVIEW - HOSTMIRROR-TO-DEVICE
630 Kokkos::deep_copy(XS(), batch_info, batch_info_h);
631
632 // FIXME (TJF SEP 2017)
633 // The scalar type is not necessarily default constructible
634 size_t bytes_per_value = PackTraits<ST>::packValueCount(ST());
635
636 // Now do the actual unpack!
637 const bool atomic = XS().concurrency() != 1;
639 functor f(
640 local_matrix,
641 local_map,
642 imports,
643 num_packets_per_lid,
644 import_lids,
645 batch_info,
646 offsets,
647 combine_mode,
648 batch_size,
649 bytes_per_value,
650 atomic);
651
652 using policy = Kokkos::TeamPolicy<XS, Kokkos::IndexType<LO>>;
654 if (!Spaces::is_gpu_exec_space<XS>() || team_size == Teuchos::OrdinalTraits<size_t>::invalid()) {
655 Kokkos::parallel_for(policy(static_cast<LO>(num_batches), Kokkos::AUTO), f);
656 } else {
657 Kokkos::parallel_for(policy(static_cast<LO>(num_batches), static_cast<int>(team_size)), f);
658 }
659
660 auto error_code = f.error();
662 error_code != 0,
663 std::runtime_error,
664 prefix << "UnpackCrsMatrixAndCombineFunctor reported error code " << error_code);
665} // unpackAndCombineIntoCrsMatrix (Kokkos version)
666
667template <class LocalMatrix, class BufferDeviceType>
668size_t
670 const LocalMatrix& local_matrix,
673 const Kokkos::View<const char*, BufferDeviceType, void, void>& imports,
674 const Kokkos::View<const size_t*, BufferDeviceType, void, void>& num_packets_per_lid,
675#else
676 const Kokkos::View<const char*, BufferDeviceType>& imports,
677 const Kokkos::View<const size_t*, BufferDeviceType>& num_packets_per_lid,
678#endif
679 const size_t num_same_ids) {
680 using Kokkos::parallel_reduce;
681 typedef typename LocalMatrix::ordinal_type LO;
682 typedef typename LocalMatrix::device_type device_type;
683 typedef typename device_type::execution_space XS;
684 typedef typename Kokkos::View<LO*, device_type>::size_type size_type;
685 typedef Kokkos::RangePolicy<XS, Kokkos::IndexType<LO>> range_policy;
686 typedef BufferDeviceType BDT;
687
688 size_t count = 0;
689 LO num_items;
690
691 // Number of matrix entries to unpack (returned by this function).
692 num_items = static_cast<LO>(num_same_ids);
693 if (num_items) {
694 size_t kcnt = 0;
696 range_policy(0, num_items),
697 KOKKOS_LAMBDA(const LO lid, size_t& update) {
698 update += static_cast<size_t>(local_matrix.graph.row_map[lid + 1] - local_matrix.graph.row_map[lid]);
699 },
700 kcnt);
701 count += kcnt;
702 }
703
704 // Count entries copied directly from the source matrix with permuting.
705 num_items = static_cast<LO>(permute_from_lids.extent(0));
706 if (num_items) {
707 size_t kcnt = 0;
708 parallel_reduce(
709 range_policy(0, num_items),
710 KOKKOS_LAMBDA(const LO i, size_t& update) {
711 const LO lid = permute_from_lids(i);
712 update += static_cast<size_t>(local_matrix.graph.row_map[lid + 1] - local_matrix.graph.row_map[lid]);
713 },
714 kcnt);
715 count += kcnt;
716 }
717
718 {
719 // Count entries received from other MPI processes.
720 const size_type np = num_packets_per_lid.extent(0);
721 Kokkos::View<size_t*, device_type> offsets("offsets", np + 1);
722 computeOffsetsFromCounts(offsets, num_packets_per_lid);
723 count +=
724 compute_total_num_entries<LO, device_type, BDT>(num_packets_per_lid,
725 offsets, imports);
726 }
727
728 return count;
729} // unpackAndCombineWithOwningPIDsCount (Kokkos version)
730
732template <class LO, class DT, class BDT>
733int setupRowPointersForRemotes(
735 const typename PackTraits<LO>::input_array_type& import_lids,
736 const Kokkos::View<const char*, BDT>& imports,
737 const Kokkos::View<const size_t*, BDT>& num_packets_per_lid,
738 const typename PackTraits<size_t>::input_array_type& offsets) {
739 using Kokkos::parallel_reduce;
740 typedef typename DT::execution_space XS;
741 typedef typename PackTraits<size_t>::input_array_type::size_type size_type;
742 typedef Kokkos::RangePolicy<XS, Kokkos::IndexType<size_type>> range_policy;
743
745 const size_type N = num_packets_per_lid.extent(0);
746
747 int errors = 0;
749 "Setup row pointers for remotes",
750 range_policy(0, N),
751 KOKKOS_LAMBDA(const size_t i, int& k_error) {
752 typedef typename std::remove_reference<decltype(tgt_rowptr(0))>::type atomic_incr_type;
753 const size_t num_bytes = num_packets_per_lid(i);
754 const size_t offset = offsets(i);
755 const size_t num_ent = unpackRowCount<LO>(imports.data(), offset, num_bytes);
756 if (num_ent == InvalidNum) {
757 k_error += 1;
758 }
759 Kokkos::atomic_fetch_add(&tgt_rowptr(import_lids(i)), atomic_incr_type(num_ent));
760 },
761 errors);
762 return errors;
763}
764
765// Convert array of row lengths to a CRS pointer array
766template <class DT>
767void makeCrsRowPtrFromLengths(
769 const Kokkos::View<size_t*, DT>& new_start_row) {
770 using Kokkos::parallel_scan;
771 typedef typename DT::execution_space XS;
772 typedef typename Kokkos::View<size_t*, DT>::size_type size_type;
773 typedef Kokkos::RangePolicy<XS, Kokkos::IndexType<size_type>> range_policy;
774 const size_type N = new_start_row.extent(0);
776 range_policy(0, N),
777 KOKKOS_LAMBDA(const size_t& i, size_t& update, const bool& final) {
778 auto cur_val = tgt_rowptr(i);
779 if (final) {
780 tgt_rowptr(i) = update;
782 }
783 update += cur_val;
784 });
785}
786
787template <class LocalMatrix, class LocalMap>
788void copyDataFromSameIDs(
790 const typename PackTraits<int>::output_array_type& tgt_pids,
792 const Kokkos::View<size_t*, typename LocalMap::device_type>& new_start_row,
793 const typename PackTraits<size_t>::output_array_type& tgt_rowptr,
794 const typename PackTraits<int>::input_array_type& src_pids,
795 const LocalMatrix& local_matrix,
796 const LocalMap& local_col_map,
797 const size_t num_same_ids,
798 const int my_pid) {
799 using Kokkos::parallel_for;
800 typedef typename LocalMap::device_type DT;
801 typedef typename LocalMap::local_ordinal_type LO;
802 typedef typename DT::execution_space XS;
803 typedef Kokkos::RangePolicy<XS, Kokkos::IndexType<size_t>> range_policy;
804
805 parallel_for(
806 range_policy(0, num_same_ids),
807 KOKKOS_LAMBDA(const size_t i) {
808 typedef typename std::remove_reference<decltype(new_start_row(0))>::type atomic_incr_type;
809
810 const LO src_lid = static_cast<LO>(i);
811 size_t src_row = local_matrix.graph.row_map(src_lid);
812
813 const LO tgt_lid = static_cast<LO>(i);
814 const size_t tgt_row = tgt_rowptr(tgt_lid);
815
816 const size_t nsr = local_matrix.graph.row_map(src_lid + 1) - local_matrix.graph.row_map(src_lid);
817 Kokkos::atomic_fetch_add(&new_start_row(tgt_lid), atomic_incr_type(nsr));
818
819 for (size_t j = local_matrix.graph.row_map(src_lid);
820 j < local_matrix.graph.row_map(src_lid + 1); ++j) {
821 LO src_col = local_matrix.graph.entries(j);
822 tgt_vals(tgt_row + j - src_row) = local_matrix.values(j);
823 tgt_colind(tgt_row + j - src_row) = local_col_map.getGlobalElement(src_col);
824 tgt_pids(tgt_row + j - src_row) = (src_pids(src_col) != my_pid) ? src_pids(src_col) : -1;
825 }
826 });
827}
828
829template <class LocalMatrix, class LocalMap>
830void copyDataFromPermuteIDs(
832 const typename PackTraits<int>::output_array_type& tgt_pids,
834 const Kokkos::View<size_t*, typename LocalMap::device_type>& new_start_row,
835 const typename PackTraits<size_t>::output_array_type& tgt_rowptr,
836 const typename PackTraits<int>::input_array_type& src_pids,
839 const LocalMatrix& local_matrix,
840 const LocalMap& local_col_map,
841 const int my_pid) {
842 using Kokkos::parallel_for;
843 typedef typename LocalMap::device_type DT;
844 typedef typename LocalMap::local_ordinal_type LO;
845 typedef typename DT::execution_space XS;
846 typedef typename PackTraits<LO>::input_array_type::size_type size_type;
847 typedef Kokkos::RangePolicy<XS, Kokkos::IndexType<size_type>> range_policy;
848
849 const size_type num_permute_to_lids = permute_to_lids.extent(0);
850
851 parallel_for(
852 range_policy(0, num_permute_to_lids),
853 KOKKOS_LAMBDA(const size_t i) {
854 typedef typename std::remove_reference<decltype(new_start_row(0))>::type atomic_incr_type;
855
856 const LO src_lid = permute_from_lids(i);
857 const size_t src_row = local_matrix.graph.row_map(src_lid);
858
859 const LO tgt_lid = permute_to_lids(i);
860 const size_t tgt_row = tgt_rowptr(tgt_lid);
861
862 size_t nsr = local_matrix.graph.row_map(src_lid + 1) - local_matrix.graph.row_map(src_lid);
863 Kokkos::atomic_fetch_add(&new_start_row(tgt_lid), atomic_incr_type(nsr));
864
865 for (size_t j = local_matrix.graph.row_map(src_lid);
866 j < local_matrix.graph.row_map(src_lid + 1); ++j) {
867 LO src_col = local_matrix.graph.entries(j);
868 tgt_vals(tgt_row + j - src_row) = local_matrix.values(j);
869 tgt_colind(tgt_row + j - src_row) = local_col_map.getGlobalElement(src_col);
870 tgt_pids(tgt_row + j - src_row) = (src_pids(src_col) != my_pid) ? src_pids(src_col) : -1;
871 }
872 });
873}
874
875template <typename LocalMatrix, typename LocalMap, typename BufferDeviceType>
876int unpackAndCombineIntoCrsArrays2(
878 const typename PackTraits<int>::output_array_type& tgt_pids,
880 const Kokkos::View<size_t*, typename LocalMap::device_type>& new_start_row,
881 const typename PackTraits<size_t>::input_array_type& offsets,
883#ifdef KOKKOS_ENABLE_DEPRECATED_CODE_4
884 const Kokkos::View<const char*, BufferDeviceType, void, void>& imports,
885 const Kokkos::View<const size_t*, BufferDeviceType, void, void>& num_packets_per_lid,
886#else
887 const Kokkos::View<const char*, BufferDeviceType>& imports,
888 const Kokkos::View<const size_t*, BufferDeviceType>& num_packets_per_lid,
889#endif
890 const LocalMatrix& /* local_matrix */,
891 const LocalMap /*& local_col_map*/,
892 const int my_pid,
893 const size_t bytes_per_value) {
894 using Kokkos::atomic_fetch_add;
895 using Kokkos::MemoryUnmanaged;
896 using Kokkos::parallel_reduce;
897 using Kokkos::subview;
898 using Kokkos::View;
900 typedef typename LocalMap::device_type DT;
901 typedef typename LocalMap::local_ordinal_type LO;
902 typedef typename LocalMap::global_ordinal_type GO;
903 typedef typename LocalMatrix::value_type ST;
904 typedef typename DT::execution_space XS;
905 typedef typename Kokkos::View<LO*, DT>::size_type size_type;
906 typedef typename Kokkos::pair<size_type, size_type> slice;
907 typedef Kokkos::RangePolicy<XS, Kokkos::IndexType<size_type>> range_policy;
908
909 typedef View<int*, DT, MemoryUnmanaged> pids_out_type;
910 typedef View<GO*, DT, MemoryUnmanaged> gids_out_type;
911 typedef View<ST*, DT, MemoryUnmanaged> vals_out_type;
912
913 const size_t InvalidNum = OrdinalTraits<size_t>::invalid();
914
915 int errors = 0;
916 const size_type num_import_lids = import_lids.size();
917
918 // RemoteIDs: Loop structure following UnpackAndCombine
919 parallel_reduce(
920 "Unpack and combine into CRS",
921 range_policy(0, num_import_lids),
922 KOKKOS_LAMBDA(const size_t i, int& k_error) {
923 typedef typename std::remove_reference<decltype(new_start_row(0))>::type atomic_incr_type;
924 const size_t num_bytes = num_packets_per_lid(i);
925 const size_t offset = offsets(i);
926 if (num_bytes == 0) {
927 // Empty buffer means that the row is empty.
928 return;
929 }
930 size_t num_ent = unpackRowCount<LO>(imports.data(), offset, num_bytes);
931 if (num_ent == InvalidNum) {
932 k_error += 1;
933 return;
934 }
935 const LO lcl_row = import_lids(i);
936 const size_t start_row = atomic_fetch_add(&new_start_row(lcl_row), atomic_incr_type(num_ent));
937 const size_t end_row = start_row + num_ent;
938
939 gids_out_type gids_out = subview(tgt_colind, slice(start_row, end_row));
940 vals_out_type vals_out = subview(tgt_vals, slice(start_row, end_row));
941 pids_out_type pids_out = subview(tgt_pids, slice(start_row, end_row));
942
943 k_error += unpackRow<ST, LO, GO>(gids_out, pids_out, vals_out,
944 imports.data(), offset, num_bytes,
945 num_ent, bytes_per_value);
946
947 // Correct target PIDs.
948 for (size_t j = 0; j < static_cast<size_t>(num_ent); ++j) {
949 const int pid = pids_out(j);
950 pids_out(j) = (pid != my_pid) ? pid : -1;
951 }
952 },
953 errors);
954
955 return errors;
956}
957
958template <typename LocalMatrix, typename LocalMap, typename BufferDeviceType>
960 const LocalMatrix& local_matrix,
961 const LocalMap& local_col_map,
963#ifdef KOKKOS_ENABLE_DEPRECATED_CODE_4
964 const Kokkos::View<const char*, BufferDeviceType, void, void>& imports,
965 const Kokkos::View<const size_t*, BufferDeviceType, void, void>& num_packets_per_lid,
966#else
967 const Kokkos::View<const char*, BufferDeviceType>& imports,
968 const Kokkos::View<const size_t*, BufferDeviceType>& num_packets_per_lid,
969#endif
972 const typename PackTraits<size_t>::output_array_type& tgt_rowptr,
975 const typename PackTraits<int>::input_array_type& src_pids,
976 const typename PackTraits<int>::output_array_type& tgt_pids,
977 const size_t num_same_ids,
978 const size_t tgt_num_rows,
979 const size_t tgt_num_nonzeros,
980 const int my_tgt_pid,
981 const size_t bytes_per_value) {
982 using Kokkos::MemoryUnmanaged;
983 using Kokkos::parallel_for;
984 using Kokkos::subview;
985 using Kokkos::View;
987 typedef typename LocalMap::device_type DT;
988 typedef typename LocalMap::local_ordinal_type LO;
989 typedef typename DT::execution_space XS;
990 typedef typename Kokkos::View<LO*, DT>::size_type size_type;
991 typedef Kokkos::RangePolicy<XS, Kokkos::IndexType<size_t>> range_policy;
992 typedef BufferDeviceType BDT;
993
994 const char prefix[] = "unpackAndCombineIntoCrsArrays: ";
995
996 const size_t N = tgt_num_rows;
997
998 // In the case of reduced communicators, the sourceMatrix won't have
999 // the right "my_pid", so thus we have to supply it.
1000 const int my_pid = my_tgt_pid;
1001
1002 // Zero the rowptr
1003 parallel_for(
1004 range_policy(0, N + 1),
1005 KOKKOS_LAMBDA(const size_t i) {
1006 tgt_rowptr(i) = 0;
1007 });
1008
1009 // same IDs: Always first, always in the same place
1010 parallel_for(
1011 range_policy(0, num_same_ids),
1012 KOKKOS_LAMBDA(const size_t i) {
1013 const LO tgt_lid = static_cast<LO>(i);
1014 const LO src_lid = static_cast<LO>(i);
1015 tgt_rowptr(tgt_lid) = local_matrix.graph.row_map(src_lid + 1) - local_matrix.graph.row_map(src_lid);
1016 });
1017
1018 // Permute IDs: Still local, but reordered
1019 const size_type num_permute_to_lids = permute_to_lids.extent(0);
1020 parallel_for(
1021 range_policy(0, num_permute_to_lids),
1022 KOKKOS_LAMBDA(const size_t i) {
1023 const LO tgt_lid = permute_to_lids(i);
1024 const LO src_lid = permute_from_lids(i);
1025 tgt_rowptr(tgt_lid) = local_matrix.graph.row_map(src_lid + 1) - local_matrix.graph.row_map(src_lid);
1026 });
1027
1028 // Get the offsets from the number of packets per LID
1029 const size_type num_import_lids = import_lids.extent(0);
1030 View<size_t*, DT> offsets("offsets", num_import_lids + 1);
1031 computeOffsetsFromCounts(offsets, num_packets_per_lid);
1032
1033#ifdef HAVE_TPETRA_DEBUG
1034 {
1035 auto nth_offset_h = getEntryOnHost(offsets, num_import_lids);
1036 const bool condition =
1037 nth_offset_h != static_cast<size_t>(imports.extent(0));
1038 TEUCHOS_TEST_FOR_EXCEPTION(condition, std::logic_error, prefix << "The final offset in bytes " << nth_offset_h << " != imports.size() = " << imports.extent(0) << ". Please report this bug to the Tpetra developers.");
1039 }
1040#endif // HAVE_TPETRA_DEBUG
1041
1042 // Setup row pointers for remotes
1043 int k_error =
1044 setupRowPointersForRemotes<LO, DT, BDT>(tgt_rowptr,
1045 import_lids, imports, num_packets_per_lid, offsets);
1046 TEUCHOS_TEST_FOR_EXCEPTION(k_error != 0, std::logic_error, prefix << " Error transferring data to target row pointers. "
1047 "Please report this bug to the Tpetra developers.");
1048
1049 // If multiple processes contribute to the same row, we may need to
1050 // update row offsets. This tracks that.
1051 View<size_t*, DT> new_start_row("new_start_row", N + 1);
1052
1053 // Turn row length into a real CRS row pointer
1054 makeCrsRowPtrFromLengths(tgt_rowptr, new_start_row);
1055
1056 // SameIDs: Copy the data over
1057 copyDataFromSameIDs(tgt_colind, tgt_pids, tgt_vals, new_start_row,
1058 tgt_rowptr, src_pids, local_matrix, local_col_map, num_same_ids, my_pid);
1059
1060 copyDataFromPermuteIDs(tgt_colind, tgt_pids, tgt_vals, new_start_row,
1061 tgt_rowptr, src_pids, permute_to_lids, permute_from_lids,
1062 local_matrix, local_col_map, my_pid);
1063
1064 if (imports.extent(0) <= 0) {
1065 return;
1066 }
1067
1068 int unpack_err = unpackAndCombineIntoCrsArrays2(tgt_colind, tgt_pids,
1069 tgt_vals, new_start_row, offsets, import_lids, imports, num_packets_per_lid,
1070 local_matrix, local_col_map, my_pid, bytes_per_value);
1071 TEUCHOS_TEST_FOR_EXCEPTION(
1072 unpack_err != 0, std::logic_error, prefix << "unpack loop failed. This "
1073 "should never happen. Please report this bug to the Tpetra developers.");
1074
1075 return;
1076}
1077
1078} // namespace UnpackAndCombineCrsMatrixImpl
1079
1114template <typename ST, typename LO, typename GO, typename Node>
1117 const Teuchos::ArrayView<const char>& imports,
1118 const Teuchos::ArrayView<const size_t>& numPacketsPerLID,
1119 const Teuchos::ArrayView<const LO>& importLIDs,
1120 size_t /* constantNumPackets */,
1122 using Kokkos::View;
1123 typedef typename Node::device_type device_type;
1124 typedef typename CrsMatrix<ST, LO, GO, Node>::local_matrix_device_type local_matrix_device_type;
1125 static_assert(std::is_same<device_type, typename local_matrix_device_type::device_type>::value,
1126 "Node::device_type and LocalMatrix::device_type must be the same.");
1127
1128 // Convert all Teuchos::Array to Kokkos::View.
1129 device_type outputDevice;
1130
1131 // numPacketsPerLID, importLIDs, and imports are input, so we have to copy
1132 // them to device. Since unpacking is done directly in to the local matrix
1133 // (lclMatrix), no copying needs to be performed after unpacking.
1136 numPacketsPerLID.size(), true, "num_packets_per_lid");
1137
1138 auto import_lids_d =
1140 importLIDs.size(), true, "import_lids");
1141
1142 auto imports_d =
1144 imports.size(), true, "imports");
1145
1146 auto local_matrix = sourceMatrix.getLocalMatrixDevice();
1147 auto local_col_map = sourceMatrix.getColMap()->getLocalMap();
1148
1149 // KDDKDD This loop doesn't appear to do anything; what is it?
1150 // KDDKDD for (int i=0; i<importLIDs.size(); i++)
1151 // KDDKDD {
1152 // KDDKDD auto lclRow = importLIDs[i];
1153 // KDDKDD Teuchos::ArrayView<const LO> A_indices;
1154 // KDDKDD Teuchos::ArrayView<const ST> A_values;
1155 // KDDKDD sourceMatrix.getLocalRowView(lclRow, A_indices, A_values);
1156 // KDDKDD }
1157 // Now do the actual unpack!
1158 UnpackAndCombineCrsMatrixImpl::unpackAndCombineIntoCrsMatrix(
1159 local_matrix, local_col_map, imports_d, num_packets_per_lid_d,
1161}
1162
1163template <typename ST, typename LO, typename GO, typename NT>
1164void unpackCrsMatrixAndCombineNew(
1166 Kokkos::DualView<char*,
1168 imports,
1169 Kokkos::DualView<size_t*,
1172 const Kokkos::DualView<const LO*,
1174 const size_t /* constantNumPackets */,
1175 const CombineMode combineMode) {
1176 using Kokkos::View;
1177 using crs_matrix_type = CrsMatrix<ST, LO, GO, NT>;
1178 using dist_object_type = DistObject<char, LO, GO, NT>;
1179 using device_type = typename crs_matrix_type::device_type;
1180 using local_matrix_device_type = typename crs_matrix_type::local_matrix_device_type;
1181 using buffer_device_type = typename dist_object_type::buffer_device_type;
1182
1183 static_assert(std::is_same<device_type, typename local_matrix_device_type::device_type>::value,
1184 "crs_matrix_type::device_type and local_matrix_device_type::device_type "
1185 "must be the same.");
1186
1187 if (numPacketsPerLID.need_sync_device()) {
1188 numPacketsPerLID.sync_device();
1189 }
1190 auto num_packets_per_lid_d = numPacketsPerLID.view_device();
1191
1192 TEUCHOS_ASSERT(!importLIDs.need_sync_device());
1193 auto import_lids_d = importLIDs.view_device();
1194
1195 if (imports.need_sync_device()) {
1196 imports.sync_device();
1197 }
1198 auto imports_d = imports.view_device();
1199
1200 auto local_matrix = sourceMatrix.getLocalMatrixDevice();
1201 auto local_col_map = sourceMatrix.getColMap()->getLocalMap();
1202 typedef decltype(local_col_map) local_map_type;
1203
1204 UnpackAndCombineCrsMatrixImpl::unpackAndCombineIntoCrsMatrix<
1205 local_matrix_device_type,
1206 local_map_type,
1207 buffer_device_type>(local_matrix, local_col_map, imports_d, num_packets_per_lid_d,
1208 import_lids_d, combineMode);
1209}
1210
1257//
1266template <typename Scalar, typename LocalOrdinal, typename GlobalOrdinal, typename Node>
1267size_t
1270 const Teuchos::ArrayView<const LocalOrdinal>& importLIDs,
1271 const Teuchos::ArrayView<const char>& imports,
1272 const Teuchos::ArrayView<const size_t>& numPacketsPerLID,
1273 size_t /* constantNumPackets */,
1274 CombineMode /* combineMode */,
1275 size_t numSameIDs,
1276 const Teuchos::ArrayView<const LocalOrdinal>& permuteToLIDs,
1277 const Teuchos::ArrayView<const LocalOrdinal>& permuteFromLIDs) {
1278 using Kokkos::MemoryUnmanaged;
1279 using Kokkos::View;
1280 typedef typename Node::device_type DT;
1281 const char prefix[] = "unpackAndCombineWithOwningPIDsCount: ";
1282
1283 TEUCHOS_TEST_FOR_EXCEPTION(permuteToLIDs.size() != permuteFromLIDs.size(), std::invalid_argument,
1284 prefix << "permuteToLIDs.size() = " << permuteToLIDs.size() << " != "
1285 "permuteFromLIDs.size() = "
1286 << permuteFromLIDs.size() << ".");
1287 // FIXME (mfh 26 Jan 2015) If there are no entries on the calling
1288 // process, then the matrix is neither locally nor globally indexed.
1289 const bool locallyIndexed = sourceMatrix.isLocallyIndexed();
1290 TEUCHOS_TEST_FOR_EXCEPTION(!locallyIndexed, std::invalid_argument, prefix << "The input "
1291 "CrsMatrix 'sourceMatrix' must be locally indexed.");
1292 TEUCHOS_TEST_FOR_EXCEPTION(importLIDs.size() != numPacketsPerLID.size(), std::invalid_argument,
1293 prefix << "importLIDs.size() = " << importLIDs.size() << " != "
1294 "numPacketsPerLID.size() = "
1295 << numPacketsPerLID.size() << ".");
1296
1297 auto local_matrix = sourceMatrix.getLocalMatrixDevice();
1298
1299 using kokkos_device_type = Kokkos::Device<typename Node::device_type::execution_space,
1300 Tpetra::Details::DefaultTypes::comm_buffer_memory_space<typename Node::device_type>>;
1301
1302#ifdef KOKKOS_ENABLE_DEPRECATED_CODE_4
1303 Kokkos::View<LocalOrdinal const*, kokkos_device_type, void, void> permute_from_lids_d =
1304#else
1305 Kokkos::View<LocalOrdinal const*, kokkos_device_type> permute_from_lids_d =
1306#endif
1308 permuteFromLIDs.getRawPtr(),
1309 permuteFromLIDs.size(), true,
1310 "permute_from_lids");
1311
1312#ifdef KOKKOS_ENABLE_DEPRECATED_CODE_4
1313 Kokkos::View<const char*, kokkos_device_type, void, void> imports_d =
1314#else
1315 Kokkos::View<const char*, kokkos_device_type> imports_d =
1316#endif
1318 imports.getRawPtr(),
1319 imports.size(), true,
1320 "imports");
1321
1322#ifdef KOKKOS_ENABLE_DEPRECATED_CODE_4
1323 Kokkos::View<const size_t*, kokkos_device_type, void, void> num_packets_per_lid_d =
1324#else
1325 Kokkos::View<const size_t*, kokkos_device_type> num_packets_per_lid_d =
1326#endif
1328 numPacketsPerLID.getRawPtr(),
1329 numPacketsPerLID.size(), true,
1330 "num_packets_per_lid");
1331
1332 return UnpackAndCombineCrsMatrixImpl::unpackAndCombineWithOwningPIDsCount(
1333 local_matrix, permute_from_lids_d, imports_d,
1334 num_packets_per_lid_d, numSameIDs);
1335} // unpackAndCombineWithOwningPIDsCount (Teuchos::Array version)
1336
1351
1352template <typename Scalar, typename LocalOrdinal, typename GlobalOrdinal, typename Node>
1355 const Kokkos::View<LocalOrdinal const*,
1356 Kokkos::Device<typename Node::device_type::execution_space,
1357 Tpetra::Details::DefaultTypes::comm_buffer_memory_space<typename Node::device_type>>
1359 ,
1360 void, void
1361#endif
1362 >
1364 const Kokkos::View<const char*,
1365 Kokkos::Device<typename Node::device_type::execution_space,
1366 Tpetra::Details::DefaultTypes::comm_buffer_memory_space<typename Node::device_type>>
1368 ,
1369 void, void
1370#endif
1371 >
1372 imports_d,
1373 const Kokkos::View<const size_t*,
1374 Kokkos::Device<typename Node::device_type::execution_space,
1375 Tpetra::Details::DefaultTypes::comm_buffer_memory_space<typename Node::device_type>>
1377 ,
1378 void, void
1379#endif
1380 >
1382 const size_t numSameIDs,
1383 const Kokkos::View<LocalOrdinal const*,
1384 Kokkos::Device<typename Node::device_type::execution_space,
1385 Tpetra::Details::DefaultTypes::comm_buffer_memory_space<typename Node::device_type>>
1387 ,
1388 void, void
1389#endif
1390 >
1392 const Kokkos::View<LocalOrdinal const*,
1393 Kokkos::Device<typename Node::device_type::execution_space,
1394 Tpetra::Details::DefaultTypes::comm_buffer_memory_space<typename Node::device_type>>
1396 ,
1397 void, void
1398#endif
1399 >
1401 size_t TargetNumRows,
1402 const int MyTargetPID,
1403 Kokkos::View<size_t*, typename Node::device_type>& crs_rowptr_d,
1404 Kokkos::View<GlobalOrdinal*, typename Node::device_type>& crs_colind_d,
1405 Kokkos::View<typename CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::impl_scalar_type*, typename Node::device_type>& crs_vals_d,
1406 const Teuchos::ArrayView<const int>& SourcePids,
1407 Kokkos::View<int*, typename Node::device_type>& TargetPids) {
1408 using execution_space = typename Node::execution_space;
1410
1411 using Kokkos::deep_copy;
1412 using Kokkos::View;
1413
1414 using Teuchos::ArrayView;
1415 using Teuchos::outArg;
1416 using Teuchos::REDUCE_MAX;
1417 using Teuchos::reduceAll;
1418
1419 typedef typename Node::device_type DT;
1420
1422 typedef typename matrix_type::impl_scalar_type ST;
1423
1424 const char prefix[] = "Tpetra::Details::unpackAndCombineIntoCrsArrays_new: ";
1425 Teuchos::RCP<Tpetra::Details::ProfilingRegion> tm;
1426
1427 using Kokkos::MemoryUnmanaged;
1428
1429 TEUCHOS_TEST_FOR_EXCEPTION(permute_to_lids_d.size() != permute_from_lids_d.size(), std::invalid_argument,
1430 prefix << "permute_to_lids_d.size() = " << permute_to_lids_d.size() << " != "
1431 "permute_from_lids_d.size() = "
1432 << permute_from_lids_d.size() << ".");
1433 // FIXME (mfh 26 Jan 2015) If there are no entries on the calling
1434 // process, then the matrix is neither locally nor globally indexed.
1435 const bool locallyIndexed = sourceMatrix.isLocallyIndexed();
1436 TEUCHOS_TEST_FOR_EXCEPTION(!locallyIndexed, std::invalid_argument, prefix << "The input "
1437 "CrsMatrix 'sourceMatrix' must be locally indexed.");
1438 TEUCHOS_TEST_FOR_EXCEPTION(((size_t)import_lids_d.size()) != num_packets_per_lid_d.size(), std::invalid_argument,
1439 prefix << "import_lids_d.size() = " << import_lids_d.size() << " != "
1440 "num_packets_per_lid_d.size() = "
1441 << num_packets_per_lid_d.size() << ".");
1442
1443 auto local_matrix = sourceMatrix.getLocalMatrixDevice();
1444
1445 // TargetNumNonzeros is number of nonzeros in local matrix.
1446 tm = Teuchos::rcp(new Tpetra::Details::ProfilingRegion("Tpetra::Details::unpackAndCombineIntoCrsArrays_new: unpackAndCombineWithOwningPIDsCount"));
1447 size_t TargetNumNonzeros =
1448 UnpackAndCombineCrsMatrixImpl::unpackAndCombineWithOwningPIDsCount(
1449 local_matrix, permute_from_lids_d, imports_d,
1450 num_packets_per_lid_d, numSameIDs);
1451 tm = Teuchos::null;
1452
1453 tm = Teuchos::rcp(new Tpetra::Details::ProfilingRegion("Tpetra::Details::unpackAndCombineIntoCrsArrays_new: resize CRS pointers"));
1454 Kokkos::resize(crs_rowptr_d, TargetNumRows + 1);
1455 Kokkos::resize(crs_colind_d, TargetNumNonzeros);
1456 Kokkos::resize(crs_vals_d, TargetNumNonzeros);
1457 tm = Teuchos::null;
1458
1460 permute_to_lids_d.size() != permute_from_lids_d.size(), std::invalid_argument,
1461 prefix << "permuteToLIDs.size() = " << permute_to_lids_d.size()
1462 << "!= permute_from_lids_d.size() = " << permute_from_lids_d.size() << ".");
1463
1464 if (static_cast<size_t>(TargetPids.size()) != TargetNumNonzeros) {
1465 Kokkos::resize(TargetPids, TargetNumNonzeros);
1466 }
1467 Kokkos::deep_copy(execution_space(), TargetPids, -1);
1468
1469 // Grab pointers for sourceMatrix
1470 auto local_col_map = sourceMatrix.getColMap()->getLocalMap();
1471
1472 tm = Teuchos::rcp(new Tpetra::Details::ProfilingRegion("Tpetra::Details::unpackAndCombineIntoCrsArrays_new: create mirror views from inputs"));
1473 // Convert input arrays to Kokkos::Views
1474 DT outputDevice;
1475
1476 auto src_pids_d =
1478 SourcePids.size(), true, "src_pids");
1479
1480 tm = Teuchos::null;
1481
1482 size_t bytes_per_value = 0;
1484 // assume that ST is default constructible
1485 bytes_per_value = PackTraits<ST>::packValueCount(ST());
1486 } else {
1487 // Since the packed data come from the source matrix, we can use the source
1488 // matrix to get the number of bytes per Scalar value stored in the matrix.
1489 // This assumes that all Scalar values in the source matrix require the same
1490 // number of bytes. If the source matrix has no entries on the calling
1491 // process, then we hope that some process does have some idea how big
1492 // a Scalar value is. Of course, if no processes have any entries, then no
1493 // values should be packed (though this does assume that in our packing
1494 // scheme, rows with zero entries take zero bytes).
1495 size_t bytes_per_value_l = 0;
1496 if (local_matrix.values.extent(0) > 0) {
1497 const ST& val = local_matrix.values(0);
1499 } else {
1500 const ST& val = crs_vals_d(0);
1502 }
1503 Teuchos::reduceAll<int, size_t>(*(sourceMatrix.getComm()),
1504 Teuchos::REDUCE_MAX,
1506 outArg(bytes_per_value));
1507 }
1508
1509 tm = Teuchos::rcp(new Tpetra::Details::ProfilingRegion("Tpetra::Details::unpackAndCombineIntoCrsArrays_new: unpackAndCombineIntoCrsArrays"));
1510 UnpackAndCombineCrsMatrixImpl::unpackAndCombineIntoCrsArrays(
1511 local_matrix, local_col_map, import_lids_d, imports_d,
1515 bytes_per_value);
1516 tm = Teuchos::null;
1517
1518 // Copy outputs back to host
1519 tm = Teuchos::rcp(new Tpetra::Details::ProfilingRegion("Tpetra::Details::unpackAndCombineIntoCrsArrays_new: copy back to host"));
1520
1521 Kokkos::parallel_for(
1522 "setLocalEntriesToPID", Kokkos::RangePolicy<typename DT::execution_space>(0, TargetPids.size()), KOKKOS_LAMBDA(const size_t i) {
1523 if (TargetPids(i) == -1) TargetPids(i) = MyTargetPID;
1524 });
1525
1526} // unpackAndCombineIntoCrsArrays
1527
1528template <typename Scalar, typename LocalOrdinal, typename GlobalOrdinal, typename Node>
1531 const Kokkos::View<LocalOrdinal const*,
1532 Kokkos::Device<typename Node::device_type::execution_space,
1533 Tpetra::Details::DefaultTypes::comm_buffer_memory_space<typename Node::device_type>>
1535 ,
1536 void, void
1537#endif
1538 >
1540 const Kokkos::View<const char*,
1541 Kokkos::Device<typename Node::device_type::execution_space,
1542 Tpetra::Details::DefaultTypes::comm_buffer_memory_space<typename Node::device_type>>
1544 ,
1545 void, void
1546#endif
1547 >
1548 imports_d,
1549 const Kokkos::View<const size_t*,
1550 Kokkos::Device<typename Node::device_type::execution_space,
1551 Tpetra::Details::DefaultTypes::comm_buffer_memory_space<typename Node::device_type>>
1553 ,
1554 void, void
1555#endif
1556 >
1558 const size_t numSameIDs,
1559 const Kokkos::View<LocalOrdinal const*,
1560 Kokkos::Device<typename Node::device_type::execution_space,
1561 Tpetra::Details::DefaultTypes::comm_buffer_memory_space<typename Node::device_type>>
1563 ,
1564 void, void
1565#endif
1566 >
1568 const Kokkos::View<LocalOrdinal const*,
1569 Kokkos::Device<typename Node::device_type::execution_space,
1570 Tpetra::Details::DefaultTypes::comm_buffer_memory_space<typename Node::device_type>>
1572 ,
1573 void, void
1574#endif
1575 >
1577 size_t TargetNumRows,
1578 const int MyTargetPID,
1579 Teuchos::ArrayRCP<size_t>& CRS_rowptr,
1580 Teuchos::ArrayRCP<GlobalOrdinal>& CRS_colind,
1581 Teuchos::ArrayRCP<Scalar>& CRS_vals,
1582 const Teuchos::ArrayView<const int>& SourcePids,
1583 Teuchos::Array<int>& TargetPids) {
1584 using execution_space = typename Node::execution_space;
1586
1587 using Kokkos::deep_copy;
1588 using Kokkos::View;
1589
1590 using Teuchos::ArrayView;
1591 using Teuchos::outArg;
1592 using Teuchos::REDUCE_MAX;
1593 using Teuchos::reduceAll;
1594
1595 typedef typename Node::device_type DT;
1596
1598 typedef typename matrix_type::impl_scalar_type ST;
1599
1600 const char prefix[] = "Tpetra::Details::unpackAndCombineIntoCrsArrays_new: ";
1601 Teuchos::RCP<Tpetra::Details::ProfilingRegion> tm;
1602
1603 using Kokkos::MemoryUnmanaged;
1604
1605 TEUCHOS_TEST_FOR_EXCEPTION(permute_to_lids_d.size() != permute_from_lids_d.size(), std::invalid_argument,
1606 prefix << "permute_to_lids_d.size() = " << permute_to_lids_d.size() << " != "
1607 "permute_from_lids_d.size() = "
1608 << permute_from_lids_d.size() << ".");
1609 // FIXME (mfh 26 Jan 2015) If there are no entries on the calling
1610 // process, then the matrix is neither locally nor globally indexed.
1611 const bool locallyIndexed = sourceMatrix.isLocallyIndexed();
1612 TEUCHOS_TEST_FOR_EXCEPTION(!locallyIndexed, std::invalid_argument, prefix << "The input "
1613 "CrsMatrix 'sourceMatrix' must be locally indexed.");
1614 TEUCHOS_TEST_FOR_EXCEPTION(((size_t)import_lids_d.size()) != num_packets_per_lid_d.size(), std::invalid_argument,
1615 prefix << "import_lids_d.size() = " << import_lids_d.size() << " != "
1616 "num_packets_per_lid_d.size() = "
1617 << num_packets_per_lid_d.size() << ".");
1618
1619 auto local_matrix = sourceMatrix.getLocalMatrixDevice();
1620
1621 // TargetNumNonzeros is number of nonzeros in local matrix.
1622 tm = Teuchos::rcp(new Tpetra::Details::ProfilingRegion("Tpetra::Details::unpackAndCombineIntoCrsArrays_new: unpackAndCombineWithOwningPIDsCount"));
1623 size_t TargetNumNonzeros =
1624 UnpackAndCombineCrsMatrixImpl::unpackAndCombineWithOwningPIDsCount(
1625 local_matrix, permute_from_lids_d, imports_d,
1626 num_packets_per_lid_d, numSameIDs);
1627 tm = Teuchos::null;
1628
1629 tm = Teuchos::rcp(new Tpetra::Details::ProfilingRegion("Tpetra::Details::unpackAndCombineIntoCrsArrays_new: resize CRS pointers"));
1630 CRS_rowptr.resize(TargetNumRows + 1);
1633 Teuchos::ArrayRCP<ST> const& CRS_vals_impl_scalar_type = Teuchos::arcp_reinterpret_cast<ST>(CRS_vals);
1634 tm = Teuchos::null;
1635
1637 permute_to_lids_d.size() != permute_from_lids_d.size(), std::invalid_argument,
1638 prefix << "permuteToLIDs.size() = " << permute_to_lids_d.size()
1639 << "!= permute_from_lids_d.size() = " << permute_from_lids_d.size() << ".");
1640
1641 // Preseed TargetPids with -1 for local
1642 if (static_cast<size_t>(TargetPids.size()) != TargetNumNonzeros) {
1644 }
1645 TargetPids.assign(TargetNumNonzeros, -1);
1646
1647 // Grab pointers for sourceMatrix
1648 auto local_col_map = sourceMatrix.getColMap()->getLocalMap();
1649
1650 tm = Teuchos::rcp(new Tpetra::Details::ProfilingRegion("Tpetra::Details::unpackAndCombineIntoCrsArrays_new: create mirror views from inputs"));
1651 // Convert input arrays to Kokkos::Views
1652 DT outputDevice;
1653
1654 auto crs_rowptr_d =
1656 CRS_rowptr.size(), true, "crs_rowptr");
1657
1658 auto crs_colind_d =
1660 CRS_colind.size(), true, "crs_colidx");
1661#ifdef HAVE_TPETRA_INST_COMPLEX_DOUBLE
1662 static_assert(!std::is_same<
1663 typename std::remove_const<
1664 typename std::decay<
1665 decltype(CRS_vals_impl_scalar_type)>::type::value_type>::type,
1666 std::complex<double>>::value,
1667 "CRS_vals::value_type is std::complex<double>; this should never happen"
1668 ", since std::complex does not work in Kokkos::View objects.");
1669#endif // HAVE_TPETRA_INST_COMPLEX_DOUBLE
1670
1671 auto crs_vals_d =
1673 CRS_vals_impl_scalar_type.size(), true, "crs_vals");
1674
1675#ifdef HAVE_TPETRA_INST_COMPLEX_DOUBLE
1676 static_assert(!std::is_same<
1677 typename decltype(crs_vals_d)::non_const_value_type,
1678 std::complex<double>>::value,
1679 "crs_vals_d::non_const_value_type is std::complex<double>; this should "
1680 "never happen, since std::complex does not work in Kokkos::View objects.");
1681#endif // HAVE_TPETRA_INST_COMPLEX_DOUBLE
1682
1683 auto src_pids_d =
1685 SourcePids.size(), true, "src_pids");
1686
1687 auto tgt_pids_d =
1689 TargetPids.size(), true, "tgt_pids");
1690
1691 tm = Teuchos::null;
1692
1693 size_t bytes_per_value = 0;
1695 // assume that ST is default constructible
1696 bytes_per_value = PackTraits<ST>::packValueCount(ST());
1697 } else {
1698 // Since the packed data come from the source matrix, we can use the source
1699 // matrix to get the number of bytes per Scalar value stored in the matrix.
1700 // This assumes that all Scalar values in the source matrix require the same
1701 // number of bytes. If the source matrix has no entries on the calling
1702 // process, then we hope that some process does have some idea how big
1703 // a Scalar value is. Of course, if no processes have any entries, then no
1704 // values should be packed (though this does assume that in our packing
1705 // scheme, rows with zero entries take zero bytes).
1706 size_t bytes_per_value_l = 0;
1707 if (local_matrix.values.extent(0) > 0) {
1708 const ST& val = local_matrix.values(0);
1710 } else {
1711 const ST& val = crs_vals_d(0);
1713 }
1714 Teuchos::reduceAll<int, size_t>(*(sourceMatrix.getComm()),
1715 Teuchos::REDUCE_MAX,
1717 outArg(bytes_per_value));
1718 }
1719
1720#ifdef HAVE_TPETRA_INST_COMPLEX_DOUBLE
1721 static_assert(!std::is_same<
1722 typename decltype(crs_vals_d)::non_const_value_type,
1723 std::complex<double>>::value,
1724 "crs_vals_d::non_const_value_type is std::complex<double>; this should "
1725 "never happen, since std::complex does not work in Kokkos::View objects.");
1726#endif // HAVE_TPETRA_INST_COMPLEX_DOUBLE
1727
1728 tm = Teuchos::rcp(new Tpetra::Details::ProfilingRegion("Tpetra::Details::unpackAndCombineIntoCrsArrays_new: unpackAndCombineIntoCrsArrays"));
1729 UnpackAndCombineCrsMatrixImpl::unpackAndCombineIntoCrsArrays(
1730 local_matrix, local_col_map, import_lids_d, imports_d,
1734 bytes_per_value);
1735 tm = Teuchos::null;
1736
1737 // Copy outputs back to host
1738 tm = Teuchos::rcp(new Tpetra::Details::ProfilingRegion("Tpetra::Details::unpackAndCombineIntoCrsArrays_new: copy back to host"));
1739 typename decltype(crs_rowptr_d)::host_mirror_type crs_rowptr_h(
1740 CRS_rowptr.getRawPtr(), CRS_rowptr.size());
1741 // DEEP_COPY REVIEW - DEVICE-TO-HOSTMIRROR
1742 deep_copy(execution_space(), crs_rowptr_h, crs_rowptr_d);
1743
1744 typename decltype(crs_colind_d)::host_mirror_type crs_colind_h(
1745 CRS_colind.getRawPtr(), CRS_colind.size());
1746 // DEEP_COPY REVIEW - DEVICE-TO-HOSTMIRROR
1747 deep_copy(execution_space(), crs_colind_h, crs_colind_d);
1748
1749 typename decltype(crs_vals_d)::host_mirror_type crs_vals_h(
1751 // DEEP_COPY REVIEW - DEVICE-TO-HOSTMIRROR
1752 deep_copy(execution_space(), crs_vals_h, crs_vals_d);
1753
1754 typename decltype(tgt_pids_d)::host_mirror_type tgt_pids_h(
1755 TargetPids.getRawPtr(), TargetPids.size());
1756 // DEEP_COPY REVIEW - DEVICE-TO-HOSTMIRROR
1757 deep_copy(execution_space(), tgt_pids_h, tgt_pids_d);
1758
1759} // unpackAndCombineIntoCrsArrays
1760
1761} // namespace Details
1762} // namespace Tpetra
1763
1764#define TPETRA_DETAILS_UNPACKCRSMATRIXANDCOMBINE_INSTANT_KOKKOS_DEPRECATED_CODE_4_ON(ST, LO, GO, NT) \
1765 template void \
1766 Details::unpackCrsMatrixAndCombine<ST, LO, GO, NT>( \
1767 const CrsMatrix<ST, LO, GO, NT>&, \
1768 const Teuchos::ArrayView<const char>&, \
1769 const Teuchos::ArrayView<const size_t>&, \
1770 const Teuchos::ArrayView<const LO>&, \
1771 size_t, \
1772 CombineMode); \
1773 template size_t \
1774 Details::unpackAndCombineWithOwningPIDsCount<ST, LO, GO, NT>( \
1775 const CrsMatrix<ST, LO, GO, NT>&, \
1776 const Teuchos::ArrayView<const LO>&, \
1777 const Teuchos::ArrayView<const char>&, \
1778 const Teuchos::ArrayView<const size_t>&, \
1779 size_t, \
1780 CombineMode, \
1781 size_t, \
1782 const Teuchos::ArrayView<const LO>&, \
1783 const Teuchos::ArrayView<const LO>&); \
1784 template void \
1785 Details::unpackCrsMatrixAndCombineNew<ST, LO, GO, NT>( \
1786 const CrsMatrix<ST, LO, GO, NT>&, \
1787 Kokkos::DualView<char*, typename DistObject<char, LO, GO, NT>::buffer_device_type>, \
1788 Kokkos::DualView<size_t*, typename DistObject<char, LO, GO, NT>::buffer_device_type>, \
1789 const Kokkos::DualView<const LO*, typename DistObject<char, LO, GO, NT>::buffer_device_type>&, \
1790 const size_t, \
1791 const CombineMode); \
1792 template void \
1793 Details::unpackAndCombineIntoCrsArrays<ST, LO, GO, NT>( \
1794 const CrsMatrix<ST, LO, GO, NT>&, \
1795 const Kokkos::View<LO const*, \
1796 Kokkos::Device<typename NT::device_type::execution_space, \
1797 Tpetra::Details::DefaultTypes::comm_buffer_memory_space<typename NT::device_type>>, \
1798 void, void>, \
1799 const Kokkos::View<const char*, \
1800 Kokkos::Device<typename NT::device_type::execution_space, \
1801 Tpetra::Details::DefaultTypes::comm_buffer_memory_space<typename NT::device_type>>, \
1802 void, void>, \
1803 const Kokkos::View<const size_t*, \
1804 Kokkos::Device<typename NT::device_type::execution_space, \
1805 Tpetra::Details::DefaultTypes::comm_buffer_memory_space<typename NT::device_type>>, \
1806 void, void>, \
1807 const size_t, \
1808 const Kokkos::View<LO const*, \
1809 Kokkos::Device<typename NT::device_type::execution_space, \
1810 Tpetra::Details::DefaultTypes::comm_buffer_memory_space<typename NT::device_type>>, \
1811 void, void>, \
1812 const Kokkos::View<LO const*, \
1813 Kokkos::Device<typename NT::device_type::execution_space, \
1814 Tpetra::Details::DefaultTypes::comm_buffer_memory_space<typename NT::device_type>>, \
1815 void, void>, \
1816 size_t, \
1817 const int, \
1818 Kokkos::View<size_t*, typename NT::device_type>&, \
1819 Kokkos::View<GO*, typename NT::device_type>&, \
1820 Kokkos::View<typename CrsMatrix<ST, LO, GO, NT>::impl_scalar_type*, typename NT::device_type>&, \
1821 const Teuchos::ArrayView<const int>&, \
1822 Kokkos::View<int*, typename NT::device_type>&); \
1823 template void \
1824 Details::unpackAndCombineIntoCrsArrays<ST, LO, GO, NT>( \
1825 const CrsMatrix<ST, LO, GO, NT>&, \
1826 const Kokkos::View<LO const*, \
1827 Kokkos::Device<typename NT::device_type::execution_space, \
1828 Tpetra::Details::DefaultTypes::comm_buffer_memory_space<typename NT::device_type>>, \
1829 void, void>, \
1830 const Kokkos::View<const char*, \
1831 Kokkos::Device<typename NT::device_type::execution_space, \
1832 Tpetra::Details::DefaultTypes::comm_buffer_memory_space<typename NT::device_type>>, \
1833 void, void>, \
1834 const Kokkos::View<const size_t*, \
1835 Kokkos::Device<typename NT::device_type::execution_space, \
1836 Tpetra::Details::DefaultTypes::comm_buffer_memory_space<typename NT::device_type>>, \
1837 void, void>, \
1838 const size_t, \
1839 const Kokkos::View<LO const*, \
1840 Kokkos::Device<typename NT::device_type::execution_space, \
1841 Tpetra::Details::DefaultTypes::comm_buffer_memory_space<typename NT::device_type>>, \
1842 void, void>, \
1843 const Kokkos::View<LO const*, \
1844 Kokkos::Device<typename NT::device_type::execution_space, \
1845 Tpetra::Details::DefaultTypes::comm_buffer_memory_space<typename NT::device_type>>, \
1846 void, void>, \
1847 size_t, \
1848 const int, \
1849 Teuchos::ArrayRCP<size_t>&, \
1850 Teuchos::ArrayRCP<GO>&, \
1851 Teuchos::ArrayRCP<ST>&, \
1852 const Teuchos::ArrayView<const int>&, \
1853 Teuchos::Array<int>&);
1854
1855#define TPETRA_DETAILS_UNPACKCRSMATRIXANDCOMBINE_INSTANT_KOKKOS_DEPRECATED_CODE_4_OFF(ST, LO, GO, NT) \
1856 template void \
1857 Details::unpackCrsMatrixAndCombine<ST, LO, GO, NT>( \
1858 const CrsMatrix<ST, LO, GO, NT>&, \
1859 const Teuchos::ArrayView<const char>&, \
1860 const Teuchos::ArrayView<const size_t>&, \
1861 const Teuchos::ArrayView<const LO>&, \
1862 size_t, \
1863 CombineMode); \
1864 template size_t \
1865 Details::unpackAndCombineWithOwningPIDsCount<ST, LO, GO, NT>( \
1866 const CrsMatrix<ST, LO, GO, NT>&, \
1867 const Teuchos::ArrayView<const LO>&, \
1868 const Teuchos::ArrayView<const char>&, \
1869 const Teuchos::ArrayView<const size_t>&, \
1870 size_t, \
1871 CombineMode, \
1872 size_t, \
1873 const Teuchos::ArrayView<const LO>&, \
1874 const Teuchos::ArrayView<const LO>&); \
1875 template void \
1876 Details::unpackCrsMatrixAndCombineNew<ST, LO, GO, NT>( \
1877 const CrsMatrix<ST, LO, GO, NT>&, \
1878 Kokkos::DualView<char*, typename DistObject<char, LO, GO, NT>::buffer_device_type>, \
1879 Kokkos::DualView<size_t*, typename DistObject<char, LO, GO, NT>::buffer_device_type>, \
1880 const Kokkos::DualView<const LO*, typename DistObject<char, LO, GO, NT>::buffer_device_type>&, \
1881 const size_t, \
1882 const CombineMode); \
1883 template void \
1884 Details::unpackAndCombineIntoCrsArrays<ST, LO, GO, NT>( \
1885 const CrsMatrix<ST, LO, GO, NT>&, \
1886 const Kokkos::View<LO const*, \
1887 Kokkos::Device<typename NT::device_type::execution_space, \
1888 Tpetra::Details::DefaultTypes::comm_buffer_memory_space<typename NT::device_type>>>, \
1889 const Kokkos::View<const char*, \
1890 Kokkos::Device<typename NT::device_type::execution_space, \
1891 Tpetra::Details::DefaultTypes::comm_buffer_memory_space<typename NT::device_type>>>, \
1892 const Kokkos::View<const size_t*, \
1893 Kokkos::Device<typename NT::device_type::execution_space, \
1894 Tpetra::Details::DefaultTypes::comm_buffer_memory_space<typename NT::device_type>>>, \
1895 const size_t, \
1896 const Kokkos::View<LO const*, \
1897 Kokkos::Device<typename NT::device_type::execution_space, \
1898 Tpetra::Details::DefaultTypes::comm_buffer_memory_space<typename NT::device_type>>>, \
1899 const Kokkos::View<LO const*, \
1900 Kokkos::Device<typename NT::device_type::execution_space, \
1901 Tpetra::Details::DefaultTypes::comm_buffer_memory_space<typename NT::device_type>>>, \
1902 size_t, \
1903 const int, \
1904 Kokkos::View<size_t*, typename NT::device_type>&, \
1905 Kokkos::View<GO*, typename NT::device_type>&, \
1906 Kokkos::View<typename CrsMatrix<ST, LO, GO, NT>::impl_scalar_type*, typename NT::device_type>&, \
1907 const Teuchos::ArrayView<const int>&, \
1908 Kokkos::View<int*, typename NT::device_type>&); \
1909 template void \
1910 Details::unpackAndCombineIntoCrsArrays<ST, LO, GO, NT>( \
1911 const CrsMatrix<ST, LO, GO, NT>&, \
1912 const Kokkos::View<LO const*, \
1913 Kokkos::Device<typename NT::device_type::execution_space, \
1914 Tpetra::Details::DefaultTypes::comm_buffer_memory_space<typename NT::device_type>>>, \
1915 const Kokkos::View<const char*, \
1916 Kokkos::Device<typename NT::device_type::execution_space, \
1917 Tpetra::Details::DefaultTypes::comm_buffer_memory_space<typename NT::device_type>>>, \
1918 const Kokkos::View<const size_t*, \
1919 Kokkos::Device<typename NT::device_type::execution_space, \
1920 Tpetra::Details::DefaultTypes::comm_buffer_memory_space<typename NT::device_type>>>, \
1921 const size_t, \
1922 const Kokkos::View<LO const*, \
1923 Kokkos::Device<typename NT::device_type::execution_space, \
1924 Tpetra::Details::DefaultTypes::comm_buffer_memory_space<typename NT::device_type>>>, \
1925 const Kokkos::View<LO const*, \
1926 Kokkos::Device<typename NT::device_type::execution_space, \
1927 Tpetra::Details::DefaultTypes::comm_buffer_memory_space<typename NT::device_type>>>, \
1928 size_t, \
1929 const int, \
1930 Teuchos::ArrayRCP<size_t>&, \
1931 Teuchos::ArrayRCP<GO>&, \
1932 Teuchos::ArrayRCP<ST>&, \
1933 const Teuchos::ArrayView<const int>&, \
1934 Teuchos::Array<int>&);
1935
1936#ifdef KOKKOS_ENABLE_DEPRECATED_CODE_4
1937#define TPETRA_DETAILS_UNPACKCRSMATRIXANDCOMBINE_INSTANT(ST, LO, GO, NT) \
1938 TPETRA_DETAILS_UNPACKCRSMATRIXANDCOMBINE_INSTANT_KOKKOS_DEPRECATED_CODE_4_ON(ST, LO, GO, NT)
1939#else
1940#define TPETRA_DETAILS_UNPACKCRSMATRIXANDCOMBINE_INSTANT(ST, LO, GO, NT) \
1941 TPETRA_DETAILS_UNPACKCRSMATRIXANDCOMBINE_INSTANT_KOKKOS_DEPRECATED_CODE_4_OFF(ST, LO, GO, NT)
1942#endif
1943
1944#endif // TPETRA_DETAILS_UNPACKCRSMATRIXANDCOMBINE_DEF_HPP
Declaration of the Tpetra::CrsMatrix class.
Import KokkosSparse::OrdinalTraits, a traits class for "invalid" (flag) values of integer types,...
Declaration and generic definition of traits class that tells Tpetra::CrsMatrix how to pack and unpac...
Declaration and definition of Tpetra::Details::castAwayConstDualView, an implementation detail of Tpe...
Declare and define the functions Tpetra::Details::computeOffsetsFromCounts and Tpetra::computeOffsets...
Functions that wrap Kokkos::create_mirror_view, in order to avoid deep copies when not necessary,...
Declaration and definition of Tpetra::Details::getEntryOnHost.
size_t compute_total_num_entries(const Kokkos::View< const size_t *, BDT > &num_packets_per_lid, const Kokkos::View< const size_t *, DT > &offsets, const Kokkos::View< const char *, BDT > &imports)
Total number of entries in any row of the packed matrix.
void unpackAndCombineIntoCrsMatrix(const LocalMatrix &local_matrix, const LocalMap &local_map, const Kokkos::View< const char *, BufferDeviceType > &imports, const Kokkos::View< const size_t *, BufferDeviceType > &num_packets_per_lid, const typename PackTraits< typename LocalMap::local_ordinal_type >::input_array_type import_lids, const Tpetra::CombineMode combine_mode)
Perform the unpack operation for the matrix.
size_t compute_maximum_num_entries(const Kokkos::View< const size_t *, BDT > &num_packets_per_lid, const Kokkos::View< const size_t *, DT > &offsets, const Kokkos::View< const char *, BDT > &imports)
Maximum number of entries in any row of the packed matrix.
bool compute_batch_info(const View1 &batches_per_lid, View2 &batch_info)
Compute the index and batch number associated with each batch.
KokkosSparse::CrsMatrix< impl_scalar_type, local_ordinal_type, device_type, void, typename local_graph_device_type::size_type > local_matrix_device_type
The specialization of Kokkos::CrsMatrix that represents the part of the sparse matrix on each MPI pro...
typename row_matrix_type::impl_scalar_type impl_scalar_type
The type used internally in place of Scalar.
Struct that holds views of the contents of a CrsMatrix.
static size_t hierarchicalUnpackBatchSize()
Size of batch for hierarchical unpacking.
static size_t hierarchicalUnpackTeamSize()
Size of team for hierarchical unpacking.
"Local" part of Map suitable for Kokkos kernels.
KOKKOS_INLINE_FUNCTION LocalOrdinal getLocalElement(const GlobalOrdinal globalIndex) const
Get the local index corresponding to the given global index. (device only)
LocalOrdinal local_ordinal_type
The type of local indices.
GlobalOrdinal global_ordinal_type
The type of global indices.
DeviceType device_type
The device type.
Kokkos::parallel_reduce functor to determine the number of entries (to unpack) in a KokkosSparse::Crs...
Kokkos::Device< typename device_type::execution_space, buffer_memory_space > buffer_device_type
Kokkos::Device specialization for communication buffers.
Implementation details of Tpetra.
void unpackAndCombineIntoCrsArrays(const CrsGraph< LO, GO, NT > &sourceGraph, const Teuchos::ArrayView< const LO > &importLIDs, const Teuchos::ArrayView< const typename CrsGraph< LO, GO, NT >::packet_type > &imports, const Teuchos::ArrayView< const size_t > &numPacketsPerLID, const size_t constantNumPackets, const CombineMode combineMode, const size_t numSameIDs, const Teuchos::ArrayView< const LO > &permuteToLIDs, const Teuchos::ArrayView< const LO > &permuteFromLIDs, size_t TargetNumRows, size_t TargetNumNonzeros, const int MyTargetPID, const Teuchos::ArrayView< size_t > &CRS_rowptr, const Teuchos::ArrayView< GO > &CRS_colind, const Teuchos::ArrayView< const int > &SourcePids, Teuchos::Array< int > &TargetPids)
unpackAndCombineIntoCrsArrays
Impl::CreateMirrorViewFromUnmanagedHostArray< ValueType, OutputDeviceType >::output_view_type create_mirror_view_from_raw_host_array(const OutputDeviceType &, ValueType *inPtr, const size_t inSize, const bool copy=true, const char label[]="")
Variant of Kokkos::create_mirror_view that takes a raw host 1-d array as input.
size_t unpackAndCombineWithOwningPIDsCount(const CrsGraph< LO, GO, NT > &sourceGraph, const Teuchos::ArrayView< const LO > &importLIDs, const Teuchos::ArrayView< const typename CrsGraph< LO, GO, NT >::packet_type > &imports, const Teuchos::ArrayView< const size_t > &numPacketsPerLID, size_t constantNumPackets, CombineMode combineMode, size_t numSameIDs, const Teuchos::ArrayView< const LO > &permuteToLIDs, const Teuchos::ArrayView< const LO > &permuteFromLIDs)
Special version of Tpetra::Details::unpackCrsGraphAndCombine that also unpacks owning process ranks.
void unpackCrsMatrixAndCombine(const CrsMatrix< ST, LO, GO, NT > &sourceMatrix, const Teuchos::ArrayView< const char > &imports, const Teuchos::ArrayView< const size_t > &numPacketsPerLID, const Teuchos::ArrayView< const LO > &importLIDs, size_t constantNumPackets, CombineMode combineMode)
Unpack the imported column indices and values, and combine into matrix.
OffsetsViewType::non_const_value_type computeOffsetsFromCounts(const ExecutionSpace &execSpace, const OffsetsViewType &ptr, const CountsViewType &counts)
Compute offsets from counts.
Namespace Tpetra contains the class and methods constituting the Tpetra library.
void deep_copy(MultiVector< DS, DL, DG, DN > &dst, const MultiVector< SS, SL, SG, SN > &src)
Copy the contents of the MultiVector src into dst.
CombineMode
Rule for combining data in an Import or Export.
@ REPLACE
Replace existing values with new values.
@ ADD
Sum new values.
@ ABSMAX
Replace old value with maximum of magnitudes of old and new values.
@ INSERT
Insert new values that don't currently exist.
Traits class for packing / unpacking data of type T.
static KOKKOS_INLINE_FUNCTION Kokkos::pair< int, size_t > unpackArray(value_type outBuf[], const char inBuf[], const size_t numEnt)
Unpack numEnt value_type entries from the given input buffer of bytes, to the given output buffer of ...
static KOKKOS_INLINE_FUNCTION size_t unpackValue(T &outVal, const char inBuf[])
Unpack the given value from the given output buffer.
Kokkos::View< value_type *, Kokkos::AnonymousSpace > output_array_type
The type of an output array of value_type.
static KOKKOS_INLINE_FUNCTION size_t packValueCount(const T &)
Number of bytes required to pack or unpack the given value of type value_type.
Kokkos::View< const value_type *, Kokkos::AnonymousSpace > input_array_type
The type of an input array of value_type.