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
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.");
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;
138 <<
" != counts.extent(0) = " << counts_.extent(0)
143 static_cast<size_t>(outputOffsets_.extent(0))) {
144 std::ostringstream
os;
146 <<
" != outputOffsets.extent(0) = " << outputOffsets_.extent(0)
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))) {
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_);
207 auto error_h = Kokkos::create_mirror_view(error_);
212 Kokkos::deep_copy(
error_h, error_);
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_;
243typename CountsViewType::non_const_value_type
249 const typename CountsViewType::non_const_value_type
sizeOfLclCount,
251 const typename CountsViewType::non_const_value_type
sizeOfPid,
252 const typename CountsViewType::non_const_value_type
sizeOfValue) {
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;
272 std::invalid_argument,
prefix <<
"There is at least one row to pack, "
273 "but the matrix has no rows. lclRowInds.extent(0) = "
277 std::invalid_argument,
278 prefix <<
"Output dimension does not match number of rows to pack. "
280 <<
" != lclRowInds.extent(0) + 1 = "
302 errStr = std::unique_ptr<std::ostringstream> (
new std::ostringstream ());
308 <<
total <<
"." << std::endl;
312 os <<
"outputOffsets: [";
319 os <<
"]" << std::endl;
327 os <<
"]" << std::endl;
341 using Tpetra::Details::getEntryOnHost;
362template <
class ST,
class ColumnMap,
class BufferDeviceType>
364 Kokkos::pair<int, size_t>
366 const Kokkos::View<char*, BufferDeviceType>& exports,
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;
424 error_code +=
p.first;
428 if (error_code != 0) {
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.");
466 local_matrix_device_type local_matrix;
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;
496 static_cast<LO
>(local_matrix.graph.row_map.extent(0));
498 std::logic_error,
"local_matrix.graph.row_map.extent(0) = " <<
rowMapDim <<
" != numRows (= " <<
numRows <<
" ) + 1.");
502 using ::Tpetra::Details::OrdinalTraits;
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) {
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.");
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) <<
".");
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.");
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));
627 "reported error code "
628 <<
result.first <<
" for the first "
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,
670 const bool pack_pids) {
672 "Tpetra::Details::PackCrsMatrixImpl::packCrsMatrix",
676 typedef Kokkos::DualView<char*, BufferDeviceType> exports_view_type;
677 const char prefix[] =
"Tpetra::Details::PackCrsMatrixImpl::packCrsMatrix: ";
678 constexpr bool debug =
false;
680 auto local_matrix =
sourceMatrix.getLocalMatrixDevice();
681 auto local_col_map =
sourceMatrix.getColMap()->getLocalMap();
689 static_cast<size_t>(export_lids.extent(0));
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) <<
".");
696 "num_packets_per_lid.data() = "
697 << num_packets_per_lid.data() <<
" == NULL.");
704 size_t num_bytes_per_value = 0;
719 if (local_matrix.values.extent(0) > 0) {
720 const ST&
val = local_matrix.values(0);
723 using Teuchos::reduceAll;
727 Teuchos::outArg(num_bytes_per_value));
731 exports = exports_view_type(
"exports", 0);
741 computeNumPacketsAndOffsets(offsets, num_packets_per_lid,
742 local_matrix.graph.row_map, export_lids,
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();
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
772 local_matrix_device_type;
773 typedef typename std::decay<
decltype(local_col_map)>::type
776 exports.modify_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,
790 const Teuchos::ArrayView<const LO>&
exportLIDs,
794 using host_exec_space =
typename Kokkos::View<size_t*, device_type>::host_mirror_type::execution_space;
796 using host_dev_type = Kokkos::Device<host_exec_space, Kokkos::HostSpace>;
806 "num_packets_per_lid");
820 Kokkos::DualView<char*, buffer_device_type>
exports_dv;
821 constexpr bool pack_pids =
false;
822 PackCrsMatrixImpl::packCrsMatrix<ST, LO, GO, NT, buffer_device_type>(
838 if (
static_cast<size_t>(exports.size()) !=
842 Kokkos::View<char*, host_dev_type>
exports_h(exports.getRawPtr(),
848template <
typename ST,
typename LO,
typename GO,
typename NT>
859 Kokkos::View<int*, device_type>
exportPIDs_d(
"exportPIDs", 0);
860 constexpr bool pack_pids =
false;
873 "Tpetra::Details::packCrsMatrixNew",
875 PackCrsMatrixImpl::packCrsMatrix<ST, LO, GO, NT, buffer_device_type>(
880template <
typename ST,
typename LO,
typename GO,
typename NT>
884 const Teuchos::ArrayView<const LO>&
exportLIDs,
885 const Teuchos::ArrayView<const int>&
sourcePIDs,
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;
893 typedef typename NT::execution_space execution_space;
896 std::unique_ptr<std::string>
prefix;
898 const int myRank = [&]() {
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;
915 std::cerr <<
os2.str();
926 "num_packets_per_lid");
942 constexpr bool pack_pids =
true;
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();
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.
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.
Sparse matrix that presents a row-oriented interface that lets users read or modify entries.
typename Node::device_type device_type
The Kokkos device type.
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...
Struct that holds views of the contents of a CrsMatrix.
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.
Implementation details of Tpetra.
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.
Traits class for packing / unpacking data of type T.
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 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.