12 #include "Teuchos_StandardParameterEntryValidators.hpp"
23 if (sendType == DISTRIBUTOR_ISEND) {
26 else if (sendType == DISTRIBUTOR_SEND) {
29 else if (sendType == DISTRIBUTOR_ALLTOALL) {
32 #if defined(HAVE_TPETRACORE_MPI_ADVANCE)
33 else if (sendType == DISTRIBUTOR_MPIADVANCE_ALLTOALL) {
34 return "MpiAdvanceAlltoall";
36 else if (sendType == DISTRIBUTOR_MPIADVANCE_NBRALLTOALLV) {
37 return "MpiAdvanceNbralltoallv";
41 TEUCHOS_TEST_FOR_EXCEPTION(
true, std::invalid_argument,
"Invalid "
42 "EDistributorSendType enum value " << sendType <<
".");
50 case Details::DISTRIBUTOR_NOT_INITIALIZED:
51 return "Not initialized yet";
52 case Details::DISTRIBUTOR_INITIALIZED_BY_CREATE_FROM_SENDS:
53 return "By createFromSends";
54 case Details::DISTRIBUTOR_INITIALIZED_BY_CREATE_FROM_RECVS:
55 return "By createFromRecvs";
56 case Details::DISTRIBUTOR_INITIALIZED_BY_CREATE_FROM_SENDS_N_RECVS:
57 return "By createFromSendsAndRecvs";
58 case Details::DISTRIBUTOR_INITIALIZED_BY_REVERSE:
59 return "By createReverseDistributor";
60 case Details::DISTRIBUTOR_INITIALIZED_BY_COPY:
61 return "By copy constructor";
67 DistributorPlan::DistributorPlan(Teuchos::RCP<
const Teuchos::Comm<int>> comm)
69 #if defined(HAVE_TPETRACORE_MPI_ADVANCE)
70 mpixComm_(Teuchos::null),
72 howInitialized_(DISTRIBUTOR_NOT_INITIALIZED),
73 reversePlan_(Teuchos::null),
74 sendType_(DISTRIBUTOR_SEND),
75 sendMessageToSelf_(false),
76 numSendsToOtherProcs_(0),
79 totalReceiveLength_(0)
82 DistributorPlan::DistributorPlan(
const DistributorPlan& otherPlan)
83 : comm_(otherPlan.comm_),
84 #if defined(HAVE_TPETRACORE_MPI_ADVANCE)
85 mpixComm_(otherPlan.mpixComm_),
87 howInitialized_(DISTRIBUTOR_INITIALIZED_BY_COPY),
88 reversePlan_(otherPlan.reversePlan_),
89 sendType_(otherPlan.sendType_),
90 sendMessageToSelf_(otherPlan.sendMessageToSelf_),
91 numSendsToOtherProcs_(otherPlan.numSendsToOtherProcs_),
92 procIdsToSendTo_(otherPlan.procIdsToSendTo_),
93 startsTo_(otherPlan.startsTo_),
94 lengthsTo_(otherPlan.lengthsTo_),
95 maxSendLength_(otherPlan.maxSendLength_),
96 indicesTo_(otherPlan.indicesTo_),
97 numReceives_(otherPlan.numReceives_),
98 totalReceiveLength_(otherPlan.totalReceiveLength_),
99 lengthsFrom_(otherPlan.lengthsFrom_),
100 procsFrom_(otherPlan.procsFrom_),
101 startsFrom_(otherPlan.startsFrom_),
102 indicesFrom_(otherPlan.indicesFrom_)
105 size_t DistributorPlan::createFromSends(
const Teuchos::ArrayView<const int>& exportProcIDs) {
106 using Teuchos::outArg;
107 using Teuchos::REDUCE_MAX;
108 using Teuchos::reduceAll;
110 const char rawPrefix[] =
"Tpetra::DistributorPlan::createFromSends";
112 const size_t numExports = exportProcIDs.size();
113 const int myProcID = comm_->getRank();
114 const int numProcs = comm_->getSize();
158 for (
size_t i = 0; i < numExports; ++i) {
159 const int exportID = exportProcIDs[i];
160 if (exportID >= numProcs || exportID < 0) {
166 reduceAll<int, int> (*comm_, REDUCE_MAX, badID, outArg (gbl_badID));
167 TEUCHOS_TEST_FOR_EXCEPTION
168 (gbl_badID >= 0, std::runtime_error, rawPrefix <<
"Proc "
169 << gbl_badID <<
", perhaps among other processes, got a bad "
185 Teuchos::Array<size_t> starts (numProcs + 1, 0);
188 size_t numActive = 0;
189 int needSendBuff = 0;
191 for (
size_t i = 0; i < numExports; ++i) {
192 const int exportID = exportProcIDs[i];
207 if (needSendBuff == 0 && starts[exportID] > 1 &&
208 exportID != exportProcIDs[i-1]) {
215 #if defined(HAVE_TPETRA_PRINT_EFFICIENCY_WARNINGS)
217 int global_needSendBuff;
218 reduceAll<int, int> (*comm_, REDUCE_MAX, needSendBuff,
219 outArg (global_needSendBuff));
221 global_needSendBuff != 0,
222 "::createFromSends: Grouping export IDs together by process rank often "
223 "improves performance.");
229 if (starts[myProcID] != 0) {
230 sendMessageToSelf_ =
true;
233 sendMessageToSelf_ =
false;
236 if (! needSendBuff) {
238 numSendsToOtherProcs_ = 0;
241 for (
int i = 0; i < numProcs; ++i) {
243 ++numSendsToOtherProcs_;
249 indicesTo_.resize(0);
252 procIdsToSendTo_.assign(numSendsToOtherProcs_,0);
253 startsTo_.assign(numSendsToOtherProcs_,0);
254 lengthsTo_.assign(numSendsToOtherProcs_,0);
261 size_t procIndex = 0;
262 for (
size_t i = 0; i < numSendsToOtherProcs_; ++i) {
263 while (exportProcIDs[procIndex] < 0) {
266 startsTo_[i] = procIndex;
267 int procID = exportProcIDs[procIndex];
268 procIdsToSendTo_[i] = procID;
269 procIndex += starts[procID];
274 if (numSendsToOtherProcs_ > 0) {
275 sort2(procIdsToSendTo_.begin(), procIdsToSendTo_.end(), startsTo_.begin());
279 for (
size_t i = 0; i < numSendsToOtherProcs_; ++i) {
280 int procID = procIdsToSendTo_[i];
281 lengthsTo_[i] = starts[procID];
282 if ((procID != myProcID) && (lengthsTo_[i] > maxSendLength_)) {
283 maxSendLength_ = lengthsTo_[i];
294 if (starts[0] == 0 ) {
295 numSendsToOtherProcs_ = 0;
298 numSendsToOtherProcs_ = 1;
300 for (Teuchos::Array<size_t>::iterator i=starts.begin()+1,
302 i != starts.end(); ++i)
304 if (*i != 0) ++numSendsToOtherProcs_;
310 for (Teuchos::Array<size_t>::reverse_iterator ip1=starts.rbegin(),
312 i != starts.rend(); ++i)
321 indicesTo_.resize(numActive);
323 for (
size_t i = 0; i < numExports; ++i) {
324 if (exportProcIDs[i] >= 0) {
326 indicesTo_[starts[exportProcIDs[i]]] = i;
328 ++starts[exportProcIDs[i]];
340 for (
int proc = numProcs-1; proc != 0; --proc) {
341 starts[proc] = starts[proc-1];
344 starts[numProcs] = numActive;
351 procIdsToSendTo_.resize(numSendsToOtherProcs_);
352 startsTo_.resize(numSendsToOtherProcs_);
353 lengthsTo_.resize(numSendsToOtherProcs_);
360 for (
int proc = 0; proc < numProcs; ++proc ) {
361 if (starts[proc+1] != starts[proc]) {
362 lengthsTo_[snd] = starts[proc+1] - starts[proc];
363 startsTo_[snd] = starts[proc];
365 if ((proc != myProcID) && (lengthsTo_[snd] > maxSendLength_)) {
366 maxSendLength_ = lengthsTo_[snd];
368 procIdsToSendTo_[snd] = proc;
374 if (sendMessageToSelf_) {
375 --numSendsToOtherProcs_;
381 #if defined(HAVE_TPETRACORE_MPI_ADVANCE)
382 initializeMpiAdvance();
387 howInitialized_ = Details::DISTRIBUTOR_INITIALIZED_BY_CREATE_FROM_SENDS;
389 return totalReceiveLength_;
392 void DistributorPlan::createFromRecvs(
const Teuchos::ArrayView<const int>& remoteProcIDs)
394 *
this = *getReversePlan();
395 howInitialized_ = Details::DISTRIBUTOR_INITIALIZED_BY_CREATE_FROM_RECVS;
398 void DistributorPlan::createFromSendsAndRecvs(
const Teuchos::ArrayView<const int>& exportProcIDs,
399 const Teuchos::ArrayView<const int>& remoteProcIDs)
408 howInitialized_ = Tpetra::Details::DISTRIBUTOR_INITIALIZED_BY_CREATE_FROM_SENDS_N_RECVS;
410 int myProcID = comm_->getRank ();
411 int numProcs = comm_->getSize();
413 const size_t numExportIDs = exportProcIDs.size();
414 Teuchos::Array<size_t> starts (numProcs + 1, 0);
416 size_t numActive = 0;
417 int needSendBuff = 0;
419 for(
size_t i = 0; i < numExportIDs; i++ )
421 if( needSendBuff==0 && i && (exportProcIDs[i] < exportProcIDs[i-1]) )
423 if( exportProcIDs[i] >= 0 )
425 ++starts[ exportProcIDs[i] ];
430 sendMessageToSelf_ = ( starts[myProcID] != 0 ) ? 1 : 0;
432 numSendsToOtherProcs_ = 0;
436 if (starts[0] == 0 ) {
437 numSendsToOtherProcs_ = 0;
440 numSendsToOtherProcs_ = 1;
442 for (Teuchos::Array<size_t>::iterator i=starts.begin()+1,
444 i != starts.end(); ++i)
446 if (*i != 0) ++numSendsToOtherProcs_;
452 for (Teuchos::Array<size_t>::reverse_iterator ip1=starts.rbegin(),
454 i != starts.rend(); ++i)
463 indicesTo_.resize(numActive);
465 for (
size_t i = 0; i < numExportIDs; ++i) {
466 if (exportProcIDs[i] >= 0) {
468 indicesTo_[starts[exportProcIDs[i]]] = i;
470 ++starts[exportProcIDs[i]];
473 for (
int proc = numProcs-1; proc != 0; --proc) {
474 starts[proc] = starts[proc-1];
477 starts[numProcs] = numActive;
478 procIdsToSendTo_.resize(numSendsToOtherProcs_);
479 startsTo_.resize(numSendsToOtherProcs_);
480 lengthsTo_.resize(numSendsToOtherProcs_);
483 for (
int proc = 0; proc < numProcs; ++proc ) {
484 if (starts[proc+1] != starts[proc]) {
485 lengthsTo_[snd] = starts[proc+1] - starts[proc];
486 startsTo_[snd] = starts[proc];
488 if ((proc != myProcID) && (lengthsTo_[snd] > maxSendLength_)) {
489 maxSendLength_ = lengthsTo_[snd];
491 procIdsToSendTo_[snd] = proc;
498 numSendsToOtherProcs_ = 0;
501 for (
int i = 0; i < numProcs; ++i) {
503 ++numSendsToOtherProcs_;
509 indicesTo_.resize(0);
512 procIdsToSendTo_.assign(numSendsToOtherProcs_,0);
513 startsTo_.assign(numSendsToOtherProcs_,0);
514 lengthsTo_.assign(numSendsToOtherProcs_,0);
521 size_t procIndex = 0;
522 for (
size_t i = 0; i < numSendsToOtherProcs_; ++i) {
523 while (exportProcIDs[procIndex] < 0) {
526 startsTo_[i] = procIndex;
527 int procID = exportProcIDs[procIndex];
528 procIdsToSendTo_[i] = procID;
529 procIndex += starts[procID];
534 if (numSendsToOtherProcs_ > 0) {
535 sort2(procIdsToSendTo_.begin(), procIdsToSendTo_.end(), startsTo_.begin());
539 for (
size_t i = 0; i < numSendsToOtherProcs_; ++i) {
540 int procID = procIdsToSendTo_[i];
541 lengthsTo_[i] = starts[procID];
542 if ((procID != myProcID) && (lengthsTo_[i] > maxSendLength_)) {
543 maxSendLength_ = lengthsTo_[i];
549 numSendsToOtherProcs_ -= sendMessageToSelf_;
550 std::vector<int> recv_list;
551 recv_list.reserve(numSendsToOtherProcs_);
554 for(
int i=0; i<remoteProcIDs.size(); i++) {
555 if(remoteProcIDs[i]>last_pid) {
556 recv_list.push_back(remoteProcIDs[i]);
557 last_pid = remoteProcIDs[i];
559 else if (remoteProcIDs[i]<last_pid)
560 throw std::runtime_error(
"Tpetra::Distributor:::createFromSendsAndRecvs expected RemotePIDs to be in sorted order");
562 numReceives_ = recv_list.size();
564 procsFrom_.assign(numReceives_,0);
565 lengthsFrom_.assign(numReceives_,0);
566 indicesFrom_.assign(numReceives_,0);
567 startsFrom_.assign(numReceives_,0);
569 for(
size_t i=0,j=0; i<numReceives_; ++i) {
571 procsFrom_[i] = recv_list[i];
573 for( ; j<(size_t)remoteProcIDs.size() &&
574 remoteProcIDs[jlast]==remoteProcIDs[j] ; j++){;}
575 lengthsFrom_[i] = j-jlast;
577 totalReceiveLength_ = remoteProcIDs.size();
578 indicesFrom_.clear ();
579 numReceives_-=sendMessageToSelf_;
581 #if defined(HAVE_TPETRACORE_MPI_ADVANCE)
582 initializeMpiAdvance();
586 Teuchos::RCP<DistributorPlan> DistributorPlan::getReversePlan()
const {
587 if (reversePlan_.is_null()) createReversePlan();
591 void DistributorPlan::createReversePlan()
const
593 reversePlan_ = Teuchos::rcp(
new DistributorPlan(comm_));
594 reversePlan_->howInitialized_ = Details::DISTRIBUTOR_INITIALIZED_BY_REVERSE;
595 reversePlan_->sendType_ = sendType_;
600 size_t totalSendLength =
601 std::accumulate(lengthsTo_.begin(), lengthsTo_.end(), 0);
606 size_t maxReceiveLength = 0;
607 const int myProcID = comm_->getRank();
608 for (
size_t i=0; i < numReceives_; ++i) {
609 if (procsFrom_[i] != myProcID) {
611 if (lengthsFrom_[i] > maxReceiveLength) {
612 maxReceiveLength = lengthsFrom_[i];
617 reversePlan_->sendMessageToSelf_ = sendMessageToSelf_;
618 reversePlan_->numSendsToOtherProcs_ = numReceives_;
619 reversePlan_->procIdsToSendTo_ = procsFrom_;
620 reversePlan_->startsTo_ = startsFrom_;
621 reversePlan_->lengthsTo_ = lengthsFrom_;
622 reversePlan_->maxSendLength_ = maxReceiveLength;
623 reversePlan_->indicesTo_ = indicesFrom_;
624 reversePlan_->numReceives_ = numSendsToOtherProcs_;
625 reversePlan_->totalReceiveLength_ = totalSendLength;
626 reversePlan_->lengthsFrom_ = lengthsTo_;
627 reversePlan_->procsFrom_ = procIdsToSendTo_;
628 reversePlan_->startsFrom_ = startsTo_;
629 reversePlan_->indicesFrom_ = indicesTo_;
631 #if defined(HAVE_TPETRACORE_MPI_ADVANCE)
633 reversePlan_->initializeMpiAdvance();
637 void DistributorPlan::computeReceives()
639 using Teuchos::Array;
640 using Teuchos::ArrayRCP;
642 using Teuchos::CommStatus;
643 using Teuchos::CommRequest;
644 using Teuchos::ireceive;
647 using Teuchos::REDUCE_SUM;
648 using Teuchos::receive;
649 using Teuchos::reduce;
650 using Teuchos::scatter;
652 using Teuchos::waitAll;
654 const int myRank = comm_->getRank();
655 const int numProcs = comm_->getSize();
657 const int mpiTag = DEFAULT_MPI_TAG;
665 Array<int> toProcsFromMe (numProcs, 0);
666 #ifdef HAVE_TPETRA_DEBUG
667 bool counting_error =
false;
668 #endif // HAVE_TPETRA_DEBUG
669 for (
size_t i = 0; i < (numSendsToOtherProcs_ + (sendMessageToSelf_ ? 1 : 0)); ++i) {
670 #ifdef HAVE_TPETRA_DEBUG
671 if (toProcsFromMe[procIdsToSendTo_[i]] != 0) {
672 counting_error =
true;
674 #endif // HAVE_TPETRA_DEBUG
675 toProcsFromMe[procIdsToSendTo_[i]] = 1;
677 #ifdef HAVE_TPETRA_DEBUG
680 "Tpetra::Distributor::computeReceives: There was an error on at least "
681 "one process in counting the number of messages send by that process to "
682 "the other processs. Please report this bug to the Tpetra developers.",
684 #endif // HAVE_TPETRA_DEBUG
739 Array<int> numRecvsOnEachProc;
740 if (myRank == root) {
741 numRecvsOnEachProc.resize (numProcs);
743 int numReceivesAsInt = 0;
744 reduce<int, int> (toProcsFromMe.getRawPtr (),
745 numRecvsOnEachProc.getRawPtr (),
746 numProcs, REDUCE_SUM, root, *comm_);
747 scatter<int, int> (numRecvsOnEachProc.getRawPtr (), 1,
748 &numReceivesAsInt, 1, root, *comm_);
749 numReceives_ =
static_cast<size_t> (numReceivesAsInt);
755 lengthsFrom_.assign (numReceives_, 0);
756 procsFrom_.assign (numReceives_, 0);
772 const size_t actualNumReceives = numReceives_ - (sendMessageToSelf_ ? 1 : 0);
778 Array<RCP<CommRequest<int> > > requests (actualNumReceives);
779 Array<ArrayRCP<size_t> > lengthsFromBuffers (actualNumReceives);
780 Array<RCP<CommStatus<int> > > statuses (actualNumReceives);
785 const int anySourceProc = MPI_ANY_SOURCE;
787 const int anySourceProc = -1;
791 for (
size_t i = 0; i < actualNumReceives; ++i) {
796 lengthsFromBuffers[i].resize (1);
797 lengthsFromBuffers[i][0] = as<size_t> (0);
798 requests[i] = ireceive<int, size_t> (lengthsFromBuffers[i], anySourceProc,
810 for (
size_t i = 0; i < numSendsToOtherProcs_ + (sendMessageToSelf_ ? 1 : 0); ++i) {
811 if (procIdsToSendTo_[i] != myRank) {
815 const size_t*
const lengthsTo_i = &lengthsTo_[i];
816 send<int, size_t> (lengthsTo_i, 1, as<int> (procIdsToSendTo_[i]), mpiTag, *comm_);
825 lengthsFrom_[numReceives_-1] = lengthsTo_[i];
826 procsFrom_[numReceives_-1] = myRank;
836 waitAll (*comm_, requests (), statuses ());
837 for (
size_t i = 0; i < actualNumReceives; ++i) {
838 lengthsFrom_[i] = *lengthsFromBuffers[i];
839 procsFrom_[i] = statuses[i]->getSourceRank ();
845 sort2 (procsFrom_.begin(), procsFrom_.end(), lengthsFrom_.begin());
848 totalReceiveLength_ =
849 std::accumulate (lengthsFrom_.begin (), lengthsFrom_.end (), 0);
850 indicesFrom_.clear ();
852 startsFrom_.clear ();
853 startsFrom_.reserve (numReceives_);
854 for (
size_t i = 0, j = 0; i < numReceives_; ++i) {
855 startsFrom_.push_back(j);
856 j += lengthsFrom_[i];
859 if (sendMessageToSelf_) {
864 void DistributorPlan::setParameterList(
const Teuchos::RCP<Teuchos::ParameterList>& plist)
866 using Teuchos::FancyOStream;
867 using Teuchos::getIntegralValue;
868 using Teuchos::ParameterList;
869 using Teuchos::parameterList;
873 if (! plist.is_null()) {
874 RCP<const ParameterList> validParams = getValidParameters ();
875 plist->validateParametersAndSetDefaults (*validParams);
878 getIntegralValue<Details::EDistributorSendType> (*plist,
"Send type");
881 sendType_ = sendType;
885 this->setMyParamList (plist);
891 Teuchos::Array<std::string> sendTypes;
892 sendTypes.push_back (
"Isend");
893 sendTypes.push_back (
"Send");
894 sendTypes.push_back (
"Alltoall");
895 #if defined(HAVE_TPETRACORE_MPI_ADVANCE)
896 sendTypes.push_back (
"MpiAdvanceAlltoall");
897 sendTypes.push_back (
"MpiAdvanceNbralltoallv");
902 Teuchos::RCP<const Teuchos::ParameterList>
903 DistributorPlan::getValidParameters()
const
905 using Teuchos::Array;
906 using Teuchos::ParameterList;
907 using Teuchos::parameterList;
909 using Teuchos::setStringToIntegralParameter;
912 const std::string defaultSendType (
"Send");
913 Array<Details::EDistributorSendType> sendTypeEnums;
914 sendTypeEnums.push_back (Details::DISTRIBUTOR_ISEND);
915 sendTypeEnums.push_back (Details::DISTRIBUTOR_SEND);
916 sendTypeEnums.push_back (Details::DISTRIBUTOR_ALLTOALL);
917 #if defined(HAVE_TPETRACORE_MPI_ADVANCE)
918 sendTypeEnums.push_back (Details::DISTRIBUTOR_MPIADVANCE_ALLTOALL);
919 sendTypeEnums.push_back (Details::DISTRIBUTOR_MPIADVANCE_NBRALLTOALLV);
922 RCP<ParameterList> plist = parameterList (
"Tpetra::Distributor");
924 setStringToIntegralParameter<Details::EDistributorSendType> (
"Send type",
925 defaultSendType,
"When using MPI, the variant of send to use in "
926 "do[Reverse]Posts()", sendTypes(), sendTypeEnums(), plist.getRawPtr());
927 plist->set (
"Timer Label",
"",
"Label for Time Monitor output");
929 return Teuchos::rcp_const_cast<
const ParameterList> (plist);
932 #if defined(HAVE_TPETRACORE_MPI_ADVANCE)
935 struct MpixCommDeallocator {
936 void free(MPIX_Comm **comm)
const {
937 MPIX_Comm_free(*comm);
941 void DistributorPlan::initializeMpiAdvance() {
944 TEUCHOS_ASSERT(mpixComm_.is_null());
947 Teuchos::RCP<const Teuchos::MpiComm<int> > mpiComm = Teuchos::rcp_dynamic_cast<
const Teuchos::MpiComm<int> >(comm_);
948 Teuchos::RCP<const Teuchos::OpaqueWrapper<MPI_Comm> > rawComm = mpiComm->getRawMpiComm();
950 if (sendType_ == DISTRIBUTOR_MPIADVANCE_ALLTOALL) {
951 MPIX_Comm **mpixComm =
new(MPIX_Comm*);
952 err = MPIX_Comm_init(mpixComm, (*rawComm)());
953 mpixComm_ = Teuchos::RCP(mpixComm,
954 MpixCommDeallocator(),
958 else if (sendType_ == DISTRIBUTOR_MPIADVANCE_NBRALLTOALLV) {
959 int numRecvs = (int)(numReceives_ + (sendMessageToSelf_ ? 1 : 0));
960 int *sourceRanks = procsFrom_.data();
963 const int *sourceWeights = MPI_UNWEIGHTED;
964 int numSends = (int)(numSendsToOtherProcs_ + (sendMessageToSelf_ ? 1 : 0));
965 int *destRanks = procIdsToSendTo_.data();
968 const int *destWeights = MPI_UNWEIGHTED;
970 MPIX_Comm **mpixComm =
new(MPIX_Comm*);
971 err = MPIX_Dist_graph_create_adjacent((*rawComm)(), numRecvs, sourceRanks, sourceWeights, numSends, destRanks, destWeights, MPI_INFO_NULL,
false, mpixComm);
972 mpixComm_ = Teuchos::RCP(mpixComm,
973 MpixCommDeallocator(),
978 TEUCHOS_ASSERT(err == 0);
983 DistributorPlan::SubViewLimits DistributorPlan::getImportViewLimits(
size_t numPackets)
const {
984 const size_t actualNumReceives = getNumReceives() + (hasSelfMessage() ? 1 : 0);
986 IndexView importStarts(actualNumReceives);
987 IndexView importLengths(actualNumReceives);
990 for (
size_t i = 0; i < actualNumReceives; ++i) {
991 importStarts[i] = offset;
992 offset += getLengthsFrom()[i] * numPackets;
993 importLengths[i] = getLengthsFrom()[i] * numPackets;
995 return std::make_pair(importStarts, importLengths);
998 DistributorPlan::SubViewLimits DistributorPlan::getImportViewLimits(
const Teuchos::ArrayView<const size_t> &numImportPacketsPerLID)
const {
1000 const size_t actualNumReceives = getNumReceives() + (hasSelfMessage() ? 1 : 0);
1002 IndexView importStarts(actualNumReceives);
1003 IndexView importLengths(actualNumReceives);
1006 size_t curLIDoffset = 0;
1007 for (
size_t i = 0; i < actualNumReceives; ++i) {
1008 size_t totalPacketsFrom_i = 0;
1009 for (
size_t j = 0; j < getLengthsFrom()[i]; ++j) {
1010 totalPacketsFrom_i += numImportPacketsPerLID[curLIDoffset + j];
1012 curLIDoffset += getLengthsFrom()[i];
1013 importStarts[i] = offset;
1014 offset += totalPacketsFrom_i;
1015 importLengths[i] = totalPacketsFrom_i;
1017 return std::make_pair(importStarts, importLengths);
1021 DistributorPlan::SubViewLimits DistributorPlan::getExportViewLimits(
size_t numPackets)
const {
1022 if (getIndicesTo().is_null()) {
1024 const size_t actualNumSends = getNumSends() + (hasSelfMessage() ? 1 : 0);
1025 IndexView exportStarts(actualNumSends);
1026 IndexView exportLengths(actualNumSends);
1027 for (
size_t pp = 0; pp < actualNumSends; ++pp) {
1028 exportStarts[pp] = getStartsTo()[pp] * numPackets;
1029 exportLengths[pp] = getLengthsTo()[pp] * numPackets;
1031 return std::make_pair(exportStarts, exportLengths);
1033 const size_t numIndices = getIndicesTo().size();
1034 IndexView exportStarts(numIndices);
1035 IndexView exportLengths(numIndices);
1036 for (
size_t j = 0; j < numIndices; ++j) {
1037 exportStarts[j] = getIndicesTo()[j]*numPackets;
1038 exportLengths[j] = numPackets;
1040 return std::make_pair(exportStarts, exportLengths);
1044 DistributorPlan::SubViewLimits DistributorPlan::getExportViewLimits(
const Teuchos::ArrayView<const size_t> &numExportPacketsPerLID)
const {
1045 if (getIndicesTo().is_null()) {
1046 const size_t actualNumSends = getNumSends() + (hasSelfMessage() ? 1 : 0);
1047 IndexView exportStarts(actualNumSends);
1048 IndexView exportLengths(actualNumSends);
1050 for (
size_t pp = 0; pp < actualNumSends; ++pp) {
1051 size_t numPackets = 0;
1052 for (
size_t j = getStartsTo()[pp];
1053 j < getStartsTo()[pp] + getLengthsTo()[pp]; ++j) {
1054 numPackets += numExportPacketsPerLID[j];
1056 exportStarts[pp] = offset;
1057 offset += numPackets;
1058 exportLengths[pp] = numPackets;
1060 return std::make_pair(exportStarts, exportLengths);
1062 const size_t numIndices = getIndicesTo().size();
1063 IndexView exportStarts(numIndices);
1064 IndexView exportLengths(numIndices);
1066 for (
size_t j = 0; j < numIndices; ++j) {
1067 exportStarts[j] = offset;
1068 offset += numExportPacketsPerLID[j];
1069 exportLengths[j] = numExportPacketsPerLID[j];
1071 return std::make_pair(exportStarts, exportLengths);
EDistributorHowInitialized
Enum indicating how and whether a Distributor was initialized.
static bool debug()
Whether Tpetra is in debug mode.
std::string DistributorSendTypeEnumToString(EDistributorSendType sendType)
Convert an EDistributorSendType enum value to a string.
#define TPETRA_EFFICIENCY_WARNING(throw_exception_test, msg)
Print or throw an efficency warning.
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.
Teuchos::Array< std::string > distributorSendTypes()
Valid values for Distributor's "Send type" parameter.
std::string DistributorHowInitializedEnumToString(EDistributorHowInitialized how)
Convert an EDistributorHowInitialized enum value to a string.
Stand-alone utility functions and macros.
#define SHARED_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg, comm)
Test for exception, with reduction over the given communicator.
EDistributorSendType
The type of MPI send that Distributor should use.
Declaration of Tpetra::Details::Behavior, a class that describes Tpetra's behavior.