10#ifndef TEUCHOS_MPI_COMM_DEF_HPP
11#define TEUCHOS_MPI_COMM_DEF_HPP
17#ifdef HAVE_TEUCHOS_MPI
23template <
class OrdinalType>
24MpiCommStatus<OrdinalType>::MpiCommStatus(MPI_Status status)
27template <
class OrdinalType> MpiCommStatus<OrdinalType>::~MpiCommStatus() {}
29template <
class OrdinalType>
30OrdinalType MpiCommStatus<OrdinalType>::getSourceRank() {
31 return status_.MPI_SOURCE;
34template <
class OrdinalType> OrdinalType MpiCommStatus<OrdinalType>::getTag() {
35 return status_.MPI_TAG;
38template <
class OrdinalType>
39OrdinalType MpiCommStatus<OrdinalType>::getError() {
40 return status_.MPI_ERROR;
43template<
class OrdinalType>
44RCP<MpiCommStatus<OrdinalType> >
45mpiCommStatus (MPI_Status rawMpiStatus)
47 return rcp (
new MpiCommStatus<OrdinalType> (rawMpiStatus));
51template<
class OrdinalType>
52MpiCommRequestBase<OrdinalType>::MpiCommRequestBase () :
53 rawMpiRequest_ (MPI_REQUEST_NULL)
57template<
class OrdinalType>
58MpiCommRequestBase<OrdinalType>::MpiCommRequestBase (MPI_Request rawMpiRequest) :
59 rawMpiRequest_ (rawMpiRequest)
62template<
class OrdinalType>
63MPI_Request MpiCommRequestBase<OrdinalType>::releaseRawMpiRequest()
65 MPI_Request tmp_rawMpiRequest = rawMpiRequest_;
66 rawMpiRequest_ = MPI_REQUEST_NULL;
67 return tmp_rawMpiRequest;
70template<
class OrdinalType>
71bool MpiCommRequestBase<OrdinalType>::isNull()
const {
72 return rawMpiRequest_ == MPI_REQUEST_NULL;
75template<
class OrdinalType>
76bool MpiCommRequestBase<OrdinalType>::isReady() {
77 MPI_Status rawMpiStatus;
80 MPI_Test(&rawMpiRequest_, &flag, &rawMpiStatus);
86template<
class OrdinalType>
87RCP<CommStatus<OrdinalType> >
88MpiCommRequestBase<OrdinalType>::wait () {
89 MPI_Status rawMpiStatus;
92 const int err = MPI_Wait (&rawMpiRequest_, &rawMpiStatus);
94 err != MPI_SUCCESS, std::runtime_error,
95 "Teuchos: MPI_Wait() failed with error \""
96 << mpiErrorCodeToString (err));
98 return mpiCommStatus<OrdinalType> (rawMpiStatus);
102template<
class OrdinalType>
103RCP<CommStatus<OrdinalType> > MpiCommRequestBase<OrdinalType>::cancel () {
104 if (rawMpiRequest_ == MPI_REQUEST_NULL) {
108 int err = MPI_Cancel (&rawMpiRequest_);
110 err != MPI_SUCCESS, std::runtime_error,
111 "Teuchos: MPI_Cancel failed with the following error: "
112 << mpiErrorCodeToString (err));
119 err = MPI_Wait (&rawMpiRequest_, &status);
121 "Teuchos::MpiCommStatus::cancel: MPI_Wait failed with the following "
122 "error: " << mpiErrorCodeToString (err));
123 return mpiCommStatus<OrdinalType> (status);
127template<
class OrdinalType>
128MpiCommRequestBase<OrdinalType>::~MpiCommRequestBase () {
129 if (rawMpiRequest_ != MPI_REQUEST_NULL) {
132 const int err = MPI_Cancel (&rawMpiRequest_);
133 if (err == MPI_SUCCESS) {
150 (void) MPI_Wait (&rawMpiRequest_, MPI_STATUS_IGNORE);
156template<
class OrdinalType>
157MpiCommRequest<OrdinalType>::MpiCommRequest () :
158 MpiCommRequestBase<OrdinalType> (MPI_REQUEST_NULL),
162template<
class OrdinalType>
163MpiCommRequest<OrdinalType>::MpiCommRequest (MPI_Request rawMpiRequest,
164 const ArrayView<char>::size_type numBytesInMessage) :
165 MpiCommRequestBase<OrdinalType> (rawMpiRequest),
166 numBytes_ (numBytesInMessage)
169template<
class OrdinalType>
170ArrayView<char>::size_type MpiCommRequest<OrdinalType>::numBytes ()
const {
174template<
class OrdinalType>
175MpiCommRequest<OrdinalType>::~MpiCommRequest () =
default;
178template<
class OrdinalType>
179RCP<MpiCommRequest<OrdinalType> >
180mpiCommRequest (MPI_Request rawMpiRequest,
181 const ArrayView<char>::size_type numBytes)
183 return rcp (
new MpiCommRequest<OrdinalType> (rawMpiRequest, numBytes));
193template<
typename Ordinal>
194int MpiComm<Ordinal>::tagCounter_ = MpiComm<Ordinal>::minTag_;
200template<
typename Ordinal>
202MpiComm (
const RCP<
const OpaqueWrapper<MPI_Comm> >& rawMpiComm)
205 rawMpiComm.get () == NULL, std::invalid_argument,
206 "Teuchos::MpiComm constructor: The input RCP is null.");
208 *rawMpiComm == MPI_COMM_NULL, std::invalid_argument,
209 "Teuchos::MpiComm constructor: The given MPI_Comm is MPI_COMM_NULL.");
211 rawMpiComm_ = rawMpiComm;
225 setupMembersFromComm ();
229template<
typename Ordinal>
231MpiComm (
const RCP<
const OpaqueWrapper<MPI_Comm> >& rawMpiComm,
232 const int defaultTag)
235 rawMpiComm.get () == NULL, std::invalid_argument,
236 "Teuchos::MpiComm constructor: The input RCP is null.");
238 *rawMpiComm == MPI_COMM_NULL, std::invalid_argument,
239 "Teuchos::MpiComm constructor: The given MPI_Comm is MPI_COMM_NULL.");
241 rawMpiComm_ = rawMpiComm;
243 int err = MPI_Comm_size (*rawMpiComm_, &size_);
245 "Teuchos::MpiComm constructor: MPI_Comm_size failed with "
246 "error \"" << mpiErrorCodeToString (err) <<
"\".");
248 err = MPI_Comm_rank (*rawMpiComm_, &rank_);
250 "Teuchos::MpiComm constructor: MPI_Comm_rank failed with "
251 "error \"" << mpiErrorCodeToString (err) <<
"\".");
256 int* tag_ub_val =
nullptr;
258 int const aerr = MPI_Comm_get_attr (*rawMpiComm_, MPI_TAG_UB, &tag_ub_val, &found);
259 tagUb_ = (aerr == MPI_SUCCESS && found && tag_ub_val !=
nullptr && *tag_ub_val > minTag_) ? *tag_ub_val : 32767;
264template<
typename Ordinal>
265MpiComm<Ordinal>::MpiComm (MPI_Comm rawMpiComm)
268 std::invalid_argument,
"Teuchos::MpiComm constructor: The given MPI_Comm "
269 "is MPI_COMM_NULL.");
273 rawMpiComm_ = opaqueWrapper<MPI_Comm> (rawMpiComm);
287 setupMembersFromComm ();
291template<
typename Ordinal>
292MpiComm<Ordinal>::MpiComm (
const MpiComm<Ordinal>& other) :
293 rawMpiComm_ (opaqueWrapper<MPI_Comm> (MPI_COMM_NULL))
296 RCP<const OpaqueWrapper<MPI_Comm> > origCommPtr = other.getRawMpiComm ();
298 "Teuchos::MpiComm copy constructor: "
299 "The input's getRawMpiComm() method returns null.");
300 MPI_Comm origComm = *origCommPtr;
302 "Teuchos::MpiComm copy constructor: "
303 "The input's raw MPI_Comm is MPI_COMM_NULL.");
311 rawMpiComm_ = origCommPtr;
315 const int err = MPI_Comm_dup (origComm, &newComm);
317 "Teuchos::MpiComm copy constructor: MPI_Comm_dup failed with "
318 "the following error: " << mpiErrorCodeToString (err));
320 rawMpiComm_ = opaqueWrapper (newComm, details::safeCommFree);
323 setupMembersFromComm ();
327template<
typename Ordinal>
328void MpiComm<Ordinal>::setupMembersFromComm ()
330 int err = MPI_Comm_size (*rawMpiComm_, &size_);
332 "Teuchos::MpiComm constructor: MPI_Comm_size failed with "
333 "error \"" << mpiErrorCodeToString (err) <<
"\".");
334 err = MPI_Comm_rank (*rawMpiComm_, &rank_);
336 "Teuchos::MpiComm constructor: MPI_Comm_rank failed with "
337 "error \"" << mpiErrorCodeToString (err) <<
"\".");
346 int* tag_ub_val =
nullptr;
348 int const aerr = MPI_Comm_get_attr (*rawMpiComm_, MPI_TAG_UB, &tag_ub_val, &found);
349 tagUb_ = (aerr == MPI_SUCCESS && found && tag_ub_val !=
nullptr && *tag_ub_val > minTag_) ? *tag_ub_val : 32767;
353 if (tagCounter_ > maxTag_) {
354 tagCounter_ = minTag_;
356 tag_ = tagCounter_++;
366 MPI_Bcast (&tag_, 1, MPI_INT, 0, *rawMpiComm_);
370template<
typename Ordinal>
373setErrorHandler (
const RCP<
const OpaqueWrapper<MPI_Errhandler> >& errHandler)
375 if (! is_null (errHandler)) {
376 const int err = details::setCommErrhandler (*getRawMpiComm (), *errHandler);
378 "Teuchos::MpiComm: Setting the MPI_Comm's error handler failed with "
379 "error \"" << mpiErrorCodeToString (err) <<
"\".");
383 customErrorHandler_ = errHandler;
390template<
typename Ordinal>
391int MpiComm<Ordinal>::getRank()
const
397template<
typename Ordinal>
398int MpiComm<Ordinal>::getSize()
const
404template<
typename Ordinal>
405void MpiComm<Ordinal>::alltoAll(
406 const Ordinal sendBytes,
const char sendBuffer[],
407 const Ordinal recvBytes,
char recvBuffer[])
const
409 TEUCHOS_COMM_TIME_MONITOR(
410 "Teuchos::MpiComm<"<<OrdinalTraits<Ordinal>::name()<<
">::alltoAll(...)"
412 const int err = MPI_Alltoall (sendBuffer, sendBytes, MPI_CHAR, recvBuffer, recvBytes, MPI_CHAR, *rawMpiComm_);
414 "Teuchos::MpiComm::alltoAll: MPI_Alltoall failed with error \""
415 << mpiErrorCodeToString (err) <<
"\".");
419template<
typename Ordinal>
420void MpiComm<Ordinal>::barrier()
const
422 TEUCHOS_COMM_TIME_MONITOR(
423 "Teuchos::MpiComm<"<<OrdinalTraits<Ordinal>::name()<<
">::barrier()"
425 const int err = MPI_Barrier (*rawMpiComm_);
427 "Teuchos::MpiComm::barrier: MPI_Barrier failed with error \""
428 << mpiErrorCodeToString (err) <<
"\".");
432template<
typename Ordinal>
433void MpiComm<Ordinal>::broadcast(
434 const int rootRank,
const Ordinal bytes,
char buffer[]
437 TEUCHOS_COMM_TIME_MONITOR(
438 "Teuchos::MpiComm<"<<OrdinalTraits<Ordinal>::name()<<
">::broadcast(...)"
440 const int err = MPI_Bcast (buffer, bytes, MPI_CHAR, rootRank, *rawMpiComm_);
442 "Teuchos::MpiComm::broadcast: MPI_Bcast failed with error \""
443 << mpiErrorCodeToString (err) <<
"\".");
447template<
typename Ordinal>
448void MpiComm<Ordinal>::gatherAll(
449 const Ordinal sendBytes,
const char sendBuffer[],
450 const Ordinal recvBytes,
char recvBuffer[]
453 TEUCHOS_COMM_TIME_MONITOR(
454 "Teuchos::MpiComm<"<<OrdinalTraits<Ordinal>::name()<<
">::gatherAll(...)"
458 MPI_Allgather (
const_cast<char *
>(sendBuffer), sendBytes, MPI_CHAR,
459 recvBuffer, sendBytes, MPI_CHAR, *rawMpiComm_);
464 "Teuchos::MpiComm::gatherAll: MPI_Allgather failed with error \""
465 << mpiErrorCodeToString (err) <<
"\".");
469template<
typename Ordinal>
471MpiComm<Ordinal>::gather (
const Ordinal sendBytes,
472 const char sendBuffer[],
473 const Ordinal recvBytes,
475 const int root)
const
479 TEUCHOS_COMM_TIME_MONITOR(
480 "Teuchos::MpiComm<"<<OrdinalTraits<Ordinal>::name()<<
">::gather(...)"
483 MPI_Gather (
const_cast<char *
> (sendBuffer), sendBytes, MPI_CHAR,
484 recvBuffer, sendBytes, MPI_CHAR, root, *rawMpiComm_);
486 "Teuchos::MpiComm::gather: MPI_Gather failed with error \""
487 << mpiErrorCodeToString (err) <<
"\".");
491template<
typename Ordinal>
494reduceAll (
const ValueTypeReductionOp<Ordinal,char> &reductOp,
496 const char sendBuffer[],
497 char globalReducts[])
const
499 TEUCHOS_COMM_TIME_MONITOR(
"Teuchos::MpiComm::reduceAll(...)" );
500 int err = MPI_SUCCESS;
502 if (bytes == 0)
return;
504 Details::MpiReductionOp<Ordinal> opWrap (reductOp);
505 MPI_Op op = Details::setMpiReductionOp (opWrap);
514 MPI_Datatype char_block;
515 err = MPI_Type_contiguous (bytes, MPI_CHAR, &char_block);
517 err != MPI_SUCCESS, std::runtime_error,
"Teuchos::reduceAll: "
518 "MPI_Type_contiguous failed with error \"" << mpiErrorCodeToString (err)
520 err = MPI_Type_commit (&char_block);
522 err != MPI_SUCCESS, std::runtime_error,
"Teuchos::reduceAll: "
523 "MPI_Type_commit failed with error \"" << mpiErrorCodeToString (err)
526 if (sendBuffer == globalReducts) {
530 err = MPI_Allreduce (MPI_IN_PLACE, globalReducts, 1,
531 char_block, op, *rawMpiComm_);
534 err = MPI_Allreduce (
const_cast<char*
> (sendBuffer), globalReducts, 1,
535 char_block, op, *rawMpiComm_);
537 if (err != MPI_SUCCESS) {
542 (void) MPI_Type_free (&char_block);
544 true, std::runtime_error,
"Teuchos::reduceAll (MPI, custom op): "
545 "MPI_Allreduce failed with error \"" << mpiErrorCodeToString (err)
548 err = MPI_Type_free (&char_block);
550 err != MPI_SUCCESS, std::runtime_error,
"Teuchos::reduceAll: "
551 "MPI_Type_free failed with error \"" << mpiErrorCodeToString (err)
556template<
typename Ordinal>
557void MpiComm<Ordinal>::scan(
558 const ValueTypeReductionOp<Ordinal,char> &reductOp
559 ,
const Ordinal bytes,
const char sendBuffer[],
char scanReducts[]
562 TEUCHOS_COMM_TIME_MONITOR(
"Teuchos::MpiComm::scan(...)" );
564 Details::MpiReductionOp<Ordinal> opWrap (reductOp);
565 MPI_Op op = Details::setMpiReductionOp (opWrap);
567 MPI_Scan (
const_cast<char*
> (sendBuffer), scanReducts, bytes, MPI_CHAR,
570 "Teuchos::MpiComm::scan: MPI_Scan() failed with error \""
571 << mpiErrorCodeToString (err) <<
"\".");
575template<
typename Ordinal>
577MpiComm<Ordinal>::send (
const Ordinal bytes,
578 const char sendBuffer[],
579 const int destRank)
const
581 TEUCHOS_COMM_TIME_MONITOR(
"Teuchos::MpiComm::send(...)" );
583#ifdef TEUCHOS_MPI_COMM_DUMP
585 dumpBuffer<Ordinal,char>(
586 "Teuchos::MpiComm<Ordinal>::send(...)"
587 ,
"sendBuffer", bytes, sendBuffer
592 const int err = MPI_Send (
const_cast<char*
>(sendBuffer), bytes, MPI_CHAR,
593 destRank, tag_, *rawMpiComm_);
595 "Teuchos::MpiComm::send: MPI_Send() failed with error \""
596 << mpiErrorCodeToString (err) <<
"\".");
600template<
typename Ordinal>
602MpiComm<Ordinal>::send (
const Ordinal bytes,
603 const char sendBuffer[],
607 TEUCHOS_COMM_TIME_MONITOR(
"Teuchos::MpiComm::send(...)" );
608 const int err = MPI_Send (
const_cast<char*
> (sendBuffer), bytes, MPI_CHAR,
609 destRank, tag, *rawMpiComm_);
611 "Teuchos::MpiComm::send: MPI_Send() failed with error \""
612 << mpiErrorCodeToString (err) <<
"\".");
616template<
typename Ordinal>
618MpiComm<Ordinal>::ssend (
const Ordinal bytes,
619 const char sendBuffer[],
620 const int destRank)
const
622 TEUCHOS_COMM_TIME_MONITOR(
"Teuchos::MpiComm::ssend(...)" );
624#ifdef TEUCHOS_MPI_COMM_DUMP
626 dumpBuffer<Ordinal,char>(
627 "Teuchos::MpiComm<Ordinal>::send(...)"
628 ,
"sendBuffer", bytes, sendBuffer
633 const int err = MPI_Ssend (
const_cast<char*
>(sendBuffer), bytes, MPI_CHAR,
634 destRank, tag_, *rawMpiComm_);
636 "Teuchos::MpiComm::send: MPI_Ssend() failed with error \""
637 << mpiErrorCodeToString (err) <<
"\".");
640template<
typename Ordinal>
642MpiComm<Ordinal>::ssend (
const Ordinal bytes,
643 const char sendBuffer[],
647 TEUCHOS_COMM_TIME_MONITOR(
"Teuchos::MpiComm::ssend(...)" );
649 MPI_Ssend (
const_cast<char*
>(sendBuffer), bytes, MPI_CHAR,
650 destRank, tag, *rawMpiComm_);
652 "Teuchos::MpiComm::send: MPI_Ssend() failed with error \""
653 << mpiErrorCodeToString (err) <<
"\".");
656template<
typename Ordinal>
657void MpiComm<Ordinal>::readySend(
658 const ArrayView<const char> &sendBuffer,
662 TEUCHOS_COMM_TIME_MONITOR(
"Teuchos::MpiComm::readySend" );
664#ifdef TEUCHOS_MPI_COMM_DUMP
666 dumpBuffer<Ordinal,char>(
667 "Teuchos::MpiComm<Ordinal>::readySend(...)"
668 ,
"sendBuffer", bytes, sendBuffer
674 MPI_Rsend (
const_cast<char*
>(sendBuffer.getRawPtr()),
static_cast<int>(sendBuffer.size()),
675 MPI_CHAR, destRank, tag_, *rawMpiComm_);
677 "Teuchos::MpiComm::readySend: MPI_Rsend() failed with error \""
678 << mpiErrorCodeToString (err) <<
"\".");
682template<
typename Ordinal>
683void MpiComm<Ordinal>::
684readySend (
const Ordinal bytes,
685 const char sendBuffer[],
689 TEUCHOS_COMM_TIME_MONITOR(
"Teuchos::MpiComm::readySend" );
691 MPI_Rsend (
const_cast<char*
> (sendBuffer), bytes,
692 MPI_CHAR, destRank, tag, *rawMpiComm_);
694 "Teuchos::MpiComm::readySend: MPI_Rsend() failed with error \""
695 << mpiErrorCodeToString (err) <<
"\".");
699template<
typename Ordinal>
701MpiComm<Ordinal>::receive (
const int sourceRank,
703 char recvBuffer[])
const
705 TEUCHOS_COMM_TIME_MONITOR(
"Teuchos::MpiComm::receive(...)" );
710 const int theSrcRank = (sourceRank < 0) ? MPI_ANY_SOURCE : sourceRank;
713 const int err = MPI_Recv (recvBuffer, bytes, MPI_CHAR, theSrcRank, tag_,
714 *rawMpiComm_, &status);
716 "Teuchos::MpiComm::receive: MPI_Recv() failed with error \""
717 << mpiErrorCodeToString (err) <<
"\".");
719#ifdef TEUCHOS_MPI_COMM_DUMP
721 dumpBuffer<Ordinal,char> (
"Teuchos::MpiComm<Ordinal>::receive(...)",
722 "recvBuffer", bytes, recvBuffer);
727 return status.MPI_SOURCE;
731template<
typename Ordinal>
732RCP<CommRequest<Ordinal> >
733MpiComm<Ordinal>::isend (
const ArrayView<const char> &sendBuffer,
734 const int destRank)
const
737 TEUCHOS_COMM_TIME_MONITOR(
"Teuchos::MpiComm::isend(...)" );
739 MPI_Request rawMpiRequest = MPI_REQUEST_NULL;
741 MPI_Isend (
const_cast<char*
> (sendBuffer.getRawPtr ()),
742 as<Ordinal> (sendBuffer.size ()), MPI_CHAR,
743 destRank, tag_, *rawMpiComm_, &rawMpiRequest);
745 "Teuchos::MpiComm::isend: MPI_Isend() failed with error \""
746 << mpiErrorCodeToString (err) <<
"\".");
748 return mpiCommRequest<Ordinal> (rawMpiRequest, sendBuffer.size ());
752template<
typename Ordinal>
753RCP<CommRequest<Ordinal> >
755isend (
const ArrayView<const char> &sendBuffer,
760 TEUCHOS_COMM_TIME_MONITOR(
"Teuchos::MpiComm::isend(...)" );
762 MPI_Request rawMpiRequest = MPI_REQUEST_NULL;
764 MPI_Isend (
const_cast<char*
> (sendBuffer.getRawPtr ()),
765 as<Ordinal> (sendBuffer.size ()), MPI_CHAR,
766 destRank, tag, *rawMpiComm_, &rawMpiRequest);
768 "Teuchos::MpiComm::isend: MPI_Isend() failed with error \""
769 << mpiErrorCodeToString (err) <<
"\".");
771 return mpiCommRequest<Ordinal> (rawMpiRequest, sendBuffer.size ());
775template<
typename Ordinal>
776RCP<CommRequest<Ordinal> >
777MpiComm<Ordinal>::ireceive (
const ArrayView<char> &recvBuffer,
778 const int sourceRank)
const
780 TEUCHOS_COMM_TIME_MONITOR(
"Teuchos::MpiComm::ireceive(...)" );
785 const int theSrcRank = (sourceRank < 0) ? MPI_ANY_SOURCE : sourceRank;
787 MPI_Request rawMpiRequest = MPI_REQUEST_NULL;
789 MPI_Irecv (
const_cast<char*
>(recvBuffer.getRawPtr()), recvBuffer.size(),
790 MPI_CHAR, theSrcRank, tag_, *rawMpiComm_, &rawMpiRequest);
792 "Teuchos::MpiComm::ireceive: MPI_Irecv() failed with error \""
793 << mpiErrorCodeToString (err) <<
"\".");
795 return mpiCommRequest<Ordinal> (rawMpiRequest, recvBuffer.size());
798template<
typename Ordinal>
799RCP<CommRequest<Ordinal> >
800MpiComm<Ordinal>::ireceive (
const ArrayView<char> &recvBuffer,
801 const int sourceRank,
804 TEUCHOS_COMM_TIME_MONITOR(
"Teuchos::MpiComm::ireceive(...)" );
809 const int theSrcRank = (sourceRank < 0) ? MPI_ANY_SOURCE : sourceRank;
811 MPI_Request rawMpiRequest = MPI_REQUEST_NULL;
813 MPI_Irecv (
const_cast<char*
> (recvBuffer.getRawPtr ()), recvBuffer.size (),
814 MPI_CHAR, theSrcRank, tag, *rawMpiComm_, &rawMpiRequest);
816 "Teuchos::MpiComm::ireceive: MPI_Irecv() failed with error \""
817 << mpiErrorCodeToString (err) <<
"\".");
819 return mpiCommRequest<Ordinal> (rawMpiRequest, recvBuffer.size ());
824 template<
typename Ordinal>
826 waitAllImpl (
const ArrayView<RCP<CommRequest<Ordinal> > >& requests,
827 const ArrayView<MPI_Status>& rawMpiStatuses)
829 typedef typename ArrayView<RCP<CommRequest<Ordinal> > >::size_type size_type;
830 const size_type count = requests.size();
834 std::logic_error,
"Teuchos::MpiComm's waitAllImpl: rawMpiStatus.size() = "
835 << rawMpiStatuses.size() <<
" != requests.size() = " << requests.size()
836 <<
". Please report this bug to the Tpetra developers.");
849 bool someNullRequests =
false;
850 Array<MPI_Request> rawMpiRequests (count, MPI_REQUEST_NULL);
851 for (
int i = 0; i < count; ++i) {
852 RCP<CommRequest<Ordinal> > request = requests[i];
853 if (! is_null (request)) {
854 RCP<MpiCommRequestBase<Ordinal> > mpiRequest =
855 rcp_dynamic_cast<MpiCommRequestBase<Ordinal> > (request);
863 rawMpiRequests[i] = mpiRequest->releaseRawMpiRequest();
866 rawMpiRequests[i] = MPI_REQUEST_NULL;
867 someNullRequests =
true;
880 const int err = MPI_Waitall (count, rawMpiRequests.getRawPtr(),
881 rawMpiStatuses.getRawPtr());
891 if (err != MPI_SUCCESS) {
892 if (err == MPI_ERR_IN_STATUS) {
900 Array<std::pair<size_type, int> > errorLocationsAndCodes;
901 for (size_type k = 0; k < rawMpiStatuses.size(); ++k) {
902 const int curErr = rawMpiStatuses[k].MPI_ERROR;
903 if (curErr != MPI_SUCCESS) {
904 errorLocationsAndCodes.push_back (std::make_pair (k, curErr));
907 const size_type numErrs = errorLocationsAndCodes.size();
912 std::ostringstream os;
913 os <<
"Teuchos::MpiComm::waitAll: MPI_Waitall() failed with error \""
914 << mpiErrorCodeToString (err) <<
"\". Of the " << count
915 <<
" total request" << (count != 1 ?
"s" :
"") <<
", " << numErrs
916 <<
" failed. Here are the indices of the failed requests, and the "
917 "error codes extracted from their returned MPI_Status objects:"
919 for (size_type k = 0; k < numErrs; ++k) {
920 const size_type errInd = errorLocationsAndCodes[k].first;
921 os <<
"Request " << errInd <<
": MPI_ERROR = "
922 << mpiErrorCodeToString (rawMpiStatuses[errInd].MPI_ERROR)
925 if (someNullRequests) {
926 os <<
" On input to MPI_Waitall, there was at least one MPI_"
927 "Request that was MPI_REQUEST_NULL. MPI_Waitall should not "
928 "normally fail in that case, but we thought we should let you know "
937 std::ostringstream os;
938 os <<
"Teuchos::MpiComm::waitAll: MPI_Waitall() failed with error \""
939 << mpiErrorCodeToString (err) <<
"\".";
940 if (someNullRequests) {
941 os <<
" On input to MPI_Waitall, there was at least one MPI_Request "
942 "that was MPI_REQUEST_NULL. MPI_Waitall should not normally fail in "
943 "that case, but we thought we should let you know regardless.";
951 std::fill (requests.begin(), requests.end(), null);
957 template<
typename Ordinal>
959 waitAllImpl (
const ArrayView<RCP<CommRequest<Ordinal> > >& requests)
961 typedef typename ArrayView<RCP<CommRequest<Ordinal> > >::size_type size_type;
962 const size_type count = requests.size ();
975 bool someNullRequests =
false;
976 Array<MPI_Request> rawMpiRequests (count, MPI_REQUEST_NULL);
977 for (
int i = 0; i < count; ++i) {
978 RCP<CommRequest<Ordinal> > request = requests[i];
979 if (! request.is_null ()) {
980 RCP<MpiCommRequestBase<Ordinal> > mpiRequest =
981 rcp_dynamic_cast<MpiCommRequestBase<Ordinal> > (request);
989 rawMpiRequests[i] = mpiRequest->releaseRawMpiRequest ();
992 rawMpiRequests[i] = MPI_REQUEST_NULL;
993 someNullRequests =
true;
1003 const int err = MPI_Waitall (count, rawMpiRequests.getRawPtr(),
1004 MPI_STATUSES_IGNORE);
1014 if (err != MPI_SUCCESS) {
1015 std::ostringstream os;
1016 os <<
"Teuchos::MpiComm::waitAll: MPI_Waitall() failed with error \""
1017 << mpiErrorCodeToString (err) <<
"\".";
1018 if (someNullRequests) {
1019 os << std::endl <<
"On input to MPI_Waitall, there was at least one "
1020 "MPI_Request that was MPI_REQUEST_NULL. MPI_Waitall should not "
1021 "normally fail in that case, but we thought we should let you know "
1032 std::fill (requests.begin(), requests.end(), null);
1039template<
typename Ordinal>
1042waitAll (
const ArrayView<RCP<CommRequest<Ordinal> > >& requests)
const
1044 TEUCHOS_COMM_TIME_MONITOR(
"Teuchos::MpiComm::waitAll(requests)" );
1047 waitAllImpl<Ordinal> (requests);
1051template<
typename Ordinal>
1054waitAll (
const ArrayView<RCP<CommRequest<Ordinal> > >& requests,
1055 const ArrayView<RCP<CommStatus<Ordinal> > >& statuses)
const
1057 TEUCHOS_COMM_TIME_MONITOR(
"Teuchos::MpiComm::waitAll(requests, statuses)" );
1059 typedef typename ArrayView<RCP<CommRequest<Ordinal> > >::size_type size_type;
1060 const size_type count = requests.size();
1063 std::invalid_argument,
"Teuchos::MpiComm::waitAll: requests.size() = "
1064 << count <<
" != statuses.size() = " << statuses.size() <<
".");
1066 Array<MPI_Status> rawMpiStatuses (count);
1067 waitAllImpl<Ordinal> (requests, rawMpiStatuses());
1070 for (size_type i = 0; i < count; ++i) {
1071 statuses[i] = mpiCommStatus<Ordinal> (rawMpiStatuses[i]);
1076template<
typename Ordinal>
1077RCP<CommStatus<Ordinal> >
1078MpiComm<Ordinal>::wait (
const Ptr<RCP<CommRequest<Ordinal> > >& request)
const
1080 TEUCHOS_COMM_TIME_MONITOR(
"Teuchos::MpiComm::wait(...)" );
1082 if (is_null (*request)) {
1086 RCP<CommStatus<Ordinal> > status = (*request)->wait ();
1094template<
typename Ordinal>
1096MpiComm<Ordinal>::duplicate()
const
1098 MPI_Comm origRawComm = *rawMpiComm_;
1099 MPI_Comm newRawComm = MPI_COMM_NULL;
1100 const int err = MPI_Comm_dup (origRawComm, &newRawComm);
1102 "::MpiComm::duplicate: MPI_Comm_dup failed with the following error: "
1103 << mpiErrorCodeToString (err));
1108 RCP<OpaqueWrapper<MPI_Comm> > wrapped =
1109 opaqueWrapper<MPI_Comm> (newRawComm, details::safeCommFree);
1113 RCP<MpiComm<Ordinal> > newComm =
1114 rcp (
new MpiComm<Ordinal> (wrapped.getConst (), minTag_));
1115 return rcp_implicit_cast<Comm<Ordinal> > (newComm);
1119template<
typename Ordinal>
1121MpiComm<Ordinal>::split(
const int color,
const int key)
const
1124 const int splitReturn =
1125 MPI_Comm_split (*rawMpiComm_,
1126 color < 0 ? MPI_UNDEFINED : color,
1130 splitReturn != MPI_SUCCESS,
1132 "Teuchos::MpiComm::split: Failed to create communicator with color "
1133 << color <<
"and key " << key <<
". MPI_Comm_split failed with error \""
1134 << mpiErrorCodeToString (splitReturn) <<
"\".");
1135 if (newComm == MPI_COMM_NULL) {
1136 return RCP< Comm<Ordinal> >();
1138 RCP<const OpaqueWrapper<MPI_Comm> > wrapped =
1139 opaqueWrapper<MPI_Comm> (newComm, details::safeCommFree);
1144 return rcp (
new MpiComm<Ordinal> (wrapped, minTag_));
1149template<
typename Ordinal>
1151MpiComm<Ordinal>::createSubcommunicator(
const ArrayView<const int> &ranks)
const
1153 int err = MPI_SUCCESS;
1156 MPI_Group thisGroup;
1157 err = MPI_Comm_group (*rawMpiComm_, &thisGroup);
1159 "Failed to obtain the current communicator's group. "
1160 "MPI_Comm_group failed with error \""
1161 << mpiErrorCodeToString (err) <<
"\".");
1169 err = MPI_Group_incl (thisGroup, ranks.size(),
1170 const_cast<int*
> (ranks.getRawPtr ()), &newGroup);
1172 "Failed to create subgroup. MPI_Group_incl failed with error \""
1173 << mpiErrorCodeToString (err) <<
"\".");
1178 err = MPI_Comm_create (*rawMpiComm_, newGroup, &newComm);
1180 "Failed to create subcommunicator. MPI_Comm_create failed with error \""
1181 << mpiErrorCodeToString (err) <<
"\".");
1188 (void) MPI_Group_free (&newGroup);
1189 (void) MPI_Group_free (&thisGroup);
1194 err = MPI_Group_free (&newGroup);
1196 "Failed to free subgroup. MPI_Group_free failed with error \""
1197 << mpiErrorCodeToString (err) <<
"\".");
1198 err = MPI_Group_free (&thisGroup);
1200 "Failed to free subgroup. MPI_Group_free failed with error \""
1201 << mpiErrorCodeToString (err) <<
"\".");
1203 if (newComm == MPI_COMM_NULL) {
1204 return RCP<Comm<Ordinal> > ();
1206 using Teuchos::details::safeCommFree;
1207 typedef OpaqueWrapper<MPI_Comm> ow_type;
1208 RCP<const ow_type> wrapper =
1209 rcp_implicit_cast<const ow_type> (opaqueWrapper (newComm, safeCommFree));
1214 return rcp (
new MpiComm<Ordinal> (wrapper, minTag_));
1222template<
typename Ordinal>
1223std::string MpiComm<Ordinal>::description()
const
1225 std::ostringstream oss;
1231 <<
",rawMpiComm="<<
static_cast<MPI_Comm
>(*rawMpiComm_)
1237#ifdef TEUCHOS_MPI_COMM_DUMP
1238template<
typename Ordinal>
1239bool MpiComm<Ordinal>::show_dump =
false;
1246template<
typename Ordinal>
1247void MpiComm<Ordinal>::assertRank(
const int rank,
const std::string &rankName)
const
1250 ! ( 0 <= rank && rank < size_ ), std::logic_error
1251 ,
"Error, "<<rankName<<
" = " << rank <<
" is not < 0 or is not"
1252 " in the range [0,"<<size_-1<<
"]!"
1260template<
typename Ordinal>
1262Teuchos::createMpiComm(
1263 const RCP<
const OpaqueWrapper<MPI_Comm> > &rawMpiComm
1266 if( rawMpiComm.get()!=NULL && *rawMpiComm != MPI_COMM_NULL )
1267 return rcp(
new MpiComm<Ordinal>(rawMpiComm));
1268 return Teuchos::null;
1272template<
typename Ordinal>
1274Teuchos::createMpiComm(
1275 const RCP<
const OpaqueWrapper<MPI_Comm> > &rawMpiComm,
1276 const int defaultTag
1279 if( rawMpiComm.get()!=NULL && *rawMpiComm != MPI_COMM_NULL )
1280 return rcp(
new MpiComm<Ordinal>(rawMpiComm, defaultTag));
1281 return Teuchos::null;
1285template<
typename Ordinal>
1287Teuchos::getRawMpiComm(
const Comm<Ordinal> &comm)
1290 dyn_cast<const MpiComm<Ordinal> >(comm).getRawMpiComm()
Teuchos header file which uses auto-configuration information to include necessary C++ headers.
Implementation of Teuchos wrappers for MPI.
Smart reference counting pointer class for automatic garbage collection.
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
Macro for throwing an exception with breakpointing to ease debugging.
#define TEUCHOS_ASSERT_EQUALITY(val1, val2)
This macro is checks that to numbers are equal and if not then throws an exception with a good error ...
TypeTo as(const TypeFrom &t)
Convert from one value type to another.
std::string typeName(const T &t)
Template function for returning the concrete type name of a passed-in object.
The Teuchos namespace contains all of the classes, structs and enums used by Teuchos,...
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
Deprecated.