10#ifndef TPETRA_DETAILS_PACKCRSMATRIX_DEF_HPP
11#define TPETRA_DETAILS_PACKCRSMATRIX_DEF_HPP
13#include "TpetraCore_config.h"
14#include "Teuchos_Array.hpp"
15#include "Teuchos_ArrayView.hpp"
59namespace PackCrsMatrixImpl {
67template <
class OutputOffsetsViewType,
69 class InputOffsetsViewType,
70 class InputLocalRowIndicesViewType,
71 class InputLocalRowPidsViewType,
73#ifdef HAVE_TPETRA_DEBUG
79class NumPacketsAndOffsetsFunctor {
81 typedef typename OutputOffsetsViewType::non_const_value_type output_offset_type;
82 typedef typename CountsViewType::non_const_value_type count_type;
83 typedef typename InputOffsetsViewType::non_const_value_type input_offset_type;
84 typedef typename InputLocalRowIndicesViewType::non_const_value_type local_row_index_type;
85 typedef typename InputLocalRowPidsViewType::non_const_value_type local_row_pid_type;
87 typedef typename OutputOffsetsViewType::device_type device_type;
88 static_assert(std::is_same<
typename CountsViewType::device_type::execution_space,
89 typename device_type::execution_space>::value,
90 "OutputOffsetsViewType and CountsViewType must have the same execution space.");
91 static_assert(Kokkos::is_view<OutputOffsetsViewType>::value,
92 "OutputOffsetsViewType must be a Kokkos::View.");
93 static_assert(std::is_same<typename OutputOffsetsViewType::value_type, output_offset_type>::value,
94 "OutputOffsetsViewType must be a nonconst Kokkos::View.");
95 static_assert(std::is_integral<output_offset_type>::value,
96 "The type of each entry of OutputOffsetsViewType must be a built-in integer type.");
97 static_assert(Kokkos::is_view<CountsViewType>::value,
98 "CountsViewType must be a Kokkos::View.");
99 static_assert(std::is_same<typename CountsViewType::value_type, output_offset_type>::value,
100 "CountsViewType must be a nonconst Kokkos::View.");
101 static_assert(std::is_integral<count_type>::value,
102 "The type of each entry of CountsViewType must be a built-in integer type.");
103 static_assert(Kokkos::is_view<InputOffsetsViewType>::value,
104 "InputOffsetsViewType must be a Kokkos::View.");
105 static_assert(std::is_integral<input_offset_type>::value,
106 "The type of each entry of InputOffsetsViewType must be a built-in integer type.");
107 static_assert(Kokkos::is_view<InputLocalRowIndicesViewType>::value,
108 "InputLocalRowIndicesViewType must be a Kokkos::View.");
109 static_assert(std::is_integral<local_row_index_type>::value,
110 "The type of each entry of InputLocalRowIndicesViewType must be a built-in integer type.");
112 NumPacketsAndOffsetsFunctor(
const OutputOffsetsViewType& outputOffsets,
113 const CountsViewType& counts,
114 const InputOffsetsViewType& rowOffsets,
115 const InputLocalRowIndicesViewType& lclRowInds,
116 const InputLocalRowPidsViewType& lclRowPids,
117 const count_type sizeOfLclCount,
118 const count_type sizeOfGblColInd,
119 const count_type sizeOfPid,
120 const count_type sizeOfValue)
121 : outputOffsets_(outputOffsets)
123 , rowOffsets_(rowOffsets)
124 , lclRowInds_(lclRowInds)
125 , lclRowPids_(lclRowPids)
126 , sizeOfLclCount_(sizeOfLclCount)
127 , sizeOfGblColInd_(sizeOfGblColInd)
128 , sizeOfPid_(sizeOfPid)
129 , sizeOfValue_(sizeOfValue)
133 const size_t numRowsToPack =
static_cast<size_t>(lclRowInds_.extent(0));
135 if (numRowsToPack !=
static_cast<size_t>(counts_.extent(0))) {
136 std::ostringstream os;
137 os <<
"lclRowInds.extent(0) = " << numRowsToPack
138 <<
" != counts.extent(0) = " << counts_.extent(0)
140 TEUCHOS_TEST_FOR_EXCEPTION(
true, std::invalid_argument, os.str());
142 if (
static_cast<size_t>(numRowsToPack + 1) !=
143 static_cast<size_t>(outputOffsets_.extent(0))) {
144 std::ostringstream os;
145 os <<
"lclRowInds.extent(0) + 1 = " << (numRowsToPack + 1)
146 <<
" != outputOffsets.extent(0) = " << outputOffsets_.extent(0)
148 TEUCHOS_TEST_FOR_EXCEPTION(
true, std::invalid_argument, os.str());
153 KOKKOS_INLINE_FUNCTION
void
154 operator()(
const local_row_index_type& curInd,
155 output_offset_type& update,
156 const bool final)
const {
158 if (curInd <
static_cast<local_row_index_type
>(0)) {
166 if (curInd >=
static_cast<local_row_index_type
>(outputOffsets_.extent(0))) {
171 outputOffsets_(curInd) = update;
174 if (curInd <
static_cast<local_row_index_type
>(counts_.extent(0))) {
175 const auto lclRow = lclRowInds_(curInd);
176 if (
static_cast<size_t>(lclRow + 1) >=
static_cast<size_t>(rowOffsets_.extent(0)) ||
177 static_cast<local_row_index_type
>(lclRow) <
static_cast<local_row_index_type
>(0)) {
185 const count_type count =
186 static_cast<count_type
>(rowOffsets_(lclRow + 1) - rowOffsets_(lclRow));
192 const count_type numBytes = (count == 0) ?
static_cast<count_type
>(0) : sizeOfLclCount_ + count * (sizeOfGblColInd_ + (lclRowPids_.size() > 0 ? sizeOfPid_ : 0) + sizeOfValue_);
195 counts_(curInd) = numBytes;
207 auto error_h = Kokkos::create_mirror_view(error_);
212 Kokkos::deep_copy(error_h, error_);
217 OutputOffsetsViewType outputOffsets_;
218 CountsViewType counts_;
219 typename InputOffsetsViewType::const_type rowOffsets_;
220 typename InputLocalRowIndicesViewType::const_type lclRowInds_;
221 typename InputLocalRowPidsViewType::const_type lclRowPids_;
222 count_type sizeOfLclCount_;
223 count_type sizeOfGblColInd_;
224 count_type sizeOfPid_;
225 count_type sizeOfValue_;
226 Kokkos::View<int, device_type> error_;
238template <
class OutputOffsetsViewType,
239 class CountsViewType,
240 class InputOffsetsViewType,
241 class InputLocalRowIndicesViewType,
242 class InputLocalRowPidsViewType>
243typename CountsViewType::non_const_value_type
245 const CountsViewType& counts,
246 const InputOffsetsViewType& rowOffsets,
247 const InputLocalRowIndicesViewType& lclRowInds,
248 const InputLocalRowPidsViewType& lclRowPids,
249 const typename CountsViewType::non_const_value_type sizeOfLclCount,
250 const typename CountsViewType::non_const_value_type sizeOfGblColInd,
251 const typename CountsViewType::non_const_value_type sizeOfPid,
252 const typename CountsViewType::non_const_value_type sizeOfValue) {
254 CountsViewType,
typename InputOffsetsViewType::const_type,
255 typename InputLocalRowIndicesViewType::const_type,
256 typename InputLocalRowPidsViewType::const_type>
258 typedef typename CountsViewType::non_const_value_type count_type;
259 typedef typename OutputOffsetsViewType::size_type size_type;
260 typedef typename OutputOffsetsViewType::execution_space
execution_space;
261 typedef typename functor_type::local_row_index_type LO;
262 typedef Kokkos::RangePolicy<execution_space, LO> range_type;
263 const char prefix[] =
"computeNumPacketsAndOffsets: ";
265 count_type count = 0;
266 const count_type numRowsToPack = lclRowInds.extent(0);
268 if (numRowsToPack == 0) {
271 TEUCHOS_TEST_FOR_EXCEPTION(rowOffsets.extent(0) <=
static_cast<size_type
>(1),
272 std::invalid_argument, prefix <<
"There is at least one row to pack, "
273 "but the matrix has no rows. lclRowInds.extent(0) = "
274 << numRowsToPack <<
", but rowOffsets.extent(0) = " << rowOffsets.extent(0) <<
" <= 1.");
275 TEUCHOS_TEST_FOR_EXCEPTION(outputOffsets.extent(0) !=
276 static_cast<size_type
>(numRowsToPack + 1),
277 std::invalid_argument,
278 prefix <<
"Output dimension does not match number of rows to pack. "
279 <<
"outputOffsets.extent(0) = " << outputOffsets.extent(0)
280 <<
" != lclRowInds.extent(0) + 1 = "
281 <<
static_cast<size_type
>(numRowsToPack + 1) <<
".");
282 TEUCHOS_TEST_FOR_EXCEPTION(counts.extent(0) != numRowsToPack, std::invalid_argument,
283 prefix <<
"counts.extent(0) = " << counts.extent(0)
284 <<
" != numRowsToPack = " << numRowsToPack <<
".");
286 functor_type f(outputOffsets, counts, rowOffsets,
287 lclRowInds, lclRowPids, sizeOfLclCount,
288 sizeOfGblColInd, sizeOfPid, sizeOfValue);
289 Kokkos::parallel_scan(range_type(0, numRowsToPack + 1), f);
292 const int errCode = f.getError();
293 TEUCHOS_TEST_FOR_EXCEPTION(errCode != 0, std::runtime_error, prefix <<
"parallel_scan error code " << errCode <<
" != 0.");
297 for (LO k = 0; k < numRowsToPack; ++k) {
300 if (outputOffsets(numRowsToPack) != total) {
301 if (errStr.get () == NULL) {
302 errStr = std::unique_ptr<std::ostringstream> (
new std::ostringstream ());
304 std::ostringstream& os = *errStr;
306 <<
"outputOffsets(numRowsToPack=" << numRowsToPack <<
") "
307 << outputOffsets(numRowsToPack) <<
" != sum of counts = "
308 << total <<
"." << std::endl;
309 if (numRowsToPack != 0) {
311 if (numRowsToPack <
static_cast<LO
> (10)) {
312 os <<
"outputOffsets: [";
313 for (LO i = 0; i <= numRowsToPack; ++i) {
314 os << outputOffsets(i);
315 if (
static_cast<LO
> (i + 1) <= numRowsToPack) {
319 os <<
"]" << std::endl;
321 for (LO i = 0; i < numRowsToPack; ++i) {
323 if (
static_cast<LO
> (i + 1) < numRowsToPack) {
327 os <<
"]" << std::endl;
330 os <<
"outputOffsets(" << (numRowsToPack-1) <<
") = "
331 << outputOffsets(numRowsToPack-1) <<
"." << std::endl;
334 count = outputOffsets(numRowsToPack);
335 return {
false, errStr};
341 using Tpetra::Details::getEntryOnHost;
342 return static_cast<count_type
>(getEntryOnHost(outputOffsets,
362template <
class ST,
class ColumnMap,
class BufferDeviceType>
364 Kokkos::pair<int, size_t>
366 const Kokkos::View<char*, BufferDeviceType>& exports,
371 const size_t num_ent,
372 const size_t num_bytes_per_value,
373 const bool pack_pids) {
374 using Kokkos::subview;
375 using LO =
typename ColumnMap::local_ordinal_type;
376 using GO =
typename ColumnMap::global_ordinal_type;
377 using return_type = Kokkos::pair<int, size_t>;
381 return return_type(0, 0);
384 const LO num_ent_LO =
static_cast<LO
>(num_ent);
385 const size_t num_ent_beg = offset;
388 const size_t gids_beg = num_ent_beg + num_ent_len;
391 const size_t pids_beg = gids_beg + gids_len;
394 const size_t vals_beg = gids_beg + gids_len + pids_len;
395 const size_t vals_len = num_ent * num_bytes_per_value;
397 char*
const num_ent_out = exports.data() + num_ent_beg;
398 char*
const gids_out = exports.data() + gids_beg;
399 char*
const pids_out = pack_pids ? exports.data() + pids_beg : NULL;
400 char*
const vals_out = exports.data() + vals_beg;
402 size_t num_bytes_out = 0;
409 for (
size_t k = 0; k < num_ent; ++k) {
410 const LO lid = lids_in[k];
411 const GO gid = col_map.getGlobalElement(lid);
416 for (
size_t k = 0; k < num_ent; ++k) {
417 const LO lid = lids_in[k];
418 const int pid = pids_in[lid];
424 error_code += p.first;
425 num_bytes_out += p.second;
428 if (error_code != 0) {
429 return return_type(10, num_bytes_out);
432 const size_t expected_num_bytes =
433 num_ent_len + gids_len + pids_len + vals_len;
434 if (num_bytes_out != expected_num_bytes) {
435 return return_type(11, num_bytes_out);
437 return return_type(0, num_bytes_out);
440template <
class LocalMatrix,
class LocalMap,
class BufferDeviceType>
441struct PackCrsMatrixFunctor {
444 typedef typename local_matrix_device_type::value_type ST;
447 typedef typename local_matrix_device_type::device_type DT;
449 typedef Kokkos::View<const size_t*, BufferDeviceType>
450 num_packets_per_lid_view_type;
451 typedef Kokkos::View<const size_t*, BufferDeviceType> offsets_view_type;
452 typedef Kokkos::View<char*, BufferDeviceType> exports_view_type;
456 typedef typename num_packets_per_lid_view_type::non_const_value_type
458 typedef typename offsets_view_type::non_const_value_type
460 typedef Kokkos::pair<int, LO> value_type;
462 static_assert(std::is_same<LO, typename local_matrix_device_type::ordinal_type>::value,
463 "local_map_type::local_ordinal_type and "
464 "local_matrix_device_type::ordinal_type must be the same.");
467 local_map_type local_col_map;
468 exports_view_type exports;
469 num_packets_per_lid_view_type num_packets_per_lid;
470 export_lids_view_type export_lids;
471 source_pids_view_type source_pids;
472 offsets_view_type offsets;
473 size_t num_bytes_per_value;
477 const local_map_type& local_col_map_in,
478 const exports_view_type& exports_in,
479 const num_packets_per_lid_view_type& num_packets_per_lid_in,
480 const export_lids_view_type& export_lids_in,
481 const source_pids_view_type& source_pids_in,
482 const offsets_view_type& offsets_in,
483 const size_t num_bytes_per_value_in,
484 const bool pack_pids_in)
485 : local_matrix(local_matrix_in)
486 , local_col_map(local_col_map_in)
487 , exports(exports_in)
488 , num_packets_per_lid(num_packets_per_lid_in)
489 , export_lids(export_lids_in)
490 , source_pids(source_pids_in)
491 , offsets(offsets_in)
492 , num_bytes_per_value(num_bytes_per_value_in)
493 , pack_pids(pack_pids_in) {
494 const LO numRows = local_matrix_in.numRows();
496 static_cast<LO
>(local_matrix.graph.row_map.extent(0));
497 TEUCHOS_TEST_FOR_EXCEPTION(numRows != 0 && rowMapDim != numRows +
static_cast<LO
>(1),
498 std::logic_error,
"local_matrix.graph.row_map.extent(0) = " << rowMapDim <<
" != numRows (= " << numRows <<
" ) + 1.");
501 KOKKOS_INLINE_FUNCTION
void init(value_type& dst)
const {
502 using ::Tpetra::Details::OrdinalTraits;
503 dst = Kokkos::make_pair(0, OrdinalTraits<LO>::invalid());
506 KOKKOS_INLINE_FUNCTION
void
507 join(value_type& dst,
const value_type& src)
const {
510 if (src.first != 0 && dst.first == 0) {
515 KOKKOS_INLINE_FUNCTION
516 void operator()(
const LO i, value_type& dst)
const {
517 const size_t offset = offsets[i];
518 const LO export_lid = export_lids[i];
519 const size_t buf_size = exports.size();
520 const size_t num_bytes = num_packets_per_lid(i);
521 const size_t num_ent =
522 static_cast<size_t>(local_matrix.graph.row_map[export_lid + 1] - local_matrix.graph.row_map[export_lid]);
532 if (export_lid >= local_matrix.numRows()) {
533 if (dst.first != 0) {
534 dst = Kokkos::make_pair(1, i);
537 }
else if ((offset > buf_size || offset + num_bytes > buf_size)) {
538 if (dst.first != 0) {
539 dst = Kokkos::make_pair(2, i);
549 const auto row_beg = local_matrix.graph.row_map[export_lid];
550 const auto row_end = local_matrix.graph.row_map[export_lid + 1];
551 auto vals_in = subview(local_matrix.values,
552 Kokkos::make_pair(row_beg, row_end));
553 auto lids_in = subview(local_matrix.graph.entries,
554 Kokkos::make_pair(row_beg, row_end));
555 typedef local_map_type LMT;
556 typedef BufferDeviceType BDT;
557 auto p = packCrsMatrixRow<ST, LMT, BDT>(local_col_map, exports, lids_in,
558 source_pids, vals_in, offset,
559 num_ent, num_bytes_per_value,
561 int error_code_this_row = p.first;
562 size_t num_bytes_packed_this_row = p.second;
563 if (error_code_this_row != 0) {
564 if (dst.first != 0) {
565 dst = Kokkos::make_pair(error_code_this_row, i);
567 }
else if (num_bytes_packed_this_row != num_bytes) {
568 if (dst.first != 0) {
569 dst = Kokkos::make_pair(3, i);
582template <
class LocalMatrix,
class LocalMap,
class BufferDeviceType>
585 const Kokkos::View<char*, BufferDeviceType>& exports,
589 const Kokkos::View<const size_t*, BufferDeviceType>& offsets,
590 const size_t num_bytes_per_value,
591 const bool pack_pids) {
593 using DT =
typename LocalMatrix::device_type;
594 using range_type = Kokkos::RangePolicy<typename DT::execution_space, LO>;
595 const char prefix[] =
"Tpetra::Details::do_pack: ";
597 if (export_lids.extent(0) != 0) {
598 TEUCHOS_TEST_FOR_EXCEPTION(
static_cast<size_t>(offsets.extent(0)) !=
599 static_cast<size_t>(export_lids.extent(0) + 1),
600 std::invalid_argument, prefix <<
"offsets.extent(0) = " << offsets.extent(0) <<
" != export_lids.extent(0) (= " << export_lids.extent(0) <<
") + 1.");
601 TEUCHOS_TEST_FOR_EXCEPTION(export_lids.extent(0) != num_packets_per_lid.extent(0),
602 std::invalid_argument, prefix <<
"export_lids.extent(0) = " << export_lids.extent(0) <<
" != num_packets_per_lid.extent(0) = " << num_packets_per_lid.extent(0) <<
".");
606 TEUCHOS_TEST_FOR_EXCEPTION(pack_pids && exports.extent(0) != 0 &&
607 source_pids.extent(0) == 0,
608 std::invalid_argument, prefix <<
"pack_pids is true, and exports.extent(0) = " << exports.extent(0) <<
" != 0, meaning that we need to pack at "
609 "least one matrix entry, but source_pids.extent(0) = 0.");
612 using pack_functor_type =
613 PackCrsMatrixFunctor<LocalMatrix, LocalMap, BufferDeviceType>;
614 pack_functor_type f(local_matrix, local_map, exports,
615 num_packets_per_lid, export_lids,
616 source_pids, offsets, num_bytes_per_value,
619 typename pack_functor_type::value_type result;
620 range_type range(0, num_packets_per_lid.extent(0));
621 Kokkos::parallel_reduce(range, f, result);
623 if (result.first != 0) {
626 TEUCHOS_TEST_FOR_EXCEPTION(
true, std::runtime_error, prefix <<
"PackCrsMatrixFunctor "
627 "reported error code "
628 << result.first <<
" for the first "
630 << result.second <<
".");
663template <
typename ST,
typename LO,
typename GO,
typename NT,
typename BufferDeviceType>
665 Kokkos::DualView<char*, BufferDeviceType>& exports,
666 const Kokkos::View<size_t*, BufferDeviceType>& num_packets_per_lid,
667 const Kokkos::View<const LO*, BufferDeviceType>& export_lids,
668 const Kokkos::View<const int*, typename NT::device_type>& export_pids,
669 size_t& constant_num_packets,
670 const bool pack_pids) {
672 "Tpetra::Details::PackCrsMatrixImpl::packCrsMatrix",
675 typedef BufferDeviceType DT;
676 typedef Kokkos::DualView<char*, BufferDeviceType> exports_view_type;
677 const char prefix[] =
"Tpetra::Details::PackCrsMatrixImpl::packCrsMatrix: ";
678 constexpr bool debug =
false;
681 auto local_col_map = sourceMatrix.
getColMap()->getLocalMap();
686 constant_num_packets = 0;
688 const size_t num_export_lids =
689 static_cast<size_t>(export_lids.extent(0));
690 TEUCHOS_TEST_FOR_EXCEPTION(num_export_lids !=
691 static_cast<size_t>(num_packets_per_lid.extent(0)),
692 std::invalid_argument, prefix <<
"num_export_lids.extent(0) = " << num_export_lids <<
" != num_packets_per_lid.extent(0) = " << num_packets_per_lid.extent(0) <<
".");
693 if (num_export_lids != 0) {
694 TEUCHOS_TEST_FOR_EXCEPTION(num_packets_per_lid.data() == NULL, std::invalid_argument,
695 prefix <<
"num_export_lids = " << num_export_lids <<
" != 0, but "
696 "num_packets_per_lid.data() = "
697 << num_packets_per_lid.data() <<
" == NULL.");
704 size_t num_bytes_per_value = 0;
718 size_t num_bytes_per_value_l = 0;
719 if (local_matrix.values.extent(0) > 0) {
720 const ST& val = local_matrix.values(0);
723 using Teuchos::reduceAll;
724 reduceAll<int, size_t>(*(sourceMatrix.
getComm()),
726 num_bytes_per_value_l,
727 Teuchos::outArg(num_bytes_per_value));
730 if (num_export_lids == 0) {
731 exports = exports_view_type(
"exports", 0);
736 Kokkos::View<size_t*, DT> offsets(
"offsets", num_export_lids + 1);
742 local_matrix.graph.row_map, export_lids,
744 num_bytes_per_lid, num_bytes_per_gid,
745 num_bytes_per_pid, num_bytes_per_value);
748 if (count >
static_cast<size_t>(exports.extent(0))) {
749 exports = exports_view_type(
"exports", count);
751 std::ostringstream os;
752 os <<
"*** exports resized to " << count << std::endl;
753 std::cerr << os.str();
757 std::ostringstream os;
758 os <<
"*** count: " << count <<
", exports.extent(0): "
759 << exports.extent(0) << std::endl;
760 std::cerr << os.str();
766 TEUCHOS_TEST_FOR_EXCEPTION(pack_pids && exports.extent(0) != 0 &&
767 export_pids.extent(0) == 0,
768 std::invalid_argument, prefix <<
"pack_pids is true, and exports.extent(0) = " << exports.extent(0) <<
" != 0, meaning that we need to pack at least "
769 "one matrix entry, but export_pids.extent(0) = 0.");
771 typedef typename std::decay<
decltype(local_matrix)>::type
773 typedef typename std::decay<
decltype(local_col_map)>::type
776 exports.modify_device();
777 auto exports_d = exports.view_device();
779 export_lids, export_pids, offsets, num_bytes_per_value,
786template <
typename ST,
typename LO,
typename GO,
typename NT>
788 Teuchos::Array<char>& exports,
789 const Teuchos::ArrayView<size_t>& numPacketsPerLID,
790 const Teuchos::ArrayView<const LO>& exportLIDs,
791 size_t& constantNumPackets) {
794 using host_exec_space =
typename Kokkos::View<size_t*, device_type>::host_mirror_type::execution_space;
795 using device_exec_space =
typename device_type::execution_space;
796 using host_dev_type = Kokkos::Device<host_exec_space, Kokkos::HostSpace>;
802 Kokkos::View<size_t*, buffer_device_type> num_packets_per_lid_d =
804 numPacketsPerLID.getRawPtr(),
805 numPacketsPerLID.size(),
false,
806 "num_packets_per_lid");
813 Kokkos::View<const LO*, buffer_device_type> export_lids_d =
815 exportLIDs.getRawPtr(),
816 exportLIDs.size(),
true,
819 Kokkos::View<int*, device_type> export_pids_d;
820 Kokkos::DualView<char*, buffer_device_type> exports_dv;
821 constexpr bool pack_pids =
false;
823 sourceMatrix, exports_dv, num_packets_per_lid_d, export_lids_d,
824 export_pids_d, constantNumPackets, pack_pids);
828 Kokkos::View<size_t*, host_dev_type> num_packets_per_lid_h(numPacketsPerLID.getRawPtr(),
829 numPacketsPerLID.size());
831 Kokkos::deep_copy(device_exec_space(), num_packets_per_lid_h, num_packets_per_lid_d);
838 if (
static_cast<size_t>(exports.size()) !=
839 static_cast<size_t>(exports_dv.extent(0))) {
840 exports.resize(exports_dv.extent(0));
842 Kokkos::View<char*, host_dev_type> exports_h(exports.getRawPtr(),
845 Kokkos::deep_copy(device_exec_space(), exports_h, exports_dv.view_device());
848template <
typename ST,
typename LO,
typename GO,
typename NT>
854 size_t& constantNumPackets) {
859 Kokkos::View<int*, device_type> exportPIDs_d(
"exportPIDs", 0);
860 constexpr bool pack_pids =
false;
863 auto numPacketsPerLID_nc = numPacketsPerLID;
864 numPacketsPerLID_nc.clear_sync_state();
865 numPacketsPerLID_nc.modify_device();
866 auto numPacketsPerLID_d = numPacketsPerLID.view_device();
869 TEUCHOS_ASSERT(!exportLIDs.need_sync_device());
870 auto exportLIDs_d = exportLIDs.view_device();
873 "Tpetra::Details::packCrsMatrixNew",
876 sourceMatrix, exports, numPacketsPerLID_d, exportLIDs_d,
877 exportPIDs_d, constantNumPackets, pack_pids);
880template <
typename ST,
typename LO,
typename GO,
typename NT>
883 const Teuchos::ArrayView<size_t>& numPacketsPerLID,
884 const Teuchos::ArrayView<const LO>& exportLIDs,
885 const Teuchos::ArrayView<const int>& sourcePIDs,
886 size_t& constantNumPackets) {
889 typedef typename Kokkos::DualView<char*, buffer_device_type>::t_host::execution_space host_exec_space;
890 typedef Kokkos::Device<host_exec_space, Kokkos::HostSpace> host_dev_type;
892 typename local_matrix_device_type::device_type outputDevice;
896 std::unique_ptr<std::string> prefix;
898 const int myRank = [&]() {
899 auto map = sourceMatrix.
getMap();
900 if (map.get() ==
nullptr) {
903 auto comm = map->getComm();
904 if (comm.get() ==
nullptr) {
907 return comm->getRank();
909 std::ostringstream os;
910 os <<
"Proc " << myRank <<
": packCrsMatrixWithOwningPIDs: ";
911 prefix = std::unique_ptr<std::string>(
new std::string(os.str()));
913 std::ostringstream os2;
914 os2 << *prefix <<
"start" << std::endl;
915 std::cerr << os2.str();
922 auto num_packets_per_lid_d =
924 numPacketsPerLID.getRawPtr(),
925 numPacketsPerLID.size(),
false,
926 "num_packets_per_lid");
932 exportLIDs.getRawPtr(),
933 exportLIDs.size(),
true,
939 sourcePIDs.getRawPtr(),
940 sourcePIDs.size(),
true,
942 constexpr bool pack_pids =
true;
945 export_pids_d, constantNumPackets, pack_pids);
946 }
catch (std::exception& e) {
948 std::ostringstream os;
949 os << *prefix <<
"PackCrsMatrixImpl::packCrsMatrix threw: "
950 << e.what() << std::endl;
951 std::cerr << os.str();
956 std::ostringstream os;
957 os << *prefix <<
"PackCrsMatrixImpl::packCrsMatrix threw an exception "
958 "not a subclass of std::exception"
960 std::cerr << os.str();
965 if (numPacketsPerLID.size() != 0) {
969 Kokkos::View<size_t*, host_dev_type> num_packets_per_lid_h(numPacketsPerLID.getRawPtr(), numPacketsPerLID.size());
971 Kokkos::deep_copy(
execution_space(), num_packets_per_lid_h, num_packets_per_lid_d);
972 }
catch (std::exception& e) {
974 std::ostringstream os;
975 os << *prefix <<
"Kokkos::deep_copy threw: " << e.what() << std::endl;
976 std::cerr << os.str();
981 std::ostringstream os;
982 os << *prefix <<
"Kokkos::deep_copy threw an exception not a subclass "
985 std::cerr << os.str();
992 std::ostringstream os;
993 os << *prefix <<
"done" << std::endl;
994 std::cerr << os.str();
1001#define TPETRA_DETAILS_PACKCRSMATRIX_INSTANT(ST, LO, GO, NT) \
1003 Details::packCrsMatrix<ST, LO, GO, NT>(const CrsMatrix<ST, LO, GO, NT>&, \
1004 Teuchos::Array<char>&, \
1005 const Teuchos::ArrayView<size_t>&, \
1006 const Teuchos::ArrayView<const LO>&, \
1009 Details::packCrsMatrixNew<ST, LO, GO, NT>(const CrsMatrix<ST, LO, GO, NT>&, \
1010 Kokkos::DualView<char*, DistObject<char, LO, GO, NT>::buffer_device_type>&, \
1011 const Kokkos::DualView<size_t*, DistObject<char, LO, GO, NT>::buffer_device_type>&, \
1012 const Kokkos::DualView<const LO*, DistObject<char, LO, GO, NT>::buffer_device_type>&, \
1015 Details::packCrsMatrixWithOwningPIDs<ST, LO, GO, NT>(const CrsMatrix<ST, LO, GO, NT>&, \
1016 Kokkos::DualView<char*, DistObject<char, LO, GO, NT>::buffer_device_type>&, \
1017 const Teuchos::ArrayView<size_t>&, \
1018 const Teuchos::ArrayView<const LO>&, \
1019 const Teuchos::ArrayView<const int>&, \
Declaration of the Tpetra::CrsMatrix class.
Declaration of Tpetra::Details::Behavior, a class that describes Tpetra's behavior.
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 of Tpetra::Details::Profiling, a scope guard for Kokkos Profiling.
Declaration and definition of Tpetra::Details::castAwayConstDualView, an implementation detail of Tpe...
Functions that wrap Kokkos::create_mirror_view, in order to avoid deep copies when not necessary,...
Declaration and definition of Tpetra::Details::getEntryOnHost.
CountsViewType::non_const_value_type computeNumPacketsAndOffsets(const OutputOffsetsViewType &outputOffsets, const CountsViewType &counts, const InputOffsetsViewType &rowOffsets, const InputLocalRowIndicesViewType &lclRowInds, const InputLocalRowPidsViewType &lclRowPids, const typename CountsViewType::non_const_value_type sizeOfLclCount, const typename CountsViewType::non_const_value_type sizeOfGblColInd, const typename CountsViewType::non_const_value_type sizeOfPid, const typename CountsViewType::non_const_value_type sizeOfValue)
Compute the number of packets and offsets for the pack procedure.
void packCrsMatrix(const CrsMatrix< ST, LO, GO, NT > &sourceMatrix, Kokkos::DualView< char *, BufferDeviceType > &exports, const Kokkos::View< size_t *, BufferDeviceType > &num_packets_per_lid, const Kokkos::View< const LO *, BufferDeviceType > &export_lids, const Kokkos::View< const int *, typename NT::device_type > &export_pids, size_t &constant_num_packets, const bool pack_pids)
Pack specified entries of the given local sparse matrix for communication.
void do_pack(const LocalMatrix &local_matrix, const LocalMap &local_map, const Kokkos::View< char *, BufferDeviceType > &exports, const typename PackTraits< size_t >::input_array_type &num_packets_per_lid, const typename PackTraits< typename LocalMap::local_ordinal_type >::input_array_type &export_lids, const typename PackTraits< int >::input_array_type &source_pids, const Kokkos::View< const size_t *, BufferDeviceType > &offsets, const size_t num_bytes_per_value, const bool pack_pids)
Perform the pack operation for the matrix.
KOKKOS_FUNCTION Kokkos::pair< int, size_t > packCrsMatrixRow(const ColumnMap &col_map, const Kokkos::View< char *, BufferDeviceType > &exports, const typename PackTraits< typename ColumnMap::local_ordinal_type >::input_array_type &lids_in, const typename PackTraits< int >::input_array_type &pids_in, const typename PackTraits< ST >::input_array_type &vals_in, const size_t offset, const size_t num_ent, const size_t num_bytes_per_value, const bool pack_pids)
Packs a single row of the CrsMatrix.
Teuchos::RCP< const Teuchos::Comm< int > > getComm() const override
The communicator over which the matrix is distributed.
typename Node::device_type device_type
The Kokkos device type.
TPETRA_DETAILS_ALWAYS_INLINE local_matrix_device_type getLocalMatrixDevice() const
The local sparse matrix.
Teuchos::RCP< const map_type > getColMap() const override
The Map that describes the column distribution in this matrix.
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...
static bool verbose()
Whether Tpetra is in verbose mode.
"Local" part of Map suitable for Kokkos kernels.
LocalOrdinal local_ordinal_type
The type of local indices.
GlobalOrdinal global_ordinal_type
The type of global indices.
Compute the number of packets and offsets for the pack procedure.
int getError() const
Host function for getting the error.
Kokkos::Device< typename device_type::execution_space, buffer_memory_space > buffer_device_type
Kokkos::Device specialization for communication buffers.
virtual Teuchos::RCP< const map_type > getMap() const
The Map describing the parallel distribution of this object.
Nonmember function that computes a residual Computes R = B - A * X.
void packCrsMatrix(const CrsMatrix< ST, LO, GO, NT > &sourceMatrix, Teuchos::Array< char > &exports, const Teuchos::ArrayView< size_t > &numPacketsPerLID, const Teuchos::ArrayView< const LO > &exportLIDs, size_t &constantNumPackets)
Pack specified entries of the given local sparse matrix for communication.
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.
void packCrsMatrixWithOwningPIDs(const CrsMatrix< ST, LO, GO, NT > &sourceMatrix, Kokkos::DualView< char *, typename DistObject< char, LO, GO, NT >::buffer_device_type > &exports_dv, const Teuchos::ArrayView< size_t > &numPacketsPerLID, const Teuchos::ArrayView< const LO > &exportLIDs, const Teuchos::ArrayView< const int > &sourcePIDs, size_t &constantNumPackets)
Pack specified entries of the given local sparse matrix for communication.
void packCrsMatrixNew(const CrsMatrix< ST, LO, GO, NT > &sourceMatrix, Kokkos::DualView< char *, typename DistObject< char, LO, GO, NT >::buffer_device_type > &exports, const Kokkos::DualView< size_t *, typename DistObject< char, LO, GO, NT >::buffer_device_type > &numPacketsPerLID, const Kokkos::DualView< const LO *, typename DistObject< char, LO, GO, NT >::buffer_device_type > &exportLIDs, size_t &constantNumPackets)
Pack specified entries of the given local sparse matrix for communication, for "new" DistObject inter...
Namespace Tpetra contains the class and methods constituting the Tpetra library.
static KOKKOS_INLINE_FUNCTION Kokkos::pair< int, size_t > packArray(char outBuf[], const value_type inBuf[], const size_t numEnt)
Pack the first numEnt entries of the given input buffer of value_type, into the output buffer of byte...
static const bool compileTimeSize
Whether the number of bytes required to pack one instance of value_type is fixed at compile time.
static KOKKOS_INLINE_FUNCTION size_t packValue(char outBuf[], const T &inVal)
Pack the given value of type value_type into the given output buffer of bytes (char).
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.