40#ifndef TPETRA_DETAILS_PACKCRSGRAPH_DEF_HPP
41#define TPETRA_DETAILS_PACKCRSGRAPH_DEF_HPP
43#include "TpetraCore_config.h"
44#include "Teuchos_Array.hpp"
45#include "Teuchos_ArrayView.hpp"
85namespace PackCrsGraphImpl {
93template<
class OutputOffsetsViewType,
95 class InputOffsetsViewType,
96 class InputLocalRowIndicesViewType,
97 class InputLocalRowPidsViewType,
99#ifdef HAVE_TPETRA_DEBUG
107 typedef typename OutputOffsetsViewType::non_const_value_type output_offset_type;
108 typedef typename CountsViewType::non_const_value_type count_type;
109 typedef typename InputOffsetsViewType::non_const_value_type input_offset_type;
110 typedef typename InputLocalRowIndicesViewType::non_const_value_type local_row_index_type;
111 typedef typename InputLocalRowPidsViewType::non_const_value_type local_row_pid_type;
113 typedef typename OutputOffsetsViewType::device_type device_type;
114 static_assert (std::is_same<
typename CountsViewType::device_type::execution_space,
115 typename device_type::execution_space>::value,
116 "OutputOffsetsViewType and CountsViewType must have the same execution space.");
117 static_assert (Kokkos::Impl::is_view<OutputOffsetsViewType>::value,
118 "OutputOffsetsViewType must be a Kokkos::View.");
119 static_assert (std::is_same<typename OutputOffsetsViewType::value_type, output_offset_type>::value,
120 "OutputOffsetsViewType must be a nonconst Kokkos::View.");
121 static_assert (std::is_integral<output_offset_type>::value,
122 "The type of each entry of OutputOffsetsViewType must be a built-in integer type.");
123 static_assert (Kokkos::Impl::is_view<CountsViewType>::value,
124 "CountsViewType must be a Kokkos::View.");
125 static_assert (std::is_same<typename CountsViewType::value_type, output_offset_type>::value,
126 "CountsViewType must be a nonconst Kokkos::View.");
127 static_assert (std::is_integral<count_type>::value,
128 "The type of each entry of CountsViewType must be a built-in integer type.");
129 static_assert (Kokkos::Impl::is_view<InputOffsetsViewType>::value,
130 "InputOffsetsViewType must be a Kokkos::View.");
131 static_assert (std::is_integral<input_offset_type>::value,
132 "The type of each entry of InputOffsetsViewType must be a built-in integer type.");
133 static_assert (Kokkos::Impl::is_view<InputLocalRowIndicesViewType>::value,
134 "InputLocalRowIndicesViewType must be a Kokkos::View.");
135 static_assert (std::is_integral<local_row_index_type>::value,
136 "The type of each entry of InputLocalRowIndicesViewType must be a built-in integer type.");
151 const size_t numRowsToPack =
static_cast<size_t> (lclRowInds_.extent (0));
153 if (
numRowsToPack !=
static_cast<size_t> (counts_.extent (0))) {
154 std::ostringstream
os;
156 <<
" != counts.extent(0) = " << counts_.extent (0)
161 static_cast<size_t> (outputOffsets_.extent (0))) {
162 std::ostringstream
os;
164 <<
" != outputOffsets.extent(0) = " << outputOffsets_.extent (0)
173 output_offset_type& update,
174 const bool final)
const
177 if (
curInd <
static_cast<local_row_index_type
> (0)) {
185 if (
curInd >=
static_cast<local_row_index_type
> (outputOffsets_.extent (0))) {
190 outputOffsets_(
curInd) = update;
193 if (
curInd <
static_cast<local_row_index_type
> (counts_.extent (0))) {
195 if (
static_cast<size_t> (
lclRow + 1) >=
static_cast<size_t> (rowOffsets_.extent (0)) ||
196 static_cast<local_row_index_type
> (
lclRow) <
static_cast<local_row_index_type
> (0)) {
204 const count_type
count =
205 static_cast<count_type
> (rowOffsets_(
lclRow+1) - rowOffsets_(
lclRow));
210 ?
static_cast<count_type
>(0)
211 :
count * (1 + (lclRowPids_.size() > 0 ? 1 : 0));
226 auto error_h = Kokkos::create_mirror_view (error_);
227 Kokkos::deep_copy (
error_h, error_);
234 typename InputOffsetsViewType::const_type rowOffsets_;
235 typename InputLocalRowIndicesViewType::const_type lclRowInds_;
236 typename InputLocalRowPidsViewType::const_type lclRowPids_;
237 Kokkos::View<int, device_type> error_;
254typename CountsViewType::non_const_value_type
263 typename InputLocalRowIndicesViewType::const_type,
264 typename InputLocalRowPidsViewType::const_type>
functor_type;
265 typedef typename CountsViewType::non_const_value_type count_type;
266 typedef typename OutputOffsetsViewType::size_type size_type;
267 typedef typename OutputOffsetsViewType::execution_space execution_space;
268 typedef typename functor_type::local_row_index_type LO;
269 typedef Kokkos::RangePolicy<execution_space, LO> range_type;
270 const char prefix[] =
"computeNumPacketsAndOffsets: ";
272 count_type
count = 0;
280 (
rowOffsets.extent (0) <=
static_cast<size_type
> (1),
281 std::invalid_argument,
prefix <<
"There is at least one row to pack, "
282 "but the graph has no rows. lclRowInds.extent(0) = " <<
287 static_cast<size_type
> (
numRowsToPack + 1), std::invalid_argument,
288 prefix <<
"Output dimension does not match number of rows to pack. "
290 <<
" != lclRowInds.extent(0) + 1 = "
303 (
errCode != 0, std::runtime_error,
prefix <<
"parallel_scan error code "
313 errStr = std::unique_ptr<std::ostringstream> (
new std::ostringstream ());
319 <<
total <<
"." << std::endl;
323 os <<
"outputOffsets: [";
330 os <<
"]" << std::endl;
338 os <<
"]" << std::endl;
352 using Tpetra::Details::getEntryOnHost;
353 return static_cast<count_type
> (getEntryOnHost (
outputOffsets,
376 const Kokkos::View<Packet*, BufferDeviceType>& exports,
381 const bool pack_pids)
383 using LO =
typename LocalMapType::local_ordinal_type;
384 using GO =
typename LocalMapType::global_ordinal_type;
388 return static_cast<size_t>(0);
419struct PackCrsGraphFunctor {
425 using num_packets_per_lid_view_type =
426 Kokkos::View<const size_t*, BufferDeviceType>;
427 using offsets_view_type = Kokkos::View<const size_t*, BufferDeviceType>;
428 using exports_view_type = Kokkos::View<Packet*, BufferDeviceType>;
429 using export_lids_view_type =
431 using source_pids_view_type =
435 typename num_packets_per_lid_view_type::non_const_value_type;
436 using offset_type =
typename offsets_view_type::non_const_value_type;
437 using value_type = Kokkos::pair<int, LO>;
439 static_assert (std::is_same<LO, typename local_graph_type::data_type>::value,
440 "local_map_type::local_ordinal_type and "
441 "local_graph_type::data_type must be the same.");
443 local_graph_type local_graph;
444 local_map_type local_col_map;
445 exports_view_type exports;
446 num_packets_per_lid_view_type num_packets_per_lid;
447 export_lids_view_type export_lids;
448 source_pids_view_type source_pids;
449 offsets_view_type offsets;
471 static_cast<LO
> (local_graph.row_map.extent (0));
474 std::logic_error,
"local_graph.row_map.extent(0) = "
480 using ::Tpetra::Details::OrdinalTraits;
484 KOKKOS_INLINE_FUNCTION
void
485 join (
volatile value_type& dst,
const volatile value_type& src)
const
489 if (src.first != 0 && dst.first == 0) {
494 KOKKOS_INLINE_FUNCTION
495 void operator() (
const LO i, value_type& dst)
const
497 const size_t offset = offsets[i];
498 const LO export_lid = export_lids[i];
499 const size_t buf_size = exports.size();
500 const size_t num_packets_this_lid = num_packets_per_lid(i);
501 const size_t num_ent =
502 static_cast<size_t> (local_graph.row_map[export_lid+1]
503 - local_graph.row_map[export_lid]);
513 if (export_lid >=
static_cast<LO
>(local_graph.numRows())) {
514 if (dst.first != 0) {
515 dst = Kokkos::make_pair (1, i);
519 else if ((offset > buf_size || offset + num_packets_this_lid > buf_size)) {
520 if (dst.first != 0) {
521 dst = Kokkos::make_pair (2, i);
531 const auto row_beg = local_graph.row_map[export_lid];
532 const auto row_end = local_graph.row_map[export_lid + 1];
533 auto lids_in = Kokkos::subview (local_graph.entries,
534 Kokkos::make_pair (row_beg, row_end));
535 size_t num_ent_packed_this_row =
536 packRow (local_col_map, exports, lids_in,
537 source_pids, offset, num_ent, pack_pids);
538 if (num_ent_packed_this_row != num_packets_this_lid) {
539 if (dst.first != 0) {
540 dst = Kokkos::make_pair (3, i);
553template<
class Packet,
556 class BufferDeviceType>
560 const Kokkos::View<Packet*, BufferDeviceType>& exports,
563 >::input_array_type& num_packets_per_lid,
566 >::input_array_type& export_lids,
569 >::input_array_type& source_pids,
570 const Kokkos::View<const size_t*, BufferDeviceType>& offsets,
571 const bool pack_pids)
574 using execution_space =
typename LocalGraph::device_type::execution_space;
575 using range_type = Kokkos::RangePolicy<execution_space, LO>;
576 const char prefix[] =
"Tpetra::Details::PackCrsGraphImpl::do_pack: ";
578 if (export_lids.extent (0) != 0) {
580 (
static_cast<size_t> (offsets.extent (0)) !=
581 static_cast<size_t> (export_lids.extent (0) + 1),
582 std::invalid_argument,
prefix <<
"offsets.extent(0) = "
583 << offsets.extent (0) <<
" != export_lids.extent(0) (= "
584 << export_lids.extent (0) <<
") + 1.");
586 (export_lids.extent (0) != num_packets_per_lid.extent (0),
587 std::invalid_argument,
prefix <<
"export_lids.extent(0) = " <<
588 export_lids.extent (0) <<
" != num_packets_per_lid.extent(0) = "
589 << num_packets_per_lid.extent (0) <<
".");
594 (pack_pids && exports.extent (0) != 0 &&
595 source_pids.extent (0) == 0, std::invalid_argument,
prefix <<
596 "pack_pids is true, and exports.extent(0) = " <<
597 exports.extent (0) <<
" != 0, meaning that we need to pack at "
598 "least one graph entry, but source_pids.extent(0) = 0.");
605 num_packets_per_lid, export_lids,
606 source_pids, offsets, pack_pids);
608 typename pack_functor_type::value_type
result;
609 range_type
range (0, num_packets_per_lid.extent (0));
615 std::ostringstream
os;
617 os <<
"invalid local row index";
619 else if (
result.first == 2) {
620 os <<
"invalid offset";
623 (
true, std::runtime_error,
prefix <<
"PackCrsGraphFunctor "
624 "reported error code " <<
result.first <<
" (" <<
os.str ()
625 <<
") for the first bad row " <<
result.second <<
".");
655template<
typename LO,
typename GO,
typename NT>
666 >& num_packets_per_lid,
676 const bool pack_pids)
680 using packet_type =
typename crs_graph_type::packet_type;
681 using buffer_device_type =
typename crs_graph_type::buffer_device_type;
682 using exports_view_type = Kokkos::DualView<packet_type*, buffer_device_type>;
683 using local_graph_device_type =
typename crs_graph_type::local_graph_device_type;
685 const char prefix[] =
"Tpetra::Details::packCrsGraph: ";
686 constexpr bool debug =
false;
688 local_graph_device_type local_graph =
sourceGraph.getLocalGraphDevice ();
689 local_map_type local_col_map =
sourceGraph.getColMap ()->getLocalMap ();
699 std::invalid_argument,
prefix <<
"num_export_lids.extent(0) = "
701 << num_packets_per_lid.extent (0) <<
".");
704 (num_packets_per_lid.data () ==
nullptr, std::invalid_argument,
706 "num_packets_per_lid.data() = "
707 << num_packets_per_lid.data () <<
" == NULL.");
711 exports = exports_view_type (
"exports", 0);
725 if (
count >
size_t (exports.extent (0))) {
726 exports = exports_view_type (
"exports",
count);
728 std::ostringstream
os;
729 os <<
"*** exports resized to " <<
count << std::endl;
730 std::cerr <<
os.str ();
734 std::ostringstream
os;
735 os <<
"*** count: " <<
count <<
", exports.extent(0): "
736 << exports.extent (0) << std::endl;
737 std::cerr <<
os.str ();
744 (pack_pids && exports.extent (0) != 0 &&
746 "pack_pids is true, and exports.extent(0) = " <<
747 exports.extent (0) <<
" != 0, meaning that we need to pack at least "
748 "one graph entry, but export_pids.extent(0) = 0.");
750 exports.modify_device ();
753 (local_graph, local_col_map,
exports_d, num_packets_per_lid,
760template<
typename LO,
typename GO,
typename NT>
765 const Teuchos::ArrayView<const LO>&
exportLIDs,
768 using Kokkos::HostSpace;
769 using Kokkos::MemoryUnmanaged;
772 using packet_type =
typename crs_graph_type::packet_type;
773 using BDT =
typename crs_graph_type::buffer_device_type;
784 "num_packets_per_lid");
793 Kokkos::DualView<packet_type*, BDT>
exports_dv;
794 constexpr bool pack_pids =
false;
800 "num_packets_per_lid_d's non_const_value_type should be size_t.");
805 "num_packets_per_lid_d's BDT should be size_t.");
810 "export_lids_d's device_type should be BDT.");
815 "export_pids_d's non_const_value_type should be int.");
820 "export_pids_d's device_type should be BDT.");
822 PackCrsGraphImpl::packCrsGraph
838 if (
static_cast<size_t> (exports.size ()) !=
839 static_cast<size_t> (
exports_dv.extent (0))) {
843 exports_h (exports.getRawPtr (), exports.size ());
849template<
typename LO,
typename GO,
typename NT>
852 const Kokkos::DualView<
856 const Kokkos::DualView<
866 > num_packets_per_lid,
868 const bool pack_pids)
872 using BDT =
typename crs_graph_type::buffer_device_type;
873 using PT =
typename crs_graph_type::packet_type;
875 using LGT =
typename crs_graph_type::local_graph_device_type;
876 using LMT =
typename crs_graph_type::map_type::local_map_type;
877 const char prefix[] =
"Tpetra::Details::packCrsGraphNew: ";
880 const LMT local_col_map =
sourceGraph.getColMap ()->getLocalMap ();
888 static_cast<size_t> (export_lids.extent (0));
891 static_cast<size_t> (num_packets_per_lid.extent (0)),
892 std::invalid_argument,
prefix <<
"num_export_lids.extent(0) = "
894 << num_packets_per_lid.extent (0) <<
".");
897 num_packets_per_lid.view_device ().data () ==
nullptr,
899 <<
" != 0, but num_packets_per_lid.view_device().data() = nullptr.");
907 using offsets_type = Kokkos::View<size_t*, BDT>;
912 num_packets_per_lid.clear_sync_state ();
913 num_packets_per_lid.modify_device ();
914 using PackCrsGraphImpl::computeNumPacketsAndOffsets;
916 computeNumPacketsAndOffsets (offsets, num_packets_per_lid.view_device (),
918 export_lids.view_device (),
922 if (
count >
static_cast<size_t> (exports.extent (0))) {
930 (pack_pids && exports.extent (0) != 0 &&
932 "pack_pids is true, and exports.extent(0) = " <<
933 exports.extent (0) <<
" != 0, meaning that we need to pack at least "
934 "one graph entry, but export_pids.extent(0) = 0.");
936 exports.modify_device ();
937 using PackCrsGraphImpl::do_pack;
939 exports.view_device (),
940 num_packets_per_lid.view_device (),
941 export_lids.view_device (),
946template<
typename LO,
typename GO,
typename NT>
955 const Teuchos::ArrayView<const LO>&
exportLIDs,
956 const Teuchos::ArrayView<const int>&
sourcePIDs,
959 using Kokkos::HostSpace;
960 using Kokkos::MemoryUnmanaged;
963 using buffer_device_type =
typename crs_graph_type::buffer_device_type;
973 "num_packets_per_lid");
989 constexpr bool pack_pids =
true;
990 PackCrsGraphImpl::packCrsGraph
1004#define TPETRA_DETAILS_PACKCRSGRAPH_INSTANT( LO, GO, NT ) \
1006 Details::packCrsGraph<LO, GO, NT> ( \
1007 const CrsGraph<LO, GO, NT>&, \
1008 Teuchos::Array<CrsGraph<LO,GO,NT>::packet_type>&, \
1009 const Teuchos::ArrayView<size_t>&, \
1010 const Teuchos::ArrayView<const LO>&, \
1013 Details::packCrsGraphNew<LO, GO, NT> ( \
1014 const CrsGraph<LO, GO, NT>&, \
1015 const Kokkos::DualView< \
1017 CrsGraph<LO,GO,NT>::buffer_device_type>&, \
1018 const Kokkos::DualView< \
1020 CrsGraph<LO,GO,NT>::buffer_device_type>&, \
1022 CrsGraph<LO,GO,NT>::packet_type*, \
1023 CrsGraph<LO,GO,NT>::buffer_device_type>&, \
1026 CrsGraph<LO,GO,NT>::buffer_device_type>, \
1030 Details::packCrsGraphWithOwningPIDs<LO, GO, NT> ( \
1031 const CrsGraph<LO, GO, NT>&, \
1032 Kokkos::DualView<CrsGraph<LO,GO,NT>::packet_type*, CrsGraph<LO,GO,NT>::buffer_device_type>&, \
1033 const Teuchos::ArrayView<size_t>&, \
1034 const Teuchos::ArrayView<const LO>&, \
1035 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.