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 <<
".");
599template <
typename LO,
typename GO,
typename NT>
614 const bool pack_pids) {
617 using packet_type =
typename crs_graph_type::packet_type;
618 using buffer_device_type =
typename crs_graph_type::buffer_device_type;
619 using exports_view_type = Kokkos::DualView<packet_type*, buffer_device_type>;
620 using local_graph_device_type =
typename crs_graph_type::local_graph_device_type;
622 const char prefix[] =
"Tpetra::Details::packCrsGraph: ";
623 constexpr bool debug =
false;
625 local_graph_device_type local_graph =
sourceGraph.getLocalGraphDevice();
626 local_map_type local_col_map =
sourceGraph.getColMap()->getLocalMap();
635 std::invalid_argument,
prefix <<
"num_export_lids.extent(0) = " <<
num_export_lids <<
" != num_packets_per_lid.extent(0) = " << num_packets_per_lid.extent(0) <<
".");
639 "num_packets_per_lid.data() = "
640 << num_packets_per_lid.data() <<
" == NULL.");
644 exports = exports_view_type(
"exports", 0);
658 if (count >
size_t(exports.extent(0))) {
659 exports = exports_view_type(
"exports", count);
661 std::ostringstream
os;
662 os <<
"*** exports resized to " << count << std::endl;
663 std::cerr <<
os.str();
667 std::ostringstream
os;
668 os <<
"*** count: " << count <<
", exports.extent(0): "
669 << exports.extent(0) << std::endl;
670 std::cerr <<
os.str();
678 std::invalid_argument,
prefix <<
"pack_pids is true, and exports.extent(0) = " << exports.extent(0) <<
" != 0, meaning that we need to pack at least "
679 "one graph entry, but export_pids.extent(0) = 0.");
681 exports.modify_device();
690template <
typename LO,
typename GO,
typename NT>
694 const Teuchos::ArrayView<const LO>&
exportLIDs,
696 using Kokkos::HostSpace;
697 using Kokkos::MemoryUnmanaged;
700 using packet_type =
typename crs_graph_type::packet_type;
701 using BDT =
typename crs_graph_type::buffer_device_type;
712 "num_packets_per_lid");
721 Kokkos::DualView<packet_type*, BDT>
exports_dv;
722 constexpr bool pack_pids =
false;
724 static_assert(std::is_same<
727 "num_packets_per_lid_d's non_const_value_type should be size_t.");
728 static_assert(std::is_same<
731 "num_packets_per_lid_d's BDT should be size_t.");
732 static_assert(std::is_same<
735 "export_lids_d's device_type should be BDT.");
736 static_assert(std::is_same<
739 "export_pids_d's non_const_value_type should be int.");
740 static_assert(std::is_same<
743 "export_pids_d's device_type should be BDT.");
755 using execution_space =
typename BDT::execution_space;
763 if (
static_cast<size_t>(exports.size()) !=
768 exports_h(exports.getRawPtr(), exports.size());
771 execution_space().fence();
776template <
typename LO,
typename GO,
typename NT>
778 const Kokkos::DualView<
781 const Kokkos::DualView<
792 const bool pack_pids) {
795 using BDT =
typename crs_graph_type::buffer_device_type;
796 using PT =
typename crs_graph_type::packet_type;
798 using LGT =
typename crs_graph_type::local_graph_device_type;
799 using LMT =
typename crs_graph_type::map_type::local_map_type;
800 const char prefix[] =
"Tpetra::Details::packCrsGraphNew: ";
811 static_cast<size_t>(export_lids.extent(0));
813 static_cast<size_t>(num_packets_per_lid.extent(0)),
814 std::invalid_argument,
prefix <<
"num_export_lids.extent(0) = " <<
num_export_lids <<
" != num_packets_per_lid.extent(0) = " << num_packets_per_lid.extent(0) <<
".");
816 num_packets_per_lid.view_device().data() ==
nullptr,
817 std::invalid_argument,
prefix <<
"num_export_lids = " <<
num_export_lids <<
" != 0, but num_packets_per_lid.view_device().data() = nullptr.");
825 using offsets_type = Kokkos::View<size_t*, BDT>;
830 num_packets_per_lid.clear_sync_state();
831 num_packets_per_lid.modify_device();
832 using PackCrsGraphImpl::computeNumPacketsAndOffsets;
834 computeNumPacketsAndOffsets(offsets, num_packets_per_lid.view_device(),
836 export_lids.view_device(),
840 if (count >
static_cast<size_t>(exports.extent(0))) {
849 std::invalid_argument,
prefix <<
"pack_pids is true, and exports.extent(0) = " << exports.extent(0) <<
" != 0, meaning that we need to pack at least "
850 "one graph entry, but export_pids.extent(0) = 0.");
852 exports.modify_device();
853 using PackCrsGraphImpl::do_pack;
855 exports.view_device(),
856 num_packets_per_lid.view_device(),
857 export_lids.view_device(),
862template <
typename LO,
typename GO,
typename NT>
868 const Teuchos::ArrayView<const LO>&
exportLIDs,
869 const Teuchos::ArrayView<const int>&
sourcePIDs,
871 using Kokkos::HostSpace;
872 using Kokkos::MemoryUnmanaged;
875 using buffer_device_type =
typename crs_graph_type::buffer_device_type;
885 "num_packets_per_lid");
901 constexpr bool pack_pids =
true;
909 using execution_space =
typename buffer_device_type::execution_space;
910 Kokkos::deep_copy(execution_space(),
912 execution_space().fence();
918#define TPETRA_DETAILS_PACKCRSGRAPH_INSTANT(LO, GO, NT) \
920 Details::packCrsGraph<LO, GO, NT>( \
921 const CrsGraph<LO, GO, NT>&, \
922 Teuchos::Array<CrsGraph<LO, GO, NT>::packet_type>&, \
923 const Teuchos::ArrayView<size_t>&, \
924 const Teuchos::ArrayView<const LO>&, \
927 Details::packCrsGraphNew<LO, GO, NT>( \
928 const CrsGraph<LO, GO, NT>&, \
929 const Kokkos::DualView< \
931 CrsGraph<LO, GO, NT>::buffer_device_type>&, \
932 const Kokkos::DualView< \
934 CrsGraph<LO, GO, NT>::buffer_device_type>&, \
936 CrsGraph<LO, GO, NT>::packet_type*, \
937 CrsGraph<LO, GO, NT>::buffer_device_type>&, \
940 CrsGraph<LO, GO, NT>::buffer_device_type>, \
944 Details::packCrsGraphWithOwningPIDs<LO, GO, NT>( \
945 const CrsGraph<LO, GO, NT>&, \
946 Kokkos::DualView<CrsGraph<LO, GO, NT>::packet_type*, CrsGraph<LO, GO, NT>::buffer_device_type>&, \
947 const Teuchos::ArrayView<size_t>&, \
948 const Teuchos::ArrayView<const LO>&, \
949 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.