42 #ifndef TPETRA_DISTOBJECT_DEF_HPP 43 #define TPETRA_DISTOBJECT_DEF_HPP 45 #if TPETRA_USE_KOKKOS_DISTOBJECT 47 #include "Tpetra_ConfigDefs.hpp" 48 #include "Tpetra_Map.hpp" 49 #include "Tpetra_Import.hpp" 50 #include "Tpetra_Export.hpp" 51 #include "Tpetra_Distributor.hpp" 52 #include "Tpetra_DistObjectKA_decl.hpp" 55 template <
class Packet,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
56 DistObjectKA<Packet,LocalOrdinal,GlobalOrdinal,Node>::
57 DistObjectKA (
const Teuchos::RCP<
const Map<LocalOrdinal,GlobalOrdinal,Node> >& map)
60 #ifdef HAVE_TPETRA_TRANSFER_TIMERS 63 using Teuchos::TimeMonitor;
65 RCP<Time> doXferTimer =
66 TimeMonitor::lookupCounter (
"Tpetra::DistObject::doTransfer");
67 if (doXferTimer.is_null ()) {
69 TimeMonitor::getNewCounter (
"Tpetra::DistObject::doTransfer");
71 doXferTimer_ = doXferTimer;
73 RCP<Time> copyAndPermuteTimer =
74 TimeMonitor::lookupCounter (
"Tpetra::DistObject::copyAndPermute");
75 if (copyAndPermuteTimer.is_null ()) {
77 TimeMonitor::getNewCounter (
"Tpetra::DistObject::copyAndPermute");
79 copyAndPermuteTimer_ = copyAndPermuteTimer;
81 RCP<Time> packAndPrepareTimer =
82 TimeMonitor::lookupCounter (
"Tpetra::DistObject::packAndPrepare");
83 if (packAndPrepareTimer.is_null ()) {
85 TimeMonitor::getNewCounter (
"Tpetra::DistObject::packAndPrepare");
87 packAndPrepareTimer_ = packAndPrepareTimer;
89 RCP<Time> doPostsAndWaitsTimer =
90 TimeMonitor::lookupCounter (
"Tpetra::DistObject::doPostsAndWaits");
91 if (doPostsAndWaitsTimer.is_null ()) {
92 doPostsAndWaitsTimer =
93 TimeMonitor::getNewCounter (
"Tpetra::DistObject::doPostsAndWaits");
95 doPostsAndWaitsTimer_ = doPostsAndWaitsTimer;
97 RCP<Time> unpackAndCombineTimer =
98 TimeMonitor::lookupCounter (
"Tpetra::DistObject::unpackAndCombine");
99 if (unpackAndCombineTimer.is_null ()) {
100 unpackAndCombineTimer =
101 TimeMonitor::getNewCounter (
"Tpetra::DistObject::unpackAndCombine");
103 unpackAndCombineTimer_ = unpackAndCombineTimer;
104 #endif // HAVE_TPETRA_TRANSFER_TIMERS 107 template <
class Packet,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
108 DistObjectKA<Packet,LocalOrdinal,GlobalOrdinal,Node>::
109 DistObjectKA (
const DistObjectKA<Packet,LocalOrdinal,GlobalOrdinal,Node>& rhs)
113 template <
class Packet,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
114 DistObjectKA<Packet,LocalOrdinal,GlobalOrdinal,Node>::~DistObjectKA()
117 template <
class Packet,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
119 DistObjectKA<Packet,LocalOrdinal,GlobalOrdinal,Node>::description ()
const 121 using Teuchos::TypeNameTraits;
123 std::ostringstream os;
124 os <<
"Tpetra::DistObject<" 125 << TypeNameTraits<Packet>::name ()
126 <<
", " << TypeNameTraits<LocalOrdinal>::name ()
127 <<
", " << TypeNameTraits<GlobalOrdinal>::name ()
128 <<
", " << TypeNameTraits<Node>::name ()
133 template <
class Packet,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
135 DistObjectKA<Packet,LocalOrdinal,GlobalOrdinal,Node>::
136 describe (Teuchos::FancyOStream &out,
137 const Teuchos::EVerbosityLevel verbLevel)
const 139 using Teuchos::rcpFromRef;
142 const Teuchos::EVerbosityLevel vl = (verbLevel == Teuchos::VERB_DEFAULT) ?
143 Teuchos::VERB_LOW : verbLevel;
145 if (vl != Teuchos::VERB_NONE) {
146 out << this->description () << endl;
147 Teuchos::OSTab tab (rcpFromRef (out));
148 out <<
"Export buffer size (in packets): " << exports_.size() << endl
149 <<
"Import buffer size (in packets): " << imports_.size() << endl
150 <<
"Map over which this object is distributed:" << endl;
151 map_->describe (out, vl);
155 template <
class Packet,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
160 TEUCHOS_TEST_FOR_EXCEPTION(
true, std::logic_error,
161 "Tpetra::DistObject::removeEmptyProcessesInPlace: Not implemented");
164 template<
class DistObjectType>
167 const Teuchos::RCP<
const Map<
typename DistObjectType::local_ordinal_type,
168 typename DistObjectType::global_ordinal_type,
169 typename DistObjectType::node_type> >& newMap)
171 input->removeEmptyProcessesInPlace (newMap);
172 if (newMap.is_null ()) {
173 input = Teuchos::null;
177 template<
class DistObjectType>
182 typedef typename DistObjectType::local_ordinal_type LO;
183 typedef typename DistObjectType::global_ordinal_type GO;
184 typedef typename DistObjectType::node_type NT;
185 typedef Map<LO, GO, NT> map_type;
187 RCP<const map_type> newMap = input->getMap ()->removeEmptyProcesses ();
188 removeEmptyProcessesInPlace<DistObjectType> (input, newMap);
191 template <
class Packet,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
193 DistObjectKA<Packet,LocalOrdinal,GlobalOrdinal,Node>::
194 doImport (
const SrcDistObject& source,
195 const Import<LocalOrdinal,GlobalOrdinal,Node>& importer,
198 TEUCHOS_TEST_FOR_EXCEPTION(*getMap() != *importer.getTargetMap(),
199 std::invalid_argument,
"doImport: The target DistObject's Map is not " 200 "identical to the Import's target Map.");
201 #ifdef HAVE_TPETRA_DEBUG 203 typedef DistObjectKA<Packet,LocalOrdinal,GlobalOrdinal,Node> this_type;
204 const this_type* srcDistObj =
dynamic_cast<const this_type*
> (&source);
205 TEUCHOS_TEST_FOR_EXCEPTION(
206 srcDistObj != NULL && * (srcDistObj->getMap ()) != *importer.getSourceMap(),
207 std::invalid_argument,
"doImport: The source is a DistObject, yet its " 208 "Map is not identical to the Import's source Map.");
210 #endif // HAVE_TPETRA_DEBUG 211 size_t numSameIDs = importer.getNumSameIDs ();
213 typedef Teuchos::ArrayView<const LocalOrdinal> view_type;
214 const view_type exportLIDs = importer.getExportLIDs();
215 const view_type remoteLIDs = importer.getRemoteLIDs();
216 const view_type permuteToLIDs = importer.getPermuteToLIDs();
217 const view_type permuteFromLIDs = importer.getPermuteFromLIDs();
218 this->doTransfer (source, CM, numSameIDs, permuteToLIDs, permuteFromLIDs,
219 remoteLIDs, exportLIDs, importer.getDistributor (),
223 template <
class Packet,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
225 DistObjectKA<Packet,LocalOrdinal,GlobalOrdinal,Node>::
226 doExport (
const SrcDistObject& source,
227 const Export<LocalOrdinal,GlobalOrdinal,Node>& exporter,
230 TEUCHOS_TEST_FOR_EXCEPTION(
231 *getMap() != *exporter.getTargetMap(), std::invalid_argument,
232 "doExport: The target DistObject's Map is not identical to the Export's " 234 #ifdef HAVE_TPETRA_DEBUG 236 typedef DistObjectKA<Packet,LocalOrdinal,GlobalOrdinal,Node> this_type;
237 const this_type* srcDistObj =
dynamic_cast<const this_type*
> (&source);
238 TEUCHOS_TEST_FOR_EXCEPTION(
239 srcDistObj != NULL && * (srcDistObj->getMap ()) != *exporter.getSourceMap(),
240 std::invalid_argument,
"doExport: The source is a DistObject, yet its " 241 "Map is not identical to the Export's source Map.");
243 #endif // HAVE_TPETRA_DEBUG 244 size_t numSameIDs = exporter.getNumSameIDs();
246 typedef ArrayView<const LocalOrdinal> view_type;
247 view_type exportLIDs = exporter.getExportLIDs();
248 view_type remoteLIDs = exporter.getRemoteLIDs();
249 view_type permuteToLIDs = exporter.getPermuteToLIDs();
250 view_type permuteFromLIDs = exporter.getPermuteFromLIDs();
251 doTransfer (source, CM, numSameIDs, permuteToLIDs, permuteFromLIDs, remoteLIDs,
252 exportLIDs, exporter.getDistributor (), DoForward);
255 template <
class Packet,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
257 DistObjectKA<Packet,LocalOrdinal,GlobalOrdinal,Node>::
258 doImport (
const SrcDistObject& source,
259 const Export<LocalOrdinal,GlobalOrdinal,Node> & exporter,
262 TEUCHOS_TEST_FOR_EXCEPTION(
263 *getMap() != *exporter.getSourceMap(), std::invalid_argument,
264 "doImport (reverse mode): The target DistObject's Map is not identical " 265 "to the Export's source Map.");
266 #ifdef HAVE_TPETRA_DEBUG 268 typedef DistObjectKA<Packet,LocalOrdinal,GlobalOrdinal,Node> this_type;
269 const this_type* srcDistObj =
dynamic_cast<const this_type*
> (&source);
270 TEUCHOS_TEST_FOR_EXCEPTION(
271 srcDistObj != NULL && * (srcDistObj->getMap ()) != *exporter.getTargetMap(),
272 std::invalid_argument,
273 "doImport (reverse mode): The source is a DistObject, yet its " 274 "Map is not identical to the Export's target Map.");
276 #endif // HAVE_TPETRA_DEBUG 277 size_t numSameIDs = exporter.getNumSameIDs();
279 typedef ArrayView<const LocalOrdinal> view_type;
280 view_type exportLIDs = exporter.getRemoteLIDs();
281 view_type remoteLIDs = exporter.getExportLIDs();
282 view_type permuteToLIDs = exporter.getPermuteFromLIDs();
283 view_type permuteFromLIDs = exporter.getPermuteToLIDs();
284 doTransfer (source, CM, numSameIDs, permuteToLIDs, permuteFromLIDs, remoteLIDs,
285 exportLIDs, exporter.getDistributor (), DoReverse);
288 template <
class Packet,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
290 DistObjectKA<Packet,LocalOrdinal,GlobalOrdinal,Node>::
291 doExport (
const SrcDistObject& source,
292 const Import<LocalOrdinal,GlobalOrdinal,Node> & importer,
295 TEUCHOS_TEST_FOR_EXCEPTION(
296 *getMap() != *importer.getSourceMap(), std::invalid_argument,
297 "doExport (reverse mode): The target object's Map " 298 "is not identical to the Import's source Map.");
299 #ifdef HAVE_TPETRA_DEBUG 301 typedef DistObjectKA<Packet,LocalOrdinal,GlobalOrdinal,Node> this_type;
302 const this_type* srcDistObj =
dynamic_cast<const this_type*
> (&source);
303 TEUCHOS_TEST_FOR_EXCEPTION(
304 srcDistObj != NULL && * (srcDistObj->getMap ()) != *importer.getTargetMap(),
305 std::invalid_argument,
306 "doExport (reverse mode): The source is a DistObject, yet its " 307 "Map is not identical to the Import's target Map.");
309 #endif // HAVE_TPETRA_DEBUG 310 size_t numSameIDs = importer.getNumSameIDs();
312 typedef ArrayView<const LocalOrdinal> view_type;
313 view_type exportLIDs = importer.getRemoteLIDs();
314 view_type remoteLIDs = importer.getExportLIDs();
315 view_type permuteToLIDs = importer.getPermuteFromLIDs();
316 view_type permuteFromLIDs = importer.getPermuteToLIDs();
317 doTransfer (source, CM, numSameIDs, permuteToLIDs, permuteFromLIDs, remoteLIDs,
318 exportLIDs, importer.getDistributor (), DoReverse);
321 template <
class Packet,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
323 DistObjectKA<Packet,LocalOrdinal,GlobalOrdinal,Node>::isDistributed()
const {
324 return map_->isDistributed ();
327 template <
class Packet,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
329 DistObjectKA<Packet,LocalOrdinal,GlobalOrdinal,Node>::
330 constantNumberOfPackets ()
const {
334 template <
class Packet,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
336 DistObjectKA<Packet,LocalOrdinal,GlobalOrdinal,Node>::
337 doTransfer (
const SrcDistObject& src,
340 const Teuchos::ArrayView<const LocalOrdinal>& permuteToLIDs_,
341 const Teuchos::ArrayView<const LocalOrdinal>& permuteFromLIDs_,
342 const Teuchos::ArrayView<const LocalOrdinal>& remoteLIDs_,
343 const Teuchos::ArrayView<const LocalOrdinal>& exportLIDs_,
348 using Kokkos::Compat::getArrayView;
349 using Kokkos::Compat::getConstArrayView;
350 using Kokkos::Compat::getKokkosViewDeepCopy;
351 using Kokkos::Compat::create_const_view;
353 #ifdef HAVE_TPETRA_TRANSFER_TIMERS 354 Teuchos::TimeMonitor doXferMon (*doXferTimer_);
355 #endif // HAVE_TPETRA_TRANSFER_TIMERS 358 typedef Kokkos::View<const LocalOrdinal*, execution_space> lo_const_view_type;
359 lo_const_view_type permuteToLIDs =
360 getKokkosViewDeepCopy<execution_space> (permuteToLIDs_);
361 lo_const_view_type permuteFromLIDs =
362 getKokkosViewDeepCopy<execution_space> (permuteFromLIDs_);
363 lo_const_view_type remoteLIDs =
364 getKokkosViewDeepCopy<execution_space> (remoteLIDs_);
365 lo_const_view_type exportLIDs =
366 getKokkosViewDeepCopy<execution_space> (exportLIDs_);
368 TEUCHOS_TEST_FOR_EXCEPTION(
369 ! checkSizes (src), std::invalid_argument,
370 "Tpetra::DistObject::doTransfer(): checkSizes() indicates that the " 371 "destination object is not a legal target for redistribution from the " 372 "source object. This probably means that they do not have the same " 373 "dimensions. For example, MultiVectors must have the same number of " 374 "rows and columns.");
375 KokkosClassic::ReadWriteOption rwo = KokkosClassic::ReadWrite;
377 const size_t numIDsToWrite = numSameIDs +
378 as<size_t> (permuteToLIDs.size ()) +
379 as<size_t> (remoteLIDs.size ());
380 if (numIDsToWrite == this->getMap ()->getNodeNumElements ()) {
388 rwo = KokkosClassic::WriteOnly;
399 typedef DistObjectKA<Packet,LocalOrdinal,GlobalOrdinal,Node> this_type;
400 const this_type* srcDistObj =
dynamic_cast<const this_type*
> (&src);
401 if (srcDistObj != NULL) {
402 srcDistObj->createViews ();
417 this->createViewsNonConst (rwo);
419 if (numSameIDs + permuteToLIDs.size()) {
420 #ifdef HAVE_TPETRA_TRANSFER_TIMERS 421 Teuchos::TimeMonitor copyAndPermuteMon (*copyAndPermuteTimer_);
422 #endif // HAVE_TPETRA_TRANSFER_TIMERS 424 copyAndPermute (src, numSameIDs, permuteToLIDs, permuteFromLIDs);
435 size_t constantNumPackets = this->constantNumberOfPackets ();
442 if (constantNumPackets == 0) {
443 Kokkos::Compat::realloc (numExportPacketsPerLID_, exportLIDs.size ());
444 Kokkos::Compat::realloc (numImportPacketsPerLID_, remoteLIDs.size ());
448 #ifdef HAVE_TPETRA_TRANSFER_TIMERS 449 Teuchos::TimeMonitor packAndPrepareMon (*packAndPrepareTimer_);
450 #endif // HAVE_TPETRA_TRANSFER_TIMERS 456 packAndPrepare (src, exportLIDs, exports_, numExportPacketsPerLID_,
457 constantNumPackets, distor);
465 if (srcDistObj != NULL) {
466 srcDistObj->releaseViews ();
471 if (constantNumPackets != 0) {
476 const size_t rbufLen = remoteLIDs.size() * constantNumPackets;
477 if (as<size_t> (imports_.size()) != rbufLen) {
478 Kokkos::Compat::realloc (imports_, rbufLen);
483 typename Kokkos::View<size_t*,execution_space>::HostMirror host_numExportPacketsPerLID = Kokkos::create_mirror_view (numExportPacketsPerLID_);
484 typename Kokkos::View<size_t*,execution_space>::HostMirror host_numImportPacketsPerLID = Kokkos::create_mirror_view (numImportPacketsPerLID_);
490 bool needCommunication =
true;
491 if (revOp == DoReverse && ! isDistributed ()) {
492 needCommunication =
false;
501 else if (revOp == DoForward && srcDistObj != NULL &&
502 ! srcDistObj->isDistributed ()) {
503 needCommunication =
false;
506 if (needCommunication) {
507 if (revOp == DoReverse) {
508 #ifdef HAVE_TPETRA_TRANSFER_TIMERS 509 Teuchos::TimeMonitor doPostsAndWaitsMon (*doPostsAndWaitsTimer_);
510 #endif // HAVE_TPETRA_TRANSFER_TIMERS 511 if (constantNumPackets == 0) {
512 distor.doReversePostsAndWaits (create_const_view (host_numExportPacketsPerLID),
514 host_numImportPacketsPerLID);
515 size_t totalImportPackets = 0;
516 for (view_size_type i = 0; i < numImportPacketsPerLID_.size(); ++i) {
517 totalImportPackets += host_numImportPacketsPerLID[i];
519 Kokkos::Compat::realloc (imports_, totalImportPackets);
520 distor.doReversePostsAndWaits (create_const_view (exports_),
521 getArrayView (host_numExportPacketsPerLID),
523 getArrayView (host_numImportPacketsPerLID));
526 distor.doReversePostsAndWaits (create_const_view (exports_),
532 #ifdef HAVE_TPETRA_TRANSFER_TIMERS 533 Teuchos::TimeMonitor doPostsAndWaitsMon (*doPostsAndWaitsTimer_);
534 #endif // HAVE_TPETRA_TRANSFER_TIMERS 535 if (constantNumPackets == 0) {
536 distor.doPostsAndWaits (create_const_view (host_numExportPacketsPerLID), 1,
537 host_numImportPacketsPerLID);
538 size_t totalImportPackets = 0;
539 for (view_size_type i = 0; i < numImportPacketsPerLID_.size(); ++i) {
540 totalImportPackets += host_numImportPacketsPerLID[i];
542 Kokkos::Compat::realloc (imports_, totalImportPackets);
543 distor.doPostsAndWaits (create_const_view (exports_),
544 getArrayView (host_numExportPacketsPerLID),
546 getArrayView (host_numImportPacketsPerLID));
549 distor.doPostsAndWaits (create_const_view (exports_),
559 #ifdef HAVE_TPETRA_TRANSFER_TIMERS 560 Teuchos::TimeMonitor unpackAndCombineMon (*unpackAndCombineTimer_);
561 #endif // HAVE_TPETRA_TRANSFER_TIMERS 562 unpackAndCombine (remoteLIDs, imports_, numImportPacketsPerLID_,
563 constantNumPackets, distor, CM);
568 this->releaseViews ();
571 template <
class Packet,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
573 DistObjectKA<Packet,LocalOrdinal,GlobalOrdinal,Node>::print (std::ostream &os)
const 575 using Teuchos::FancyOStream;
576 using Teuchos::getFancyOStream;
578 using Teuchos::rcpFromRef;
581 RCP<FancyOStream> out = getFancyOStream (rcpFromRef (os));
582 this->describe (*out, Teuchos::VERB_DEFAULT);
585 template <
class Packet,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
587 DistObjectKA<Packet,LocalOrdinal,GlobalOrdinal,Node>::createViews ()
const 590 template <
class Packet,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
592 DistObjectKA<Packet,LocalOrdinal,GlobalOrdinal,Node>::
593 createViewsNonConst (KokkosClassic::ReadWriteOption )
596 template <
class Packet,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
598 DistObjectKA<Packet,LocalOrdinal,GlobalOrdinal,Node>::
599 releaseViews ()
const 602 #define TPETRA_DISTOBJECTKA_INSTANT(SCALAR, LO, GO, NODE) \ 604 template class DistObjectKA< SCALAR , LO , GO , NODE >; 607 #define TPETRA_DISTOBJECTKA_INSTANT_CHAR(LO, GO, NODE) \ 609 template class DistObjectKA< char , LO , GO , NODE >; 616 #define TPETRA_DISTOBJECTKA_INSTANT(SCALAR, LO, GO, NODE) 617 #define TPETRA_DISTOBJECTKA_INSTANT_CHAR(LO, GO, NODE) Namespace Tpetra contains the class and methods constituting the Tpetra library.
void removeEmptyProcessesInPlace(Teuchos::RCP< DistObjectType > &input, const Teuchos::RCP< const Map< typename DistObjectType::local_ordinal_type, typename DistObjectType::global_ordinal_type, typename DistObjectType::node_type > > &newMap)
Remove processes which contain no elements in this object's Map.
void deep_copy(const LittleBlock< ST2, LO > &dst, const LittleBlock< ST1, LO > &src, typename std::enable_if< std::is_convertible< ST1, ST2 >::value &&!std::is_const< ST2 >::value, int >::type *=NULL)
Copy the LittleBlock src into the LittleBlock dst.
Insert new values that don't currently exist.
CombineMode
Rule for combining data in an Import or Export.
Replace existing values with new values.
Replace old values with zero.