10#ifndef TPETRA_DETAILS_PACKCRSGRAPH_DEF_HPP
11#define TPETRA_DETAILS_PACKCRSGRAPH_DEF_HPP
13#include "TpetraCore_config.h"
14#include "Teuchos_Array.hpp"
15#include "Teuchos_ArrayView.hpp"
55namespace PackCrsGraphImpl {
63template <
class OutputOffsetsViewType,
65 class InputOffsetsViewType,
66 class InputLocalRowIndicesViewType,
67 class InputLocalRowPidsViewType,
69#ifdef HAVE_TPETRA_DEBUG
77 typedef typename OutputOffsetsViewType::non_const_value_type output_offset_type;
78 typedef typename CountsViewType::non_const_value_type count_type;
79 typedef typename InputOffsetsViewType::non_const_value_type input_offset_type;
80 typedef typename InputLocalRowIndicesViewType::non_const_value_type local_row_index_type;
81 typedef typename InputLocalRowPidsViewType::non_const_value_type local_row_pid_type;
83 typedef typename OutputOffsetsViewType::device_type device_type;
84 static_assert(std::is_same<
typename CountsViewType::device_type::execution_space,
85 typename device_type::execution_space>::value,
86 "OutputOffsetsViewType and CountsViewType must have the same execution space.");
87 static_assert(Kokkos::is_view<OutputOffsetsViewType>::value,
88 "OutputOffsetsViewType must be a Kokkos::View.");
89 static_assert(std::is_same<typename OutputOffsetsViewType::value_type, output_offset_type>::value,
90 "OutputOffsetsViewType must be a nonconst Kokkos::View.");
91 static_assert(std::is_integral<output_offset_type>::value,
92 "The type of each entry of OutputOffsetsViewType must be a built-in integer type.");
93 static_assert(Kokkos::is_view<CountsViewType>::value,
94 "CountsViewType must be a Kokkos::View.");
95 static_assert(std::is_same<typename CountsViewType::value_type, output_offset_type>::value,
96 "CountsViewType must be a nonconst Kokkos::View.");
97 static_assert(std::is_integral<count_type>::value,
98 "The type of each entry of CountsViewType must be a built-in integer type.");
99 static_assert(Kokkos::is_view<InputOffsetsViewType>::value,
100 "InputOffsetsViewType must be a Kokkos::View.");
101 static_assert(std::is_integral<input_offset_type>::value,
102 "The type of each entry of InputOffsetsViewType must be a built-in integer type.");
103 static_assert(Kokkos::is_view<InputLocalRowIndicesViewType>::value,
104 "InputLocalRowIndicesViewType must be a Kokkos::View.");
105 static_assert(std::is_integral<local_row_index_type>::value,
106 "The type of each entry of InputLocalRowIndicesViewType must be a built-in integer type.");
121 const size_t numRowsToPack =
static_cast<size_t>(lclRowInds_.extent(0));
123 if (
numRowsToPack !=
static_cast<size_t>(counts_.extent(0))) {
124 std::ostringstream
os;
126 <<
" != counts.extent(0) = " << counts_.extent(0)
131 static_cast<size_t>(outputOffsets_.extent(0))) {
132 std::ostringstream
os;
134 <<
" != outputOffsets.extent(0) = " << outputOffsets_.extent(0)
142 operator()(
const local_row_index_type&
curInd,
143 output_offset_type& update,
144 const bool final)
const {
146 if (
curInd <
static_cast<local_row_index_type
>(0)) {
154 if (
curInd >=
static_cast<local_row_index_type
>(outputOffsets_.extent(0))) {
159 outputOffsets_(
curInd) = update;
162 if (
curInd <
static_cast<local_row_index_type
>(counts_.extent(0))) {
164 if (
static_cast<size_t>(
lclRow + 1) >=
static_cast<size_t>(rowOffsets_.extent(0)) ||
165 static_cast<local_row_index_type
>(
lclRow) <
static_cast<local_row_index_type
>(0)) {
173 const count_type count =
174 static_cast<count_type
>(rowOffsets_(
lclRow + 1) - rowOffsets_(
lclRow));
179 ?
static_cast<count_type
>(0)
180 : count * (1 + (lclRowPids_.size() > 0 ? 1 : 0));
195 auto error_h = Kokkos::create_mirror_view(error_);
200 Kokkos::deep_copy(
error_h, error_);
208 typename InputOffsetsViewType::const_type rowOffsets_;
209 typename InputLocalRowIndicesViewType::const_type lclRowInds_;
210 typename InputLocalRowPidsViewType::const_type lclRowPids_;
211 Kokkos::View<int, device_type> error_;
228typename CountsViewType::non_const_value_type
236 typename InputLocalRowIndicesViewType::const_type,
237 typename InputLocalRowPidsViewType::const_type>
239 typedef typename CountsViewType::non_const_value_type count_type;
240 typedef typename OutputOffsetsViewType::size_type size_type;
241 typedef typename OutputOffsetsViewType::execution_space execution_space;
242 typedef typename functor_type::local_row_index_type LO;
243 typedef Kokkos::RangePolicy<execution_space, LO> range_type;
244 const char prefix[] =
"computeNumPacketsAndOffsets: ";
246 count_type count = 0;
253 std::invalid_argument,
prefix <<
"There is at least one row to pack, "
254 "but the graph has no rows. lclRowInds.extent(0) = "
258 std::invalid_argument,
259 prefix <<
"Output dimension does not match number of rows to pack. "
261 <<
" != lclRowInds.extent(0) + 1 = "
268 Kokkos::parallel_scan(
"Tpetra::Details::computeNumPacketsAndOffsets::scan", range_type(0,
numRowsToPack + 1),
f);
281 errStr = std::unique_ptr<std::ostringstream> (
new std::ostringstream ());
287 <<
total <<
"." << std::endl;
291 os <<
"outputOffsets: [";
298 os <<
"]" << std::endl;
306 os <<
"]" << std::endl;
320 using Tpetra::Details::getEntryOnHost;
344 const Kokkos::View<Packet*, BufferDeviceType>& exports,
349 const bool pack_pids) {
350 using LO =
typename LocalMapType::local_ordinal_type;
351 using GO =
typename LocalMapType::global_ordinal_type;
355 return static_cast<size_t>(0);
386struct PackCrsGraphFunctor {
392 using num_packets_per_lid_view_type =
393 Kokkos::View<const size_t*, BufferDeviceType>;
394 using offsets_view_type = Kokkos::View<const size_t*, BufferDeviceType>;
395 using exports_view_type = Kokkos::View<Packet*, BufferDeviceType>;
396 using export_lids_view_type =
398 using source_pids_view_type =
402 typename num_packets_per_lid_view_type::non_const_value_type;
403 using offset_type =
typename offsets_view_type::non_const_value_type;
404 using value_type = Kokkos::pair<int, LO>;
406 static_assert(std::is_same<LO, typename local_graph_type::data_type>::value,
407 "local_map_type::local_ordinal_type and "
408 "local_graph_type::data_type must be the same.");
410 local_graph_type local_graph;
411 local_map_type local_col_map;
412 exports_view_type exports;
413 num_packets_per_lid_view_type num_packets_per_lid;
414 export_lids_view_type export_lids;
415 source_pids_view_type source_pids;
416 offsets_view_type offsets;
437 static_cast<LO
>(local_graph.row_map.extent(0));
439 std::logic_error,
"local_graph.row_map.extent(0) = " <<
rowMapDim <<
" != numRows (= " <<
numRows <<
" ) + 1.");
443 using ::Tpetra::Details::OrdinalTraits;
447 KOKKOS_INLINE_FUNCTION
void
448 join(value_type& dst,
const value_type& src)
const {
451 if (src.first != 0 && dst.first == 0) {
456 KOKKOS_INLINE_FUNCTION
457 void operator()(
const LO i, value_type& dst)
const {
458 const size_t offset = offsets[i];
459 const LO export_lid = export_lids[i];
460 const size_t buf_size = exports.size();
461 const size_t num_packets_this_lid = num_packets_per_lid(i);
462 const size_t num_ent =
463 static_cast<size_t>(local_graph.row_map[export_lid + 1] - local_graph.row_map[export_lid]);
473 if (export_lid >=
static_cast<LO
>(local_graph.numRows())) {
474 if (dst.first != 0) {
475 dst = Kokkos::make_pair(1, i);
478 }
else if ((offset > buf_size || offset + num_packets_this_lid > buf_size)) {
479 if (dst.first != 0) {
480 dst = Kokkos::make_pair(2, i);
490 const auto row_beg = local_graph.row_map[export_lid];
491 const auto row_end = local_graph.row_map[export_lid + 1];
492 auto lids_in = Kokkos::subview(local_graph.entries,
493 Kokkos::make_pair(row_beg, row_end));
494 size_t num_ent_packed_this_row =
495 packRow(local_col_map, exports, lids_in,
496 source_pids, offset, num_ent, pack_pids);
497 if (num_ent_packed_this_row != num_packets_this_lid) {
498 if (dst.first != 0) {
499 dst = Kokkos::make_pair(3, i);
512template <
class Packet,
515 class BufferDeviceType>
518 const Kokkos::View<Packet*, BufferDeviceType>& exports,
520 size_t>::input_array_type& num_packets_per_lid,
524 int>::input_array_type& source_pids,
525 const Kokkos::View<const size_t*, BufferDeviceType>& offsets,
526 const bool pack_pids) {
528 using execution_space =
typename LocalGraph::device_type::execution_space;
529 using range_type = Kokkos::RangePolicy<execution_space, LO>;
530 const char prefix[] =
"Tpetra::Details::PackCrsGraphImpl::do_pack: ";
532 if (export_lids.extent(0) != 0) {
534 static_cast<size_t>(export_lids.extent(0) + 1),
535 std::invalid_argument,
prefix <<
"offsets.extent(0) = " << offsets.extent(0) <<
" != export_lids.extent(0) (= " << export_lids.extent(0) <<
") + 1.");
537 std::invalid_argument,
prefix <<
"export_lids.extent(0) = " << export_lids.extent(0) <<
" != num_packets_per_lid.extent(0) = " << num_packets_per_lid.extent(0) <<
".");
542 source_pids.extent(0) == 0,
543 std::invalid_argument,
prefix <<
"pack_pids is true, and exports.extent(0) = " << exports.extent(0) <<
" != 0, meaning that we need to pack at "
544 "least one graph entry, but source_pids.extent(0) = 0.");
551 num_packets_per_lid, export_lids,
552 source_pids, offsets, pack_pids);
554 typename pack_functor_type::value_type
result;
555 range_type
range(0, num_packets_per_lid.extent(0));
556 Kokkos::parallel_reduce(
"Tpetra::Details::computeNumPacketsAndOffsets::reduce",
range,
f,
result);
561 std::ostringstream
os;
563 os <<
"invalid local row index";
564 }
else if (
result.first == 2) {
565 os <<
"invalid offset";
568 "reported error code "
569 <<
result.first <<
" (" <<
os.str() <<
") for the first bad row " <<
result.second <<
".");
601template <
typename LO,
typename GO,
typename NT>
616 const bool pack_pids) {
619 using packet_type =
typename crs_graph_type::packet_type;
620 using buffer_device_type =
typename crs_graph_type::buffer_device_type;
621 using exports_view_type = Kokkos::DualView<packet_type*, buffer_device_type>;
622 using local_graph_device_type =
typename crs_graph_type::local_graph_device_type;
624 const char prefix[] =
"Tpetra::Details::packCrsGraph: ";
625 constexpr bool debug =
false;
627 local_graph_device_type local_graph =
sourceGraph.getLocalGraphDevice();
628 local_map_type local_col_map =
sourceGraph.getColMap()->getLocalMap();
637 std::invalid_argument,
prefix <<
"num_export_lids.extent(0) = " <<
num_export_lids <<
" != num_packets_per_lid.extent(0) = " << num_packets_per_lid.extent(0) <<
".");
641 "num_packets_per_lid.data() = "
642 << num_packets_per_lid.data() <<
" == NULL.");
646 exports = exports_view_type(
"exports", 0);
660 if (count >
size_t(exports.extent(0))) {
661 exports = exports_view_type(
"exports", count);
663 std::ostringstream
os;
664 os <<
"*** exports resized to " << count << std::endl;
665 std::cerr <<
os.str();
669 std::ostringstream
os;
670 os <<
"*** count: " << count <<
", exports.extent(0): "
671 << exports.extent(0) << std::endl;
672 std::cerr <<
os.str();
680 std::invalid_argument,
prefix <<
"pack_pids is true, and exports.extent(0) = " << exports.extent(0) <<
" != 0, meaning that we need to pack at least "
681 "one graph entry, but export_pids.extent(0) = 0.");
683 exports.modify_device();
692template <
typename LO,
typename GO,
typename NT>
696 const Teuchos::ArrayView<const LO>&
exportLIDs,
698 using Kokkos::HostSpace;
699 using Kokkos::MemoryUnmanaged;
702 using packet_type =
typename crs_graph_type::packet_type;
703 using BDT =
typename crs_graph_type::buffer_device_type;
714 "num_packets_per_lid");
723 Kokkos::DualView<packet_type*, BDT>
exports_dv;
724 constexpr bool pack_pids =
false;
726 static_assert(std::is_same<
729 "num_packets_per_lid_d's non_const_value_type should be size_t.");
730 static_assert(std::is_same<
733 "num_packets_per_lid_d's BDT should be size_t.");
734 static_assert(std::is_same<
737 "export_lids_d's device_type should be BDT.");
738 static_assert(std::is_same<
741 "export_pids_d's non_const_value_type should be int.");
742 static_assert(std::is_same<
745 "export_pids_d's device_type should be BDT.");
757 using execution_space =
typename BDT::execution_space;
765 if (
static_cast<size_t>(exports.size()) !=
770 exports_h(exports.getRawPtr(), exports.size());
773 execution_space().fence();
778template <
typename LO,
typename GO,
typename NT>
780 const Kokkos::DualView<
783 const Kokkos::DualView<
794 const bool pack_pids) {
797 using BDT =
typename crs_graph_type::buffer_device_type;
798 using PT =
typename crs_graph_type::packet_type;
800 using LGT =
typename crs_graph_type::local_graph_device_type;
801 using LMT =
typename crs_graph_type::map_type::local_map_type;
802 const char prefix[] =
"Tpetra::Details::packCrsGraphNew: ";
813 static_cast<size_t>(export_lids.extent(0));
815 static_cast<size_t>(num_packets_per_lid.extent(0)),
816 std::invalid_argument,
prefix <<
"num_export_lids.extent(0) = " <<
num_export_lids <<
" != num_packets_per_lid.extent(0) = " << num_packets_per_lid.extent(0) <<
".");
818 num_packets_per_lid.view_device().data() ==
nullptr,
819 std::invalid_argument,
prefix <<
"num_export_lids = " <<
num_export_lids <<
" != 0, but num_packets_per_lid.view_device().data() = nullptr.");
827 using offsets_type = Kokkos::View<size_t*, BDT>;
832 num_packets_per_lid.clear_sync_state();
833 num_packets_per_lid.modify_device();
834 using PackCrsGraphImpl::computeNumPacketsAndOffsets;
836 computeNumPacketsAndOffsets(offsets, num_packets_per_lid.view_device(),
838 export_lids.view_device(),
842 if (count >
static_cast<size_t>(exports.extent(0))) {
851 std::invalid_argument,
prefix <<
"pack_pids is true, and exports.extent(0) = " << exports.extent(0) <<
" != 0, meaning that we need to pack at least "
852 "one graph entry, but export_pids.extent(0) = 0.");
854 exports.modify_device();
855 using PackCrsGraphImpl::do_pack;
857 exports.view_device(),
858 num_packets_per_lid.view_device(),
859 export_lids.view_device(),
864template <
typename LO,
typename GO,
typename NT>
870 const Teuchos::ArrayView<const LO>&
exportLIDs,
871 const Teuchos::ArrayView<const int>&
sourcePIDs,
873 using Kokkos::HostSpace;
874 using Kokkos::MemoryUnmanaged;
877 using buffer_device_type =
typename crs_graph_type::buffer_device_type;
887 "num_packets_per_lid");
903 constexpr bool pack_pids =
true;
911 using execution_space =
typename buffer_device_type::execution_space;
912 Kokkos::deep_copy(execution_space(),
914 execution_space().fence();
920#define TPETRA_DETAILS_PACKCRSGRAPH_INSTANT(LO, GO, NT) \
922 Details::packCrsGraph<LO, GO, NT>( \
923 const CrsGraph<LO, GO, NT>&, \
924 Teuchos::Array<CrsGraph<LO, GO, NT>::packet_type>&, \
925 const Teuchos::ArrayView<size_t>&, \
926 const Teuchos::ArrayView<const LO>&, \
929 Details::packCrsGraphNew<LO, GO, NT>( \
930 const CrsGraph<LO, GO, NT>&, \
931 const Kokkos::DualView< \
933 CrsGraph<LO, GO, NT>::buffer_device_type>&, \
934 const Kokkos::DualView< \
936 CrsGraph<LO, GO, NT>::buffer_device_type>&, \
938 CrsGraph<LO, GO, NT>::packet_type*, \
939 CrsGraph<LO, GO, NT>::buffer_device_type>&, \
942 CrsGraph<LO, GO, NT>::buffer_device_type>, \
946 Details::packCrsGraphWithOwningPIDs<LO, GO, NT>( \
947 const CrsGraph<LO, GO, NT>&, \
948 Kokkos::DualView<CrsGraph<LO, GO, NT>::packet_type*, CrsGraph<LO, GO, NT>::buffer_device_type>&, \
949 const Teuchos::ArrayView<size_t>&, \
950 const Teuchos::ArrayView<const LO>&, \
951 const Teuchos::ArrayView<const int>&, \
Declaration of the Tpetra::CrsGraph 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 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)
Compute the number of packets and offsets for the pack procedure.
void do_pack(const LocalGraph &local_graph, const LocalMap &local_map, const Kokkos::View< Packet *, 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 bool pack_pids)
Perform the pack operation for the graph.
KOKKOS_FUNCTION size_t packRow(const LocalMapType &col_map, const Kokkos::View< Packet *, BufferDeviceType > &exports, const InputLidsType &lids_in, const InputPidsType &pids_in, const size_t offset, const size_t num_ent, const bool pack_pids)
Packs a single row of the CrsGraph.
typename dist_object_type::buffer_device_type buffer_device_type
Kokkos::Device specialization for communication buffers.
Struct that holds views of the contents of a CrsMatrix.
"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.
Implementation details of Tpetra.
void packCrsGraph(const CrsGraph< LO, GO, NT > &sourceGraph, Teuchos::Array< typename CrsGraph< LO, GO, NT >::packet_type > &exports, const Teuchos::ArrayView< size_t > &numPacketsPerLID, const Teuchos::ArrayView< const LO > &exportLIDs, size_t &constantNumPackets)
Pack specified entries of the given local sparse graph 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 packCrsGraphNew(const CrsGraph< LO, GO, NT > &sourceGraph, const Kokkos::DualView< const LO *, typename CrsGraph< LO, GO, NT >::buffer_device_type > &exportLIDs, const Kokkos::DualView< const int *, typename CrsGraph< LO, GO, NT >::buffer_device_type > &exportPIDs, Kokkos::DualView< typename CrsGraph< LO, GO, NT >::packet_type *, typename CrsGraph< LO, GO, NT >::buffer_device_type > &exports, Kokkos::DualView< size_t *, typename CrsGraph< LO, GO, NT >::buffer_device_type > numPacketsPerLID, size_t &constantNumPackets, const bool pack_pids)
Pack specified entries of the given local sparse graph for communication, for "new" DistObject interf...
void packCrsGraphWithOwningPIDs(const CrsGraph< LO, GO, NT > &sourceGraph, Kokkos::DualView< typename CrsGraph< LO, GO, NT >::packet_type *, typename CrsGraph< 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 graph for communication.
Namespace Tpetra contains the class and methods constituting the Tpetra library.
Traits class for packing / unpacking data of type T.
Kokkos::View< const value_type *, Kokkos::AnonymousSpace > input_array_type
The type of an input array of value_type.