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>::barrier()
const
407 TEUCHOS_COMM_TIME_MONITOR(
408 "Teuchos::MpiComm<"<<OrdinalTraits<Ordinal>::name()<<
">::barrier()"
410 const int err = MPI_Barrier (*rawMpiComm_);
412 "Teuchos::MpiComm::barrier: MPI_Barrier failed with error \""
413 << mpiErrorCodeToString (err) <<
"\".");
417template<
typename Ordinal>
418void MpiComm<Ordinal>::broadcast(
419 const int rootRank,
const Ordinal bytes,
char buffer[]
422 TEUCHOS_COMM_TIME_MONITOR(
423 "Teuchos::MpiComm<"<<OrdinalTraits<Ordinal>::name()<<
">::broadcast(...)"
425 const int err = MPI_Bcast (buffer, bytes, MPI_CHAR, rootRank, *rawMpiComm_);
427 "Teuchos::MpiComm::broadcast: MPI_Bcast failed with error \""
428 << mpiErrorCodeToString (err) <<
"\".");
432template<
typename Ordinal>
433void MpiComm<Ordinal>::gatherAll(
434 const Ordinal sendBytes,
const char sendBuffer[],
435 const Ordinal recvBytes,
char recvBuffer[]
438 TEUCHOS_COMM_TIME_MONITOR(
439 "Teuchos::MpiComm<"<<OrdinalTraits<Ordinal>::name()<<
">::gatherAll(...)"
443 MPI_Allgather (
const_cast<char *
>(sendBuffer), sendBytes, MPI_CHAR,
444 recvBuffer, sendBytes, MPI_CHAR, *rawMpiComm_);
449 "Teuchos::MpiComm::gatherAll: MPI_Allgather failed with error \""
450 << mpiErrorCodeToString (err) <<
"\".");
454template<
typename Ordinal>
456MpiComm<Ordinal>::gather (
const Ordinal sendBytes,
457 const char sendBuffer[],
458 const Ordinal recvBytes,
460 const int root)
const
464 TEUCHOS_COMM_TIME_MONITOR(
465 "Teuchos::MpiComm<"<<OrdinalTraits<Ordinal>::name()<<
">::gather(...)"
468 MPI_Gather (
const_cast<char *
> (sendBuffer), sendBytes, MPI_CHAR,
469 recvBuffer, sendBytes, MPI_CHAR, root, *rawMpiComm_);
471 "Teuchos::MpiComm::gather: MPI_Gather failed with error \""
472 << mpiErrorCodeToString (err) <<
"\".");
476template<
typename Ordinal>
479reduceAll (
const ValueTypeReductionOp<Ordinal,char> &reductOp,
481 const char sendBuffer[],
482 char globalReducts[])
const
484 TEUCHOS_COMM_TIME_MONITOR(
"Teuchos::MpiComm::reduceAll(...)" );
485 int err = MPI_SUCCESS;
487 if (bytes == 0)
return;
489 Details::MpiReductionOp<Ordinal> opWrap (reductOp);
490 MPI_Op op = Details::setMpiReductionOp (opWrap);
499 MPI_Datatype char_block;
500 err = MPI_Type_contiguous (bytes, MPI_CHAR, &char_block);
502 err != MPI_SUCCESS, std::runtime_error,
"Teuchos::reduceAll: "
503 "MPI_Type_contiguous failed with error \"" << mpiErrorCodeToString (err)
505 err = MPI_Type_commit (&char_block);
507 err != MPI_SUCCESS, std::runtime_error,
"Teuchos::reduceAll: "
508 "MPI_Type_commit failed with error \"" << mpiErrorCodeToString (err)
511 if (sendBuffer == globalReducts) {
515 err = MPI_Allreduce (MPI_IN_PLACE, globalReducts, 1,
516 char_block, op, *rawMpiComm_);
519 err = MPI_Allreduce (
const_cast<char*
> (sendBuffer), globalReducts, 1,
520 char_block, op, *rawMpiComm_);
522 if (err != MPI_SUCCESS) {
527 (void) MPI_Type_free (&char_block);
529 true, std::runtime_error,
"Teuchos::reduceAll (MPI, custom op): "
530 "MPI_Allreduce failed with error \"" << mpiErrorCodeToString (err)
533 err = MPI_Type_free (&char_block);
535 err != MPI_SUCCESS, std::runtime_error,
"Teuchos::reduceAll: "
536 "MPI_Type_free failed with error \"" << mpiErrorCodeToString (err)
541template<
typename Ordinal>
542void MpiComm<Ordinal>::scan(
543 const ValueTypeReductionOp<Ordinal,char> &reductOp
544 ,
const Ordinal bytes,
const char sendBuffer[],
char scanReducts[]
547 TEUCHOS_COMM_TIME_MONITOR(
"Teuchos::MpiComm::scan(...)" );
549 Details::MpiReductionOp<Ordinal> opWrap (reductOp);
550 MPI_Op op = Details::setMpiReductionOp (opWrap);
552 MPI_Scan (
const_cast<char*
> (sendBuffer), scanReducts, bytes, MPI_CHAR,
555 "Teuchos::MpiComm::scan: MPI_Scan() failed with error \""
556 << mpiErrorCodeToString (err) <<
"\".");
560template<
typename Ordinal>
562MpiComm<Ordinal>::send (
const Ordinal bytes,
563 const char sendBuffer[],
564 const int destRank)
const
566 TEUCHOS_COMM_TIME_MONITOR(
"Teuchos::MpiComm::send(...)" );
568#ifdef TEUCHOS_MPI_COMM_DUMP
570 dumpBuffer<Ordinal,char>(
571 "Teuchos::MpiComm<Ordinal>::send(...)"
572 ,
"sendBuffer", bytes, sendBuffer
577 const int err = MPI_Send (
const_cast<char*
>(sendBuffer), bytes, MPI_CHAR,
578 destRank, tag_, *rawMpiComm_);
580 "Teuchos::MpiComm::send: MPI_Send() failed with error \""
581 << mpiErrorCodeToString (err) <<
"\".");
585template<
typename Ordinal>
587MpiComm<Ordinal>::send (
const Ordinal bytes,
588 const char sendBuffer[],
592 TEUCHOS_COMM_TIME_MONITOR(
"Teuchos::MpiComm::send(...)" );
593 const int err = MPI_Send (
const_cast<char*
> (sendBuffer), bytes, MPI_CHAR,
594 destRank, tag, *rawMpiComm_);
596 "Teuchos::MpiComm::send: MPI_Send() failed with error \""
597 << mpiErrorCodeToString (err) <<
"\".");
601template<
typename Ordinal>
603MpiComm<Ordinal>::ssend (
const Ordinal bytes,
604 const char sendBuffer[],
605 const int destRank)
const
607 TEUCHOS_COMM_TIME_MONITOR(
"Teuchos::MpiComm::ssend(...)" );
609#ifdef TEUCHOS_MPI_COMM_DUMP
611 dumpBuffer<Ordinal,char>(
612 "Teuchos::MpiComm<Ordinal>::send(...)"
613 ,
"sendBuffer", bytes, sendBuffer
618 const int err = MPI_Ssend (
const_cast<char*
>(sendBuffer), bytes, MPI_CHAR,
619 destRank, tag_, *rawMpiComm_);
621 "Teuchos::MpiComm::send: MPI_Ssend() failed with error \""
622 << mpiErrorCodeToString (err) <<
"\".");
625template<
typename Ordinal>
627MpiComm<Ordinal>::ssend (
const Ordinal bytes,
628 const char sendBuffer[],
632 TEUCHOS_COMM_TIME_MONITOR(
"Teuchos::MpiComm::ssend(...)" );
634 MPI_Ssend (
const_cast<char*
>(sendBuffer), bytes, MPI_CHAR,
635 destRank, tag, *rawMpiComm_);
637 "Teuchos::MpiComm::send: MPI_Ssend() failed with error \""
638 << mpiErrorCodeToString (err) <<
"\".");
641template<
typename Ordinal>
642void MpiComm<Ordinal>::readySend(
643 const ArrayView<const char> &sendBuffer,
647 TEUCHOS_COMM_TIME_MONITOR(
"Teuchos::MpiComm::readySend" );
649#ifdef TEUCHOS_MPI_COMM_DUMP
651 dumpBuffer<Ordinal,char>(
652 "Teuchos::MpiComm<Ordinal>::readySend(...)"
653 ,
"sendBuffer", bytes, sendBuffer
659 MPI_Rsend (
const_cast<char*
>(sendBuffer.getRawPtr()),
static_cast<int>(sendBuffer.size()),
660 MPI_CHAR, destRank, tag_, *rawMpiComm_);
662 "Teuchos::MpiComm::readySend: MPI_Rsend() failed with error \""
663 << mpiErrorCodeToString (err) <<
"\".");
667template<
typename Ordinal>
668void MpiComm<Ordinal>::
669readySend (
const Ordinal bytes,
670 const char sendBuffer[],
674 TEUCHOS_COMM_TIME_MONITOR(
"Teuchos::MpiComm::readySend" );
676 MPI_Rsend (
const_cast<char*
> (sendBuffer), bytes,
677 MPI_CHAR, destRank, tag, *rawMpiComm_);
679 "Teuchos::MpiComm::readySend: MPI_Rsend() failed with error \""
680 << mpiErrorCodeToString (err) <<
"\".");
684template<
typename Ordinal>
686MpiComm<Ordinal>::receive (
const int sourceRank,
688 char recvBuffer[])
const
690 TEUCHOS_COMM_TIME_MONITOR(
"Teuchos::MpiComm::receive(...)" );
695 const int theSrcRank = (sourceRank < 0) ? MPI_ANY_SOURCE : sourceRank;
698 const int err = MPI_Recv (recvBuffer, bytes, MPI_CHAR, theSrcRank, tag_,
699 *rawMpiComm_, &status);
701 "Teuchos::MpiComm::receive: MPI_Recv() failed with error \""
702 << mpiErrorCodeToString (err) <<
"\".");
704#ifdef TEUCHOS_MPI_COMM_DUMP
706 dumpBuffer<Ordinal,char> (
"Teuchos::MpiComm<Ordinal>::receive(...)",
707 "recvBuffer", bytes, recvBuffer);
712 return status.MPI_SOURCE;
716template<
typename Ordinal>
717RCP<CommRequest<Ordinal> >
718MpiComm<Ordinal>::isend (
const ArrayView<const char> &sendBuffer,
719 const int destRank)
const
722 TEUCHOS_COMM_TIME_MONITOR(
"Teuchos::MpiComm::isend(...)" );
724 MPI_Request rawMpiRequest = MPI_REQUEST_NULL;
726 MPI_Isend (
const_cast<char*
> (sendBuffer.getRawPtr ()),
727 as<Ordinal> (sendBuffer.size ()), MPI_CHAR,
728 destRank, tag_, *rawMpiComm_, &rawMpiRequest);
730 "Teuchos::MpiComm::isend: MPI_Isend() failed with error \""
731 << mpiErrorCodeToString (err) <<
"\".");
733 return mpiCommRequest<Ordinal> (rawMpiRequest, sendBuffer.size ());
737template<
typename Ordinal>
738RCP<CommRequest<Ordinal> >
740isend (
const ArrayView<const char> &sendBuffer,
745 TEUCHOS_COMM_TIME_MONITOR(
"Teuchos::MpiComm::isend(...)" );
747 MPI_Request rawMpiRequest = MPI_REQUEST_NULL;
749 MPI_Isend (
const_cast<char*
> (sendBuffer.getRawPtr ()),
750 as<Ordinal> (sendBuffer.size ()), MPI_CHAR,
751 destRank, tag, *rawMpiComm_, &rawMpiRequest);
753 "Teuchos::MpiComm::isend: MPI_Isend() failed with error \""
754 << mpiErrorCodeToString (err) <<
"\".");
756 return mpiCommRequest<Ordinal> (rawMpiRequest, sendBuffer.size ());
760template<
typename Ordinal>
761RCP<CommRequest<Ordinal> >
762MpiComm<Ordinal>::ireceive (
const ArrayView<char> &recvBuffer,
763 const int sourceRank)
const
765 TEUCHOS_COMM_TIME_MONITOR(
"Teuchos::MpiComm::ireceive(...)" );
770 const int theSrcRank = (sourceRank < 0) ? MPI_ANY_SOURCE : sourceRank;
772 MPI_Request rawMpiRequest = MPI_REQUEST_NULL;
774 MPI_Irecv (
const_cast<char*
>(recvBuffer.getRawPtr()), recvBuffer.size(),
775 MPI_CHAR, theSrcRank, tag_, *rawMpiComm_, &rawMpiRequest);
777 "Teuchos::MpiComm::ireceive: MPI_Irecv() failed with error \""
778 << mpiErrorCodeToString (err) <<
"\".");
780 return mpiCommRequest<Ordinal> (rawMpiRequest, recvBuffer.size());
783template<
typename Ordinal>
784RCP<CommRequest<Ordinal> >
785MpiComm<Ordinal>::ireceive (
const ArrayView<char> &recvBuffer,
786 const int sourceRank,
789 TEUCHOS_COMM_TIME_MONITOR(
"Teuchos::MpiComm::ireceive(...)" );
794 const int theSrcRank = (sourceRank < 0) ? MPI_ANY_SOURCE : sourceRank;
796 MPI_Request rawMpiRequest = MPI_REQUEST_NULL;
798 MPI_Irecv (
const_cast<char*
> (recvBuffer.getRawPtr ()), recvBuffer.size (),
799 MPI_CHAR, theSrcRank, tag, *rawMpiComm_, &rawMpiRequest);
801 "Teuchos::MpiComm::ireceive: MPI_Irecv() failed with error \""
802 << mpiErrorCodeToString (err) <<
"\".");
804 return mpiCommRequest<Ordinal> (rawMpiRequest, recvBuffer.size ());
809 template<
typename Ordinal>
811 waitAllImpl (
const ArrayView<RCP<CommRequest<Ordinal> > >& requests,
812 const ArrayView<MPI_Status>& rawMpiStatuses)
814 typedef typename ArrayView<RCP<CommRequest<Ordinal> > >::size_type size_type;
815 const size_type count = requests.size();
819 std::logic_error,
"Teuchos::MpiComm's waitAllImpl: rawMpiStatus.size() = "
820 << rawMpiStatuses.size() <<
" != requests.size() = " << requests.size()
821 <<
". Please report this bug to the Tpetra developers.");
834 bool someNullRequests =
false;
835 Array<MPI_Request> rawMpiRequests (count, MPI_REQUEST_NULL);
836 for (
int i = 0; i < count; ++i) {
837 RCP<CommRequest<Ordinal> > request = requests[i];
838 if (! is_null (request)) {
839 RCP<MpiCommRequestBase<Ordinal> > mpiRequest =
840 rcp_dynamic_cast<MpiCommRequestBase<Ordinal> > (request);
848 rawMpiRequests[i] = mpiRequest->releaseRawMpiRequest();
851 rawMpiRequests[i] = MPI_REQUEST_NULL;
852 someNullRequests =
true;
865 const int err = MPI_Waitall (count, rawMpiRequests.getRawPtr(),
866 rawMpiStatuses.getRawPtr());
876 if (err != MPI_SUCCESS) {
877 if (err == MPI_ERR_IN_STATUS) {
885 Array<std::pair<size_type, int> > errorLocationsAndCodes;
886 for (size_type k = 0; k < rawMpiStatuses.size(); ++k) {
887 const int curErr = rawMpiStatuses[k].MPI_ERROR;
888 if (curErr != MPI_SUCCESS) {
889 errorLocationsAndCodes.push_back (std::make_pair (k, curErr));
892 const size_type numErrs = errorLocationsAndCodes.size();
897 std::ostringstream os;
898 os <<
"Teuchos::MpiComm::waitAll: MPI_Waitall() failed with error \""
899 << mpiErrorCodeToString (err) <<
"\". Of the " << count
900 <<
" total request" << (count != 1 ?
"s" :
"") <<
", " << numErrs
901 <<
" failed. Here are the indices of the failed requests, and the "
902 "error codes extracted from their returned MPI_Status objects:"
904 for (size_type k = 0; k < numErrs; ++k) {
905 const size_type errInd = errorLocationsAndCodes[k].first;
906 os <<
"Request " << errInd <<
": MPI_ERROR = "
907 << mpiErrorCodeToString (rawMpiStatuses[errInd].MPI_ERROR)
910 if (someNullRequests) {
911 os <<
" On input to MPI_Waitall, there was at least one MPI_"
912 "Request that was MPI_REQUEST_NULL. MPI_Waitall should not "
913 "normally fail in that case, but we thought we should let you know "
922 std::ostringstream os;
923 os <<
"Teuchos::MpiComm::waitAll: MPI_Waitall() failed with error \""
924 << mpiErrorCodeToString (err) <<
"\".";
925 if (someNullRequests) {
926 os <<
" On input to MPI_Waitall, there was at least one MPI_Request "
927 "that was MPI_REQUEST_NULL. MPI_Waitall should not normally fail in "
928 "that case, but we thought we should let you know regardless.";
936 std::fill (requests.begin(), requests.end(), null);
942 template<
typename Ordinal>
944 waitAllImpl (
const ArrayView<RCP<CommRequest<Ordinal> > >& requests)
946 typedef typename ArrayView<RCP<CommRequest<Ordinal> > >::size_type size_type;
947 const size_type count = requests.size ();
960 bool someNullRequests =
false;
961 Array<MPI_Request> rawMpiRequests (count, MPI_REQUEST_NULL);
962 for (
int i = 0; i < count; ++i) {
963 RCP<CommRequest<Ordinal> > request = requests[i];
964 if (! request.is_null ()) {
965 RCP<MpiCommRequestBase<Ordinal> > mpiRequest =
966 rcp_dynamic_cast<MpiCommRequestBase<Ordinal> > (request);
974 rawMpiRequests[i] = mpiRequest->releaseRawMpiRequest ();
977 rawMpiRequests[i] = MPI_REQUEST_NULL;
978 someNullRequests =
true;
988 const int err = MPI_Waitall (count, rawMpiRequests.getRawPtr(),
989 MPI_STATUSES_IGNORE);
999 if (err != MPI_SUCCESS) {
1000 std::ostringstream os;
1001 os <<
"Teuchos::MpiComm::waitAll: MPI_Waitall() failed with error \""
1002 << mpiErrorCodeToString (err) <<
"\".";
1003 if (someNullRequests) {
1004 os << std::endl <<
"On input to MPI_Waitall, there was at least one "
1005 "MPI_Request that was MPI_REQUEST_NULL. MPI_Waitall should not "
1006 "normally fail in that case, but we thought we should let you know "
1017 std::fill (requests.begin(), requests.end(), null);
1024template<
typename Ordinal>
1027waitAll (
const ArrayView<RCP<CommRequest<Ordinal> > >& requests)
const
1029 TEUCHOS_COMM_TIME_MONITOR(
"Teuchos::MpiComm::waitAll(requests)" );
1032 waitAllImpl<Ordinal> (requests);
1036template<
typename Ordinal>
1039waitAll (
const ArrayView<RCP<CommRequest<Ordinal> > >& requests,
1040 const ArrayView<RCP<CommStatus<Ordinal> > >& statuses)
const
1042 TEUCHOS_COMM_TIME_MONITOR(
"Teuchos::MpiComm::waitAll(requests, statuses)" );
1044 typedef typename ArrayView<RCP<CommRequest<Ordinal> > >::size_type size_type;
1045 const size_type count = requests.size();
1048 std::invalid_argument,
"Teuchos::MpiComm::waitAll: requests.size() = "
1049 << count <<
" != statuses.size() = " << statuses.size() <<
".");
1051 Array<MPI_Status> rawMpiStatuses (count);
1052 waitAllImpl<Ordinal> (requests, rawMpiStatuses());
1055 for (size_type i = 0; i < count; ++i) {
1056 statuses[i] = mpiCommStatus<Ordinal> (rawMpiStatuses[i]);
1061template<
typename Ordinal>
1062RCP<CommStatus<Ordinal> >
1063MpiComm<Ordinal>::wait (
const Ptr<RCP<CommRequest<Ordinal> > >& request)
const
1065 TEUCHOS_COMM_TIME_MONITOR(
"Teuchos::MpiComm::wait(...)" );
1067 if (is_null (*request)) {
1071 RCP<CommStatus<Ordinal> > status = (*request)->wait ();
1079template<
typename Ordinal>
1081MpiComm<Ordinal>::duplicate()
const
1083 MPI_Comm origRawComm = *rawMpiComm_;
1084 MPI_Comm newRawComm = MPI_COMM_NULL;
1085 const int err = MPI_Comm_dup (origRawComm, &newRawComm);
1087 "::MpiComm::duplicate: MPI_Comm_dup failed with the following error: "
1088 << mpiErrorCodeToString (err));
1093 RCP<OpaqueWrapper<MPI_Comm> > wrapped =
1094 opaqueWrapper<MPI_Comm> (newRawComm, details::safeCommFree);
1098 RCP<MpiComm<Ordinal> > newComm =
1099 rcp (
new MpiComm<Ordinal> (wrapped.getConst (), minTag_));
1100 return rcp_implicit_cast<Comm<Ordinal> > (newComm);
1104template<
typename Ordinal>
1106MpiComm<Ordinal>::split(
const int color,
const int key)
const
1109 const int splitReturn =
1110 MPI_Comm_split (*rawMpiComm_,
1111 color < 0 ? MPI_UNDEFINED : color,
1115 splitReturn != MPI_SUCCESS,
1117 "Teuchos::MpiComm::split: Failed to create communicator with color "
1118 << color <<
"and key " << key <<
". MPI_Comm_split failed with error \""
1119 << mpiErrorCodeToString (splitReturn) <<
"\".");
1120 if (newComm == MPI_COMM_NULL) {
1121 return RCP< Comm<Ordinal> >();
1123 RCP<const OpaqueWrapper<MPI_Comm> > wrapped =
1124 opaqueWrapper<MPI_Comm> (newComm, details::safeCommFree);
1129 return rcp (
new MpiComm<Ordinal> (wrapped, minTag_));
1134template<
typename Ordinal>
1136MpiComm<Ordinal>::createSubcommunicator(
const ArrayView<const int> &ranks)
const
1138 int err = MPI_SUCCESS;
1141 MPI_Group thisGroup;
1142 err = MPI_Comm_group (*rawMpiComm_, &thisGroup);
1144 "Failed to obtain the current communicator's group. "
1145 "MPI_Comm_group failed with error \""
1146 << mpiErrorCodeToString (err) <<
"\".");
1154 err = MPI_Group_incl (thisGroup, ranks.size(),
1155 const_cast<int*
> (ranks.getRawPtr ()), &newGroup);
1157 "Failed to create subgroup. MPI_Group_incl failed with error \""
1158 << mpiErrorCodeToString (err) <<
"\".");
1163 err = MPI_Comm_create (*rawMpiComm_, newGroup, &newComm);
1165 "Failed to create subcommunicator. MPI_Comm_create failed with error \""
1166 << mpiErrorCodeToString (err) <<
"\".");
1173 (void) MPI_Group_free (&newGroup);
1174 (void) MPI_Group_free (&thisGroup);
1179 err = MPI_Group_free (&newGroup);
1181 "Failed to free subgroup. MPI_Group_free failed with error \""
1182 << mpiErrorCodeToString (err) <<
"\".");
1183 err = MPI_Group_free (&thisGroup);
1185 "Failed to free subgroup. MPI_Group_free failed with error \""
1186 << mpiErrorCodeToString (err) <<
"\".");
1188 if (newComm == MPI_COMM_NULL) {
1189 return RCP<Comm<Ordinal> > ();
1191 using Teuchos::details::safeCommFree;
1192 typedef OpaqueWrapper<MPI_Comm> ow_type;
1193 RCP<const ow_type> wrapper =
1194 rcp_implicit_cast<const ow_type> (opaqueWrapper (newComm, safeCommFree));
1199 return rcp (
new MpiComm<Ordinal> (wrapper, minTag_));
1207template<
typename Ordinal>
1208std::string MpiComm<Ordinal>::description()
const
1210 std::ostringstream oss;
1216 <<
",rawMpiComm="<<
static_cast<MPI_Comm
>(*rawMpiComm_)
1222#ifdef TEUCHOS_MPI_COMM_DUMP
1223template<
typename Ordinal>
1224bool MpiComm<Ordinal>::show_dump =
false;
1231template<
typename Ordinal>
1232void MpiComm<Ordinal>::assertRank(
const int rank,
const std::string &rankName)
const
1235 ! ( 0 <= rank && rank < size_ ), std::logic_error
1236 ,
"Error, "<<rankName<<
" = " << rank <<
" is not < 0 or is not"
1237 " in the range [0,"<<size_-1<<
"]!"
1245template<
typename Ordinal>
1247Teuchos::createMpiComm(
1248 const RCP<
const OpaqueWrapper<MPI_Comm> > &rawMpiComm
1251 if( rawMpiComm.get()!=NULL && *rawMpiComm != MPI_COMM_NULL )
1252 return rcp(
new MpiComm<Ordinal>(rawMpiComm));
1253 return Teuchos::null;
1257template<
typename Ordinal>
1259Teuchos::createMpiComm(
1260 const RCP<
const OpaqueWrapper<MPI_Comm> > &rawMpiComm,
1261 const int defaultTag
1264 if( rawMpiComm.get()!=NULL && *rawMpiComm != MPI_COMM_NULL )
1265 return rcp(
new MpiComm<Ordinal>(rawMpiComm, defaultTag));
1266 return Teuchos::null;
1270template<
typename Ordinal>
1272Teuchos::getRawMpiComm(
const Comm<Ordinal> &comm)
1275 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.