13#include "Teuchos_StandardParameterEntryValidators.hpp"
25 }
else if (
sendType == DISTRIBUTOR_SEND) {
27 }
else if (
sendType == DISTRIBUTOR_ALLTOALL) {
30#if defined(HAVE_TPETRA_MPI)
35#if defined(HAVE_TPETRACORE_MPI_ADVANCE)
37 return "MpiAdvanceAlltoall";
39 return "MpiAdvanceNbralltoallv";
45 "EDistributorSendType enum value "
52 if (
s ==
"Isend")
return DISTRIBUTOR_ISEND;
53 if (
s ==
"Send")
return DISTRIBUTOR_SEND;
54 if (
s ==
"Alltoall")
return DISTRIBUTOR_ALLTOALL;
55#if defined(HAVE_TPETRA_MPI)
58#if defined(HAVE_TPETRACORE_MPI_ADVANCE)
77 case Details::DISTRIBUTOR_NOT_INITIALIZED:
78 return "Not initialized yet";
79 case Details::DISTRIBUTOR_INITIALIZED_BY_CREATE_FROM_SENDS:
80 return "By createFromSends";
81 case Details::DISTRIBUTOR_INITIALIZED_BY_CREATE_FROM_RECVS:
82 return "By createFromRecvs";
83 case Details::DISTRIBUTOR_INITIALIZED_BY_CREATE_FROM_SENDS_N_RECVS:
84 return "By createFromSendsAndRecvs";
85 case Details::DISTRIBUTOR_INITIALIZED_BY_REVERSE:
86 return "By createReverseDistributor";
87 case Details::DISTRIBUTOR_INITIALIZED_BY_COPY:
88 return "By copy constructor";
94DistributorPlan::DistributorPlan(Teuchos::RCP<
const Teuchos::Comm<int>> comm)
101 howInitialized_(DISTRIBUTOR_NOT_INITIALIZED)
102 , reversePlan_(Teuchos::
null)
104 , sendMessageToSelf_(
false)
105 , numSendsToOtherProcs_(0)
108 , totalReceiveLength_(0) {
111DistributorPlan::DistributorPlan(
const DistributorPlan& otherPlan)
112 : comm_(otherPlan.comm_)
114#if defined(HAVE_TPETRACORE_MPI_ADVANCE)
115 mpixComm_(otherPlan.mpixComm_)
118 howInitialized_(DISTRIBUTOR_INITIALIZED_BY_COPY)
119 , reversePlan_(otherPlan.reversePlan_)
120 , sendType_(otherPlan.sendType_)
121 , sendMessageToSelf_(otherPlan.sendMessageToSelf_)
122 , numSendsToOtherProcs_(otherPlan.numSendsToOtherProcs_)
123 , procIdsToSendTo_(otherPlan.procIdsToSendTo_)
124 , startsTo_(otherPlan.startsTo_)
125 , lengthsTo_(otherPlan.lengthsTo_)
126 , maxSendLength_(otherPlan.maxSendLength_)
127 , indicesTo_(otherPlan.indicesTo_)
128 , numReceives_(otherPlan.numReceives_)
129 , totalReceiveLength_(otherPlan.totalReceiveLength_)
130 , lengthsFrom_(otherPlan.lengthsFrom_)
131 , procsFrom_(otherPlan.procsFrom_)
132 , startsFrom_(otherPlan.startsFrom_)
133 , indicesFrom_(otherPlan.indicesFrom_)
134#if defined(HAVE_TPETRACORE_MPI)
135 , roots_(otherPlan.roots_)
140size_t DistributorPlan::createFromSends(
const Teuchos::ArrayView<const int>& exportProcIDs) {
142 using Teuchos::outArg;
143 using Teuchos::REDUCE_MAX;
144 using Teuchos::reduceAll;
145 const char rawPrefix[] =
"Tpetra::DistributorPlan::createFromSends";
148 const size_t numExports = exportProcIDs.size();
149 const int myProcID = comm_->getRank();
150 const int numProcs = comm_->getSize();
194 for (
size_t i = 0; i < numExports; ++i) {
195 const int exportID = exportProcIDs[i];
196 if (exportID >= numProcs || exportID < 0) {
202 reduceAll<int, int>(*comm_, REDUCE_MAX, badID, outArg(gbl_badID));
203 TEUCHOS_TEST_FOR_EXCEPTION(gbl_badID >= 0, std::runtime_error, rawPrefix <<
"Proc " << gbl_badID <<
", perhaps among other processes, got a bad "
219 Teuchos::Array<size_t> starts(numProcs + 1, 0);
222 size_t numActive = 0;
223 int needSendBuff = 0;
225 for (
size_t i = 0; i < numExports; ++i) {
226 const int exportID = exportProcIDs[i];
241 if (needSendBuff == 0 && starts[exportID] > 1 &&
242 exportID != exportProcIDs[i - 1]) {
249#if defined(HAVE_TPETRA_PRINT_EFFICIENCY_WARNINGS)
251 int global_needSendBuff;
252 reduceAll<int, int>(*comm_, REDUCE_MAX, needSendBuff,
253 outArg(global_needSendBuff));
255 global_needSendBuff != 0,
256 "::createFromSends: Grouping export IDs together by process rank often "
257 "improves performance.");
263 if (starts[myProcID] != 0) {
264 sendMessageToSelf_ =
true;
266 sendMessageToSelf_ =
false;
271 numSendsToOtherProcs_ = 0;
274 for (
int i = 0; i < numProcs; ++i) {
276 ++numSendsToOtherProcs_;
282 indicesTo_.resize(0);
285 procIdsToSendTo_.assign(numSendsToOtherProcs_, 0);
286 startsTo_.assign(numSendsToOtherProcs_, 0);
287 lengthsTo_.assign(numSendsToOtherProcs_, 0);
294 size_t procIndex = 0;
295 for (
size_t i = 0; i < numSendsToOtherProcs_; ++i) {
296 while (exportProcIDs[procIndex] < 0) {
299 startsTo_[i] = procIndex;
300 int procID = exportProcIDs[procIndex];
301 procIdsToSendTo_[i] = procID;
302 procIndex += starts[procID];
307 if (numSendsToOtherProcs_ > 0) {
308 sort2(procIdsToSendTo_.begin(), procIdsToSendTo_.end(), startsTo_.begin());
312 for (
size_t i = 0; i < numSendsToOtherProcs_; ++i) {
313 int procID = procIdsToSendTo_[i];
314 lengthsTo_[i] = starts[procID];
315 if ((procID != myProcID) && (lengthsTo_[i] > maxSendLength_)) {
316 maxSendLength_ = lengthsTo_[i];
326 if (starts[0] == 0) {
327 numSendsToOtherProcs_ = 0;
329 numSendsToOtherProcs_ = 1;
331 for (Teuchos::Array<size_t>::iterator i = starts.begin() + 1,
332 im1 = starts.begin();
333 i != starts.end(); ++i) {
334 if (*i != 0) ++numSendsToOtherProcs_;
340 for (Teuchos::Array<size_t>::reverse_iterator ip1 = starts.rbegin(),
341 i = starts.rbegin() + 1;
342 i != starts.rend(); ++i) {
350 indicesTo_.resize(numActive);
352 for (
size_t i = 0; i < numExports; ++i) {
353 if (exportProcIDs[i] >= 0) {
355 indicesTo_[starts[exportProcIDs[i]]] = i;
357 ++starts[exportProcIDs[i]];
369 for (
int proc = numProcs - 1; proc != 0; --proc) {
370 starts[proc] = starts[proc - 1];
373 starts[numProcs] = numActive;
380 procIdsToSendTo_.resize(numSendsToOtherProcs_);
381 startsTo_.resize(numSendsToOtherProcs_);
382 lengthsTo_.resize(numSendsToOtherProcs_);
389 for (
int proc = 0; proc < numProcs; ++proc) {
390 if (starts[proc + 1] != starts[proc]) {
391 lengthsTo_[snd] = starts[proc + 1] - starts[proc];
392 startsTo_[snd] = starts[proc];
394 if ((proc != myProcID) && (lengthsTo_[snd] > maxSendLength_)) {
395 maxSendLength_ = lengthsTo_[snd];
397 procIdsToSendTo_[snd] = proc;
403 if (sendMessageToSelf_) {
404 --numSendsToOtherProcs_;
410#if defined(HAVE_TPETRA_MPI)
411 maybeInitializeRoots();
416 howInitialized_ = Details::DISTRIBUTOR_INITIALIZED_BY_CREATE_FROM_SENDS;
418 return totalReceiveLength_;
421void DistributorPlan::createFromRecvs(
const Teuchos::ArrayView<const int>& remoteProcIDs) {
422 *
this = *getReversePlan();
423 howInitialized_ = Details::DISTRIBUTOR_INITIALIZED_BY_CREATE_FROM_RECVS;
426void DistributorPlan::createFromSendsAndRecvs(
const Teuchos::ArrayView<const int>& exportProcIDs,
427 const Teuchos::ArrayView<const int>& remoteProcIDs) {
435 howInitialized_ = Tpetra::Details::DISTRIBUTOR_INITIALIZED_BY_CREATE_FROM_SENDS_N_RECVS;
437 int myProcID = comm_->getRank();
438 int numProcs = comm_->getSize();
440 const size_t numExportIDs = exportProcIDs.size();
441 Teuchos::Array<size_t> starts(numProcs + 1, 0);
443 size_t numActive = 0;
444 int needSendBuff = 0;
446 for (
size_t i = 0; i < numExportIDs; i++) {
447 if (needSendBuff == 0 && i && (exportProcIDs[i] < exportProcIDs[i - 1]))
449 if (exportProcIDs[i] >= 0) {
450 ++starts[exportProcIDs[i]];
455 sendMessageToSelf_ = (starts[myProcID] != 0) ? 1 : 0;
457 numSendsToOtherProcs_ = 0;
461 if (starts[0] == 0) {
462 numSendsToOtherProcs_ = 0;
464 numSendsToOtherProcs_ = 1;
466 for (Teuchos::Array<size_t>::iterator i = starts.begin() + 1,
467 im1 = starts.begin();
468 i != starts.end(); ++i) {
469 if (*i != 0) ++numSendsToOtherProcs_;
475 for (Teuchos::Array<size_t>::reverse_iterator ip1 = starts.rbegin(),
476 i = starts.rbegin() + 1;
477 i != starts.rend(); ++i) {
485 indicesTo_.resize(numActive);
487 for (
size_t i = 0; i < numExportIDs; ++i) {
488 if (exportProcIDs[i] >= 0) {
490 indicesTo_[starts[exportProcIDs[i]]] = i;
492 ++starts[exportProcIDs[i]];
495 for (
int proc = numProcs - 1; proc != 0; --proc) {
496 starts[proc] = starts[proc - 1];
499 starts[numProcs] = numActive;
500 procIdsToSendTo_.resize(numSendsToOtherProcs_);
501 startsTo_.resize(numSendsToOtherProcs_);
502 lengthsTo_.resize(numSendsToOtherProcs_);
505 for (
int proc = 0; proc < numProcs; ++proc) {
506 if (starts[proc + 1] != starts[proc]) {
507 lengthsTo_[snd] = starts[proc + 1] - starts[proc];
508 startsTo_[snd] = starts[proc];
510 if ((proc != myProcID) && (lengthsTo_[snd] > maxSendLength_)) {
511 maxSendLength_ = lengthsTo_[snd];
513 procIdsToSendTo_[snd] = proc;
519 numSendsToOtherProcs_ = 0;
522 for (
int i = 0; i < numProcs; ++i) {
524 ++numSendsToOtherProcs_;
530 indicesTo_.resize(0);
533 procIdsToSendTo_.assign(numSendsToOtherProcs_, 0);
534 startsTo_.assign(numSendsToOtherProcs_, 0);
535 lengthsTo_.assign(numSendsToOtherProcs_, 0);
542 size_t procIndex = 0;
543 for (
size_t i = 0; i < numSendsToOtherProcs_; ++i) {
544 while (exportProcIDs[procIndex] < 0) {
547 startsTo_[i] = procIndex;
548 int procID = exportProcIDs[procIndex];
549 procIdsToSendTo_[i] = procID;
550 procIndex += starts[procID];
555 if (numSendsToOtherProcs_ > 0) {
556 sort2(procIdsToSendTo_.begin(), procIdsToSendTo_.end(), startsTo_.begin());
560 for (
size_t i = 0; i < numSendsToOtherProcs_; ++i) {
561 int procID = procIdsToSendTo_[i];
562 lengthsTo_[i] = starts[procID];
563 if ((procID != myProcID) && (lengthsTo_[i] > maxSendLength_)) {
564 maxSendLength_ = lengthsTo_[i];
569 numSendsToOtherProcs_ -= sendMessageToSelf_;
570 std::vector<int> recv_list;
571 recv_list.reserve(numSendsToOtherProcs_);
574 for (
int i = 0; i < remoteProcIDs.size(); i++) {
575 if (remoteProcIDs[i] > last_pid) {
576 recv_list.push_back(remoteProcIDs[i]);
577 last_pid = remoteProcIDs[i];
578 }
else if (remoteProcIDs[i] < last_pid)
579 throw std::runtime_error(
"Tpetra::Distributor:::createFromSendsAndRecvs expected RemotePIDs to be in sorted order");
581 numReceives_ = recv_list.size();
583 procsFrom_.assign(numReceives_, 0);
584 lengthsFrom_.assign(numReceives_, 0);
585 indicesFrom_.assign(numReceives_, 0);
586 startsFrom_.assign(numReceives_, 0);
588 for (
size_t i = 0, j = 0; i < numReceives_; ++i) {
590 procsFrom_[i] = recv_list[i];
592 for (; j < (size_t)remoteProcIDs.size() &&
593 remoteProcIDs[jlast] == remoteProcIDs[j];
597 lengthsFrom_[i] = j - jlast;
599 totalReceiveLength_ = remoteProcIDs.size();
600 indicesFrom_.clear();
601 numReceives_ -= sendMessageToSelf_;
603#if defined(HAVE_TPETRA_MPI)
604 maybeInitializeRoots();
608Teuchos::RCP<DistributorPlan> DistributorPlan::getReversePlan()
const {
609 if (reversePlan_.is_null()) createReversePlan();
613void DistributorPlan::createReversePlan()
const {
614 reversePlan_ = Teuchos::rcp(
new DistributorPlan(comm_));
615 reversePlan_->howInitialized_ = Details::DISTRIBUTOR_INITIALIZED_BY_REVERSE;
616 reversePlan_->sendType_ = sendType_;
618#if defined(HAVE_TPETRACORE_MPI)
622 if (DISTRIBUTOR_IALLTOFEWV == sendType_) {
623 if (Behavior::verbose()) {
624 std::stringstream ss;
625 ss << __FILE__ <<
":" << __LINE__ <<
" WARNING (Ialltofewv send type): using default for reversed Ialltofewv\n";
626 std::cerr << ss.str();
636 size_t totalSendLength =
637 std::accumulate(lengthsTo_.begin(), lengthsTo_.end(), 0);
642 size_t maxReceiveLength = 0;
643 const int myProcID = comm_->getRank();
644 for (
size_t i = 0; i < numReceives_; ++i) {
645 if (procsFrom_[i] != myProcID) {
647 if (lengthsFrom_[i] > maxReceiveLength) {
648 maxReceiveLength = lengthsFrom_[i];
653 reversePlan_->sendMessageToSelf_ = sendMessageToSelf_;
654 reversePlan_->numSendsToOtherProcs_ = numReceives_;
655 reversePlan_->procIdsToSendTo_ = procsFrom_;
656 reversePlan_->startsTo_ = startsFrom_;
657 reversePlan_->lengthsTo_ = lengthsFrom_;
658 reversePlan_->maxSendLength_ = maxReceiveLength;
659 reversePlan_->indicesTo_ = indicesFrom_;
660 reversePlan_->numReceives_ = numSendsToOtherProcs_;
661 reversePlan_->totalReceiveLength_ = totalSendLength;
662 reversePlan_->lengthsFrom_ = lengthsTo_;
663 reversePlan_->procsFrom_ = procIdsToSendTo_;
664 reversePlan_->startsFrom_ = startsTo_;
665 reversePlan_->indicesFrom_ = indicesTo_;
667#if defined(HAVE_TPETRACORE_MPI_ADVANCE)
669 reversePlan_->initializeMpiAdvance();
672#if defined(HAVE_TPETRA_MPI)
673 reversePlan_->maybeInitializeRoots();
677void DistributorPlan::computeReceives() {
678 using Teuchos::Array;
679 using Teuchos::ArrayRCP;
681 using Teuchos::CommRequest;
682 using Teuchos::CommStatus;
683 using Teuchos::ireceive;
686 using Teuchos::receive;
687 using Teuchos::reduce;
688 using Teuchos::REDUCE_SUM;
689 using Teuchos::scatter;
691 using Teuchos::waitAll;
694 const int myRank = comm_->getRank();
695 const int numProcs = comm_->getSize();
697 const int mpiTag = DEFAULT_MPI_TAG;
705 Array<int> toProcsFromMe(numProcs, 0);
706#ifdef HAVE_TPETRA_DEBUG
707 bool counting_error =
false;
709 for (
size_t i = 0; i < (numSendsToOtherProcs_ + (sendMessageToSelf_ ? 1 : 0)); ++i) {
710#ifdef HAVE_TPETRA_DEBUG
711 if (toProcsFromMe[procIdsToSendTo_[i]] != 0) {
712 counting_error =
true;
715 toProcsFromMe[procIdsToSendTo_[i]] = 1;
717#ifdef HAVE_TPETRA_DEBUG
720 "Tpetra::Distributor::computeReceives: There was an error on at least "
721 "one process in counting the number of messages send by that process to "
722 "the other processs. Please report this bug to the Tpetra developers.",
779 Array<int> numRecvsOnEachProc;
780 if (myRank == root) {
781 numRecvsOnEachProc.resize(numProcs);
783 int numReceivesAsInt = 0;
784 reduce<int, int>(toProcsFromMe.getRawPtr(),
785 numRecvsOnEachProc.getRawPtr(),
786 numProcs, REDUCE_SUM, root, *comm_);
787 scatter<int, int>(numRecvsOnEachProc.getRawPtr(), 1,
788 &numReceivesAsInt, 1, root, *comm_);
789 numReceives_ =
static_cast<size_t>(numReceivesAsInt);
795 lengthsFrom_.assign(numReceives_, 0);
796 procsFrom_.assign(numReceives_, 0);
812 const size_t actualNumReceives = numReceives_ - (sendMessageToSelf_ ? 1 : 0);
818 Array<RCP<CommRequest<int>>> requests(actualNumReceives);
819 Array<ArrayRCP<size_t>> lengthsFromBuffers(actualNumReceives);
820 Array<RCP<CommStatus<int>>> statuses(actualNumReceives);
825 const int anySourceProc = MPI_ANY_SOURCE;
827 const int anySourceProc = -1;
831 for (
size_t i = 0; i < actualNumReceives; ++i) {
836 lengthsFromBuffers[i].resize(1);
837 lengthsFromBuffers[i][0] = as<size_t>(0);
838 requests[i] = ireceive<int, size_t>(lengthsFromBuffers[i], anySourceProc,
850 for (
size_t i = 0; i < numSendsToOtherProcs_ + (sendMessageToSelf_ ? 1 : 0); ++i) {
851 if (procIdsToSendTo_[i] != myRank) {
855 const size_t*
const lengthsTo_i = &lengthsTo_[i];
856 send<int, size_t>(lengthsTo_i, 1, as<int>(procIdsToSendTo_[i]), mpiTag, *comm_);
864 lengthsFrom_[numReceives_ - 1] = lengthsTo_[i];
865 procsFrom_[numReceives_ - 1] = myRank;
875 waitAll(*comm_, requests(), statuses());
876 for (
size_t i = 0; i < actualNumReceives; ++i) {
877 lengthsFrom_[i] = *lengthsFromBuffers[i];
878 procsFrom_[i] = statuses[i]->getSourceRank();
884 sort2(procsFrom_.begin(), procsFrom_.end(), lengthsFrom_.begin());
887 totalReceiveLength_ =
888 std::accumulate(lengthsFrom_.begin(), lengthsFrom_.end(), 0);
889 indicesFrom_.clear();
892 startsFrom_.reserve(numReceives_);
893 for (
size_t i = 0, j = 0; i < numReceives_; ++i) {
894 startsFrom_.push_back(j);
895 j += lengthsFrom_[i];
898 if (sendMessageToSelf_) {
903void DistributorPlan::setParameterList(
const Teuchos::RCP<Teuchos::ParameterList>& plist) {
905 using Teuchos::FancyOStream;
906 using Teuchos::getIntegralValue;
907 using Teuchos::ParameterList;
908 using Teuchos::parameterList;
911 if (!plist.is_null()) {
912 RCP<const ParameterList> validParams = getValidParameters();
913 plist->validateParametersAndSetDefaults(*validParams);
916 getIntegralValue<Details::EDistributorSendType>(*plist,
"Send type");
919 sendType_ = sendType;
921#if defined(HAVE_TPETRACORE_MPI_ADVANCE)
922 initializeMpiAdvance();
927 this->setMyParamList(plist);
929#if defined(HAVE_TPETRA_MPI)
930 maybeInitializeRoots();
940#if defined(HAVE_TPETRA_MPI)
943#if defined(HAVE_TPETRACORE_MPI_ADVANCE)
944 sendTypes.push_back(
"MpiAdvanceAlltoall");
945 sendTypes.push_back(
"MpiAdvanceNbralltoallv");
951 Teuchos::Array<EDistributorSendType>
res;
952 res.push_back(DISTRIBUTOR_ISEND);
953 res.push_back(DISTRIBUTOR_SEND);
954 res.push_back(DISTRIBUTOR_ALLTOALL);
955#if defined(HAVE_TPETRA_MPI)
958#if defined(HAVE_TPETRACORE_MPI_ADVANCE)
965Teuchos::RCP<const Teuchos::ParameterList>
966DistributorPlan::getValidParameters()
const {
967 using Teuchos::Array;
968 using Teuchos::ParameterList;
969 using Teuchos::parameterList;
971 using Teuchos::setStringToIntegralParameter;
976 const std::string
validatedSendType = validSendTypeOrThrow(Behavior::defaultSendType());
982 "When using MPI, the variant of send to use in "
983 "do[Reverse]Posts()",
985 plist->set(
"Timer Label",
"",
"Label for Time Monitor output");
987 return Teuchos::rcp_const_cast<const ParameterList>(
plist);
990#if defined(HAVE_TPETRACORE_MPI_ADVANCE)
993struct MpixCommDeallocator {
994 void free(MPIX_Comm** comm)
const {
995 MPIX_Comm_free(comm);
999void DistributorPlan::initializeMpiAdvance() {
1001 TEUCHOS_ASSERT(mpixComm_.is_null());
1004 Teuchos::RCP<const Teuchos::MpiComm<int>> mpiComm = Teuchos::rcp_dynamic_cast<const Teuchos::MpiComm<int>>(comm_);
1005 Teuchos::RCP<const Teuchos::OpaqueWrapper<MPI_Comm>> rawComm = mpiComm->getRawMpiComm();
1007 if (sendType_ == DISTRIBUTOR_MPIADVANCE_ALLTOALL ||
1008 sendType_ == DISTRIBUTOR_MPIADVANCE_NBRALLTOALLV) {
1009 MPIX_Comm** mpixComm =
new (MPIX_Comm*);
1010 err = MPIX_Comm_init(mpixComm, (*rawComm)());
1011 mpixComm_ = Teuchos::RCP(mpixComm,
1012 MpixCommDeallocator(),
1017 TEUCHOS_ASSERT(err == 0);
1021#if defined(HAVE_TPETRA_MPI)
1023void DistributorPlan::maybeInitializeRoots() {
1025 if (DISTRIBUTOR_IALLTOFEWV != sendType_) {
1030 ProfilingRegion region_maybeInitializeRoots(
"Tpetra::DistributorPlan::maybeInitializeRoots");
1033 const int numRecvs = (int)(getNumReceives() + (hasSelfMessage() ? 1 : 0));
1034 std::vector<int> sendbuf(comm_->getSize(), numRecvs);
1035 std::vector<int> recvbuf(comm_->getSize());
1040 Teuchos::RCP<const Teuchos::MpiComm<int>> mpiComm = Teuchos::rcp_dynamic_cast<const Teuchos::MpiComm<int>>(comm_);
1041 Teuchos::RCP<const Teuchos::OpaqueWrapper<MPI_Comm>> rawComm = mpiComm->getRawMpiComm();
1042 MPI_Comm comm = (*rawComm)();
1043 MPI_Alltoall(sendbuf.data(), 1, MPI_INT, recvbuf.data(), 1, MPI_INT, comm);
1046 for (
size_t root = 0; root < recvbuf.size(); ++root) {
1047 if (recvbuf[root] > 0) {
1048 roots_.push_back(root);
1054 int slow = !getIndicesTo().is_null() ? 1 : 0;
1055 MPI_Allreduce(MPI_IN_PLACE, &slow, 1, MPI_INT, MPI_LOR, comm);
1059 std::stringstream ss;
1060 ss << __FILE__ <<
":" << __LINE__ <<
" " << comm_->getRank() <<
": WARNING: Ialltoallv send mode set, at least one rank's data is not grouped by rank. Setting to \"Send\"" << std::endl;
1061 std::cerr << ss.str();
1066 sendType_ = DISTRIBUTOR_SEND;
1072 if (roots_.size() * roots_.size() >=
size_t(comm_->getSize())) {
1074 std::stringstream ss;
1075 ss << __FILE__ <<
":" << __LINE__ <<
" " << comm_->getRank() <<
": WARNING (Ialltoallv send type): too many roots (" << roots_.size() <<
") for " << comm_->getSize() <<
" ranks. Setting send-type to \"Send\"" << std::endl;
1076 std::cerr << ss.str();
1079 sendType_ = DISTRIBUTOR_SEND;
1084DistributorPlan::SubViewLimits DistributorPlan::getImportViewLimits(
size_t numPackets)
const {
1085 const size_t actualNumReceives = getNumReceives() + (hasSelfMessage() ? 1 : 0);
1087 IndexView importStarts(actualNumReceives);
1088 IndexView importLengths(actualNumReceives);
1091 for (
size_t i = 0; i < actualNumReceives; ++i) {
1092 importStarts[i] = offset;
1093 offset += getLengthsFrom()[i] * numPackets;
1094 importLengths[i] = getLengthsFrom()[i] * numPackets;
1096 return std::make_pair(importStarts, importLengths);
1099DistributorPlan::SubViewLimits DistributorPlan::getImportViewLimits(
const Teuchos::ArrayView<const size_t>& numImportPacketsPerLID)
const {
1100 const size_t actualNumReceives = getNumReceives() + (hasSelfMessage() ? 1 : 0);
1102 IndexView importStarts(actualNumReceives);
1103 IndexView importLengths(actualNumReceives);
1106 size_t curLIDoffset = 0;
1107 for (
size_t i = 0; i < actualNumReceives; ++i) {
1108 size_t totalPacketsFrom_i = 0;
1109 for (
size_t j = 0; j < getLengthsFrom()[i]; ++j) {
1110 totalPacketsFrom_i += numImportPacketsPerLID[curLIDoffset + j];
1112 curLIDoffset += getLengthsFrom()[i];
1113 importStarts[i] = offset;
1114 offset += totalPacketsFrom_i;
1115 importLengths[i] = totalPacketsFrom_i;
1117 return std::make_pair(importStarts, importLengths);
1120DistributorPlan::SubViewLimits DistributorPlan::getExportViewLimits(
size_t numPackets)
const {
1121 if (getIndicesTo().is_null()) {
1122 const size_t actualNumSends = getNumSends() + (hasSelfMessage() ? 1 : 0);
1123 IndexView exportStarts(actualNumSends);
1124 IndexView exportLengths(actualNumSends);
1125 for (
size_t pp = 0; pp < actualNumSends; ++pp) {
1126 exportStarts[pp] = getStartsTo()[pp] * numPackets;
1127 exportLengths[pp] = getLengthsTo()[pp] * numPackets;
1129 return std::make_pair(exportStarts, exportLengths);
1131 const size_t numIndices = getIndicesTo().size();
1132 IndexView exportStarts(numIndices);
1133 IndexView exportLengths(numIndices);
1134 for (
size_t j = 0; j < numIndices; ++j) {
1135 exportStarts[j] = getIndicesTo()[j] * numPackets;
1136 exportLengths[j] = numPackets;
1138 return std::make_pair(exportStarts, exportLengths);
1142DistributorPlan::SubViewLimits DistributorPlan::getExportViewLimits(
const Teuchos::ArrayView<const size_t>& numExportPacketsPerLID)
const {
1143 if (getIndicesTo().is_null()) {
1144 const size_t actualNumSends = getNumSends() + (hasSelfMessage() ? 1 : 0);
1145 IndexView exportStarts(actualNumSends);
1146 IndexView exportLengths(actualNumSends);
1148 for (
size_t pp = 0; pp < actualNumSends; ++pp) {
1149 size_t numPackets = 0;
1150 for (
size_t j = getStartsTo()[pp];
1151 j < getStartsTo()[pp] + getLengthsTo()[pp]; ++j) {
1152 numPackets += numExportPacketsPerLID[j];
1154 exportStarts[pp] = offset;
1155 offset += numPackets;
1156 exportLengths[pp] = numPackets;
1158 return std::make_pair(exportStarts, exportLengths);
1160 const size_t numIndices = getIndicesTo().size();
1161 IndexView exportStarts(numIndices);
1162 IndexView exportLengths(numIndices);
1164 for (
size_t j = 0; j < numIndices; ++j) {
1165 exportStarts[j] = offset;
1166 offset += numExportPacketsPerLID[j];
1167 exportLengths[j] = numExportPacketsPerLID[j];
1169 return std::make_pair(exportStarts, exportLengths);
Declaration of Tpetra::Details::Behavior, a class that describes Tpetra's behavior.
Declaration of Tpetra::Details::Profiling, a scope guard for Kokkos Profiling.
Stand-alone utility functions and macros.
#define TPETRA_EFFICIENCY_WARNING(throw_exception_test, msg)
Print or throw an efficency warning.
#define SHARED_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg, comm)
Test for exception, with reduction over the given communicator.
Struct that holds views of the contents of a CrsMatrix.
static bool debug()
Whether Tpetra is in debug mode.
static bool verbose()
Whether Tpetra is in verbose mode.
Implementation details of Tpetra.
std::string DistributorSendTypeEnumToString(EDistributorSendType sendType)
Convert an EDistributorSendType enum value to a string.
EDistributorSendType
The type of MPI send that Distributor should use.
Teuchos::Array< EDistributorSendType > distributorSendTypeEnums()
Valid enum values of distributor send types.
Teuchos::Array< std::string > distributorSendTypes()
Valid string values for Distributor's "Send type" parameter.
EDistributorSendType DistributorSendTypeStringToEnum(const std::string_view s)
Convert a string to an EDistributorSendType. Throw on error.
const std::string & validSendTypeOrThrow(const std::string &s)
Valid enum values of distributor send types.
EDistributorHowInitialized
Enum indicating how and whether a Distributor was initialized.
std::string DistributorHowInitializedEnumToString(EDistributorHowInitialized how)
Convert an EDistributorHowInitialized enum value to a string.
Namespace Tpetra contains the class and methods constituting the Tpetra library.
void sort2(const IT1 &first1, const IT1 &last1, const IT2 &first2, const bool stableSort=false)
Sort the first array, and apply the resulting permutation to the second array.