10 #ifndef TEUCHOS_MPI_COMM_HPP
11 #define TEUCHOS_MPI_COMM_HPP
21 #ifdef HAVE_TEUCHOS_MPI
23 #include "Teuchos_Comm.hpp"
24 #include "Teuchos_CommUtilities.hpp"
26 #include "Teuchos_OpaqueWrapper.hpp"
28 #include "Teuchos_SerializationTraitsHelpers.hpp"
29 #include "Teuchos_Workspace.hpp"
32 #include "Teuchos_Assert.hpp"
39 #ifdef TEUCHOS_MPI_COMM_DUMP
40 # include "Teuchos_VerboseObject.hpp"
46 TEUCHOSCOMM_LIB_DLL_EXPORT std::string
47 mpiErrorCodeToString (
const int err);
63 TEUCHOSCOMM_LIB_DLL_EXPORT
void safeCommFree (MPI_Comm* comm);
69 TEUCHOSCOMM_LIB_DLL_EXPORT
int setCommErrhandler (MPI_Comm comm, MPI_Errhandler handler);
73 #ifdef TEUCHOS_MPI_COMM_DUMP
74 template<
typename Ordinal,
typename T>
76 const std::string &funcName,
const std::string &buffName
77 ,
const Ordinal bytes,
const T buff[]
84 <<
"\n" << funcName <<
"::" << buffName <<
":\n";
86 for( Ordinal i = 0; i < bytes; ++i ) {
87 *out << buffName <<
"[" << i <<
"] = '" << buff[i] <<
"'\n";
91 #endif // TEUCHOS_MPI_COMM_DUMP
104 template<
class OrdinalType>
105 class MpiCommStatus :
public CommStatus<OrdinalType> {
107 MpiCommStatus (MPI_Status status) : status_ (status) {}
110 virtual ~MpiCommStatus() {}
113 OrdinalType getSourceRank () {
return status_.MPI_SOURCE; }
116 OrdinalType getTag () {
return status_.MPI_TAG; }
119 OrdinalType getError () {
return status_.MPI_ERROR; }
132 template<
class OrdinalType>
133 inline RCP<MpiCommStatus<OrdinalType> >
134 mpiCommStatus (MPI_Status rawMpiStatus)
136 return rcp (
new MpiCommStatus<OrdinalType> (rawMpiStatus));
154 template<
class OrdinalType>
155 class MpiCommRequestBase :
public CommRequest<OrdinalType> {
158 MpiCommRequestBase () :
159 rawMpiRequest_ (MPI_REQUEST_NULL)
163 MpiCommRequestBase (MPI_Request rawMpiRequest) :
164 rawMpiRequest_ (rawMpiRequest)
174 MPI_Request releaseRawMpiRequest()
176 MPI_Request tmp_rawMpiRequest = rawMpiRequest_;
177 rawMpiRequest_ = MPI_REQUEST_NULL;
178 return tmp_rawMpiRequest;
182 bool isNull()
const {
183 return rawMpiRequest_ == MPI_REQUEST_NULL;
187 MPI_Status rawMpiStatus;
190 MPI_Test(&rawMpiRequest_, &flag, &rawMpiStatus);
200 RCP<CommStatus<OrdinalType> > wait () {
201 MPI_Status rawMpiStatus;
204 const int err = MPI_Wait (&rawMpiRequest_, &rawMpiStatus);
206 err != MPI_SUCCESS, std::runtime_error,
207 "Teuchos: MPI_Wait() failed with error \""
208 << mpiErrorCodeToString (err));
210 return mpiCommStatus<OrdinalType> (rawMpiStatus);
217 RCP<CommStatus<OrdinalType> > cancel () {
218 if (rawMpiRequest_ == MPI_REQUEST_NULL) {
222 int err = MPI_Cancel (&rawMpiRequest_);
224 err != MPI_SUCCESS, std::runtime_error,
225 "Teuchos: MPI_Cancel failed with the following error: "
226 << mpiErrorCodeToString (err));
233 err = MPI_Wait (&rawMpiRequest_, &status);
235 "Teuchos::MpiCommStatus::cancel: MPI_Wait failed with the following "
236 "error: " << mpiErrorCodeToString (err));
237 return mpiCommStatus<OrdinalType> (status);
242 virtual ~MpiCommRequestBase () {
243 if (rawMpiRequest_ != MPI_REQUEST_NULL) {
246 const int err = MPI_Cancel (&rawMpiRequest_);
247 if (err == MPI_SUCCESS) {
264 (void) MPI_Wait (&rawMpiRequest_, MPI_STATUS_IGNORE);
271 MPI_Request rawMpiRequest_;
289 template<
class OrdinalType>
290 class MpiCommRequest :
public MpiCommRequestBase<OrdinalType> {
294 MpiCommRequestBase<OrdinalType> (MPI_REQUEST_NULL),
299 MpiCommRequest (MPI_Request rawMpiRequest,
300 const ArrayView<char>::size_type numBytesInMessage) :
301 MpiCommRequestBase<OrdinalType> (rawMpiRequest),
302 numBytes_ (numBytesInMessage)
310 ArrayView<char>::size_type numBytes ()
const {
315 virtual ~MpiCommRequest () {}
319 ArrayView<char>::size_type numBytes_;
330 template<
class OrdinalType>
331 inline RCP<MpiCommRequest<OrdinalType> >
332 mpiCommRequest (MPI_Request rawMpiRequest,
333 const ArrayView<char>::size_type numBytes)
335 return rcp (
new MpiCommRequest<OrdinalType> (rawMpiRequest, numBytes));
353 template<
typename Ordinal>
354 class MpiComm :
public Comm<Ordinal> {
379 explicit MpiComm (MPI_Comm rawMpiComm);
395 MpiComm (
const RCP<
const OpaqueWrapper<MPI_Comm> >& rawMpiComm);
414 MpiComm (
const RCP<
const OpaqueWrapper<MPI_Comm> >& rawMpiComm,
415 const int defaultTag);
433 MpiComm (
const MpiComm<Ordinal>& other);
436 RCP<const OpaqueWrapper<MPI_Comm> > getRawMpiComm ()
const {
504 void setErrorHandler (
const RCP<
const OpaqueWrapper<MPI_Errhandler> >& errHandler);
511 virtual int getRank()
const;
514 virtual int getSize()
const;
517 virtual void barrier()
const;
520 virtual void broadcast(
521 const int rootRank,
const Ordinal bytes,
char buffer[]
526 gather (
const Ordinal sendBytes,
const char sendBuffer[],
527 const Ordinal recvBytes,
char recvBuffer[],
528 const int root)
const;
530 virtual void gatherAll(
531 const Ordinal sendBytes,
const char sendBuffer[]
532 ,
const Ordinal recvBytes,
char recvBuffer[]
535 virtual void reduceAll(
536 const ValueTypeReductionOp<Ordinal,char> &reductOp
537 ,
const Ordinal bytes,
const char sendBuffer[],
char globalReducts[]
541 const ValueTypeReductionOp<Ordinal,char> &reductOp
542 ,
const Ordinal bytes,
const char sendBuffer[],
char scanReducts[]
546 const Ordinal bytes,
const char sendBuffer[],
const int destRank
550 send (
const Ordinal bytes,
551 const char sendBuffer[],
553 const int tag)
const;
556 const Ordinal bytes,
const char sendBuffer[],
const int destRank
560 ssend (
const Ordinal bytes,
561 const char sendBuffer[],
563 const int tag)
const;
566 const int sourceRank,
const Ordinal bytes,
char recvBuffer[]
570 const ArrayView<const char> &sendBuffer,
576 const char sendBuffer[],
578 const int tag)
const;
580 virtual RCP<CommRequest<Ordinal> > isend(
581 const ArrayView<const char> &sendBuffer,
585 virtual RCP<CommRequest<Ordinal> >
586 isend (
const ArrayView<const char> &sendBuffer,
588 const int tag)
const;
590 virtual RCP<CommRequest<Ordinal> >
ireceive(
591 const ArrayView<char> &Buffer,
595 virtual RCP<CommRequest<Ordinal> >
596 ireceive (
const ArrayView<char> &Buffer,
597 const int sourceRank,
598 const int tag)
const;
600 virtual void waitAll(
601 const ArrayView<RCP<CommRequest<Ordinal> > > &requests
605 waitAll (
const ArrayView<RCP<CommRequest<Ordinal> > >& requests,
606 const ArrayView<RCP<CommStatus<Ordinal> > >& statuses)
const;
608 virtual RCP<CommStatus<Ordinal> >
609 wait (
const Ptr<RCP<CommRequest<Ordinal> > >& request)
const;
611 virtual RCP< Comm<Ordinal> > duplicate()
const;
613 virtual RCP< Comm<Ordinal> > split(
const int color,
const int key)
const;
615 virtual RCP< Comm<Ordinal> > createSubcommunicator(
616 const ArrayView<const int>& ranks)
const;
623 std::string description()
const;
629 static int const minTag_ = 26000;
630 static int const maxTag_ = 26099;
637 int getTag ()
const {
return tag_; }
641 if (tag_ == std::numeric_limits<int>::max())
651 void setupMembersFromComm();
652 static int tagCounter_;
661 RCP<const OpaqueWrapper<MPI_Comm> > rawMpiComm_;
679 RCP<const OpaqueWrapper<MPI_Errhandler> > customErrorHandler_;
681 void assertRank(
const int rank,
const std::string &rankName)
const;
686 #ifdef TEUCHOS_MPI_COMM_DUMP
688 static bool show_dump;
689 #endif // TEUCHOS_MPI_COMM_DUMP
707 template<
typename Ordinal>
708 RCP<MpiComm<Ordinal> >
710 const RCP<
const OpaqueWrapper<MPI_Comm> > &rawMpiComm
727 template<
typename Ordinal>
728 RCP<MpiComm<Ordinal> >
730 const RCP<
const OpaqueWrapper<MPI_Comm> > &rawMpiComm,
762 template<
typename Ordinal>
764 getRawMpiComm(
const Comm<Ordinal> &comm);
774 template<
typename Ordinal>
775 int MpiComm<Ordinal>::tagCounter_ = MpiComm<Ordinal>::minTag_;
781 template<
typename Ordinal>
783 MpiComm (
const RCP<
const OpaqueWrapper<MPI_Comm> >& rawMpiComm)
786 rawMpiComm.get () == NULL, std::invalid_argument,
787 "Teuchos::MpiComm constructor: The input RCP is null.");
789 *rawMpiComm == MPI_COMM_NULL, std::invalid_argument,
790 "Teuchos::MpiComm constructor: The given MPI_Comm is MPI_COMM_NULL.");
792 rawMpiComm_ = rawMpiComm;
806 setupMembersFromComm ();
810 template<
typename Ordinal>
812 MpiComm (
const RCP<
const OpaqueWrapper<MPI_Comm> >& rawMpiComm,
813 const int defaultTag)
816 rawMpiComm.get () == NULL, std::invalid_argument,
817 "Teuchos::MpiComm constructor: The input RCP is null.");
819 *rawMpiComm == MPI_COMM_NULL, std::invalid_argument,
820 "Teuchos::MpiComm constructor: The given MPI_Comm is MPI_COMM_NULL.");
822 rawMpiComm_ = rawMpiComm;
824 int err = MPI_Comm_size (*rawMpiComm_, &size_);
826 "Teuchos::MpiComm constructor: MPI_Comm_size failed with "
827 "error \"" << mpiErrorCodeToString (err) <<
"\".");
829 err = MPI_Comm_rank (*rawMpiComm_, &rank_);
831 "Teuchos::MpiComm constructor: MPI_Comm_rank failed with "
832 "error \"" << mpiErrorCodeToString (err) <<
"\".");
837 template<
typename Ordinal>
838 MpiComm<Ordinal>::MpiComm (MPI_Comm rawMpiComm)
841 std::invalid_argument,
"Teuchos::MpiComm constructor: The given MPI_Comm "
842 "is MPI_COMM_NULL.");
846 rawMpiComm_ = opaqueWrapper<MPI_Comm> (rawMpiComm);
860 setupMembersFromComm ();
864 template<
typename Ordinal>
865 MpiComm<Ordinal>::MpiComm (
const MpiComm<Ordinal>& other) :
866 rawMpiComm_ (opaqueWrapper<MPI_Comm> (MPI_COMM_NULL))
869 RCP<const OpaqueWrapper<MPI_Comm> > origCommPtr = other.getRawMpiComm ();
871 "Teuchos::MpiComm copy constructor: "
872 "The input's getRawMpiComm() method returns null.");
873 MPI_Comm origComm = *origCommPtr;
875 "Teuchos::MpiComm copy constructor: "
876 "The input's raw MPI_Comm is MPI_COMM_NULL.");
884 rawMpiComm_ = origCommPtr;
888 const int err = MPI_Comm_dup (origComm, &newComm);
890 "Teuchos::MpiComm copy constructor: MPI_Comm_dup failed with "
891 "the following error: " << mpiErrorCodeToString (err));
893 rawMpiComm_ = opaqueWrapper (newComm, details::safeCommFree);
896 setupMembersFromComm ();
900 template<
typename Ordinal>
901 void MpiComm<Ordinal>::setupMembersFromComm ()
903 int err = MPI_Comm_size (*rawMpiComm_, &size_);
905 "Teuchos::MpiComm constructor: MPI_Comm_size failed with "
906 "error \"" << mpiErrorCodeToString (err) <<
"\".");
907 err = MPI_Comm_rank (*rawMpiComm_, &rank_);
909 "Teuchos::MpiComm constructor: MPI_Comm_rank failed with "
910 "error \"" << mpiErrorCodeToString (err) <<
"\".");
913 if (tagCounter_ > maxTag_) {
914 tagCounter_ = minTag_;
916 tag_ = tagCounter_++;
926 MPI_Bcast (&tag_, 1, MPI_INT, 0, *rawMpiComm_);
930 template<
typename Ordinal>
933 setErrorHandler (
const RCP<
const OpaqueWrapper<MPI_Errhandler> >& errHandler)
936 const int err = details::setCommErrhandler (*getRawMpiComm (), *errHandler);
938 "Teuchos::MpiComm: Setting the MPI_Comm's error handler failed with "
939 "error \"" << mpiErrorCodeToString (err) <<
"\".");
943 customErrorHandler_ = errHandler;
950 template<
typename Ordinal>
951 int MpiComm<Ordinal>::getRank()
const
957 template<
typename Ordinal>
958 int MpiComm<Ordinal>::getSize()
const
964 template<
typename Ordinal>
965 void MpiComm<Ordinal>::barrier()
const
967 TEUCHOS_COMM_TIME_MONITOR(
968 "Teuchos::MpiComm<"<<OrdinalTraits<Ordinal>::name()<<
">::barrier()"
970 const int err = MPI_Barrier (*rawMpiComm_);
972 "Teuchos::MpiComm::barrier: MPI_Barrier failed with error \""
973 << mpiErrorCodeToString (err) <<
"\".");
977 template<
typename Ordinal>
978 void MpiComm<Ordinal>::broadcast(
979 const int rootRank,
const Ordinal bytes,
char buffer[]
982 TEUCHOS_COMM_TIME_MONITOR(
983 "Teuchos::MpiComm<"<<OrdinalTraits<Ordinal>::name()<<
">::broadcast(...)"
985 const int err = MPI_Bcast (buffer, bytes, MPI_CHAR, rootRank, *rawMpiComm_);
987 "Teuchos::MpiComm::broadcast: MPI_Bcast failed with error \""
988 << mpiErrorCodeToString (err) <<
"\".");
992 template<
typename Ordinal>
993 void MpiComm<Ordinal>::gatherAll(
994 const Ordinal sendBytes,
const char sendBuffer[],
995 const Ordinal recvBytes,
char recvBuffer[]
998 TEUCHOS_COMM_TIME_MONITOR(
999 "Teuchos::MpiComm<"<<OrdinalTraits<Ordinal>::name()<<
">::gatherAll(...)"
1003 MPI_Allgather (const_cast<char *>(sendBuffer), sendBytes, MPI_CHAR,
1004 recvBuffer, sendBytes, MPI_CHAR, *rawMpiComm_);
1009 "Teuchos::MpiComm::gatherAll: MPI_Allgather failed with error \""
1010 << mpiErrorCodeToString (err) <<
"\".");
1014 template<
typename Ordinal>
1016 MpiComm<Ordinal>::gather (
const Ordinal sendBytes,
1017 const char sendBuffer[],
1018 const Ordinal recvBytes,
1020 const int root)
const
1024 TEUCHOS_COMM_TIME_MONITOR(
1025 "Teuchos::MpiComm<"<<OrdinalTraits<Ordinal>::name()<<
">::gather(...)"
1028 MPI_Gather (const_cast<char *> (sendBuffer), sendBytes, MPI_CHAR,
1029 recvBuffer, sendBytes, MPI_CHAR, root, *rawMpiComm_);
1031 "Teuchos::MpiComm::gather: MPI_Gather failed with error \""
1032 << mpiErrorCodeToString (err) <<
"\".");
1036 template<
typename Ordinal>
1039 reduceAll (
const ValueTypeReductionOp<Ordinal,char> &reductOp,
1040 const Ordinal bytes,
1041 const char sendBuffer[],
1042 char globalReducts[])
const
1044 TEUCHOS_COMM_TIME_MONITOR(
"Teuchos::MpiComm::reduceAll(...)" );
1045 int err = MPI_SUCCESS;
1047 if (bytes == 0)
return;
1049 Details::MpiReductionOp<Ordinal> opWrap (reductOp);
1050 MPI_Op op = Details::setMpiReductionOp (opWrap);
1059 MPI_Datatype char_block;
1060 err = MPI_Type_contiguous (bytes, MPI_CHAR, &char_block);
1062 err != MPI_SUCCESS, std::runtime_error,
"Teuchos::reduceAll: "
1063 "MPI_Type_contiguous failed with error \"" << mpiErrorCodeToString (err)
1065 err = MPI_Type_commit (&char_block);
1067 err != MPI_SUCCESS, std::runtime_error,
"Teuchos::reduceAll: "
1068 "MPI_Type_commit failed with error \"" << mpiErrorCodeToString (err)
1071 if (sendBuffer == globalReducts) {
1075 err = MPI_Allreduce (MPI_IN_PLACE, globalReducts, 1,
1076 char_block, op, *rawMpiComm_);
1079 err = MPI_Allreduce (const_cast<char*> (sendBuffer), globalReducts, 1,
1080 char_block, op, *rawMpiComm_);
1082 if (err != MPI_SUCCESS) {
1087 (void) MPI_Type_free (&char_block);
1089 true, std::runtime_error,
"Teuchos::reduceAll (MPI, custom op): "
1090 "MPI_Allreduce failed with error \"" << mpiErrorCodeToString (err)
1093 err = MPI_Type_free (&char_block);
1095 err != MPI_SUCCESS, std::runtime_error,
"Teuchos::reduceAll: "
1096 "MPI_Type_free failed with error \"" << mpiErrorCodeToString (err)
1101 template<
typename Ordinal>
1102 void MpiComm<Ordinal>::scan(
1103 const ValueTypeReductionOp<Ordinal,char> &reductOp
1104 ,
const Ordinal bytes,
const char sendBuffer[],
char scanReducts[]
1107 TEUCHOS_COMM_TIME_MONITOR(
"Teuchos::MpiComm::scan(...)" );
1109 Details::MpiReductionOp<Ordinal> opWrap (reductOp);
1110 MPI_Op op = Details::setMpiReductionOp (opWrap);
1112 MPI_Scan (const_cast<char*> (sendBuffer), scanReducts, bytes, MPI_CHAR,
1115 "Teuchos::MpiComm::scan: MPI_Scan() failed with error \""
1116 << mpiErrorCodeToString (err) <<
"\".");
1120 template<
typename Ordinal>
1122 MpiComm<Ordinal>::send (
const Ordinal bytes,
1123 const char sendBuffer[],
1124 const int destRank)
const
1126 TEUCHOS_COMM_TIME_MONITOR(
"Teuchos::MpiComm::send(...)" );
1128 #ifdef TEUCHOS_MPI_COMM_DUMP
1130 dumpBuffer<Ordinal,char>(
1131 "Teuchos::MpiComm<Ordinal>::send(...)"
1132 ,
"sendBuffer", bytes, sendBuffer
1135 #endif // TEUCHOS_MPI_COMM_DUMP
1137 const int err = MPI_Send (const_cast<char*>(sendBuffer), bytes, MPI_CHAR,
1138 destRank, tag_, *rawMpiComm_);
1140 "Teuchos::MpiComm::send: MPI_Send() failed with error \""
1141 << mpiErrorCodeToString (err) <<
"\".");
1145 template<
typename Ordinal>
1147 MpiComm<Ordinal>::send (
const Ordinal bytes,
1148 const char sendBuffer[],
1150 const int tag)
const
1152 TEUCHOS_COMM_TIME_MONITOR(
"Teuchos::MpiComm::send(...)" );
1153 const int err = MPI_Send (const_cast<char*> (sendBuffer), bytes, MPI_CHAR,
1154 destRank, tag, *rawMpiComm_);
1156 "Teuchos::MpiComm::send: MPI_Send() failed with error \""
1157 << mpiErrorCodeToString (err) <<
"\".");
1161 template<
typename Ordinal>
1163 MpiComm<Ordinal>::ssend (
const Ordinal bytes,
1164 const char sendBuffer[],
1165 const int destRank)
const
1167 TEUCHOS_COMM_TIME_MONITOR(
"Teuchos::MpiComm::ssend(...)" );
1169 #ifdef TEUCHOS_MPI_COMM_DUMP
1171 dumpBuffer<Ordinal,char>(
1172 "Teuchos::MpiComm<Ordinal>::send(...)"
1173 ,
"sendBuffer", bytes, sendBuffer
1176 #endif // TEUCHOS_MPI_COMM_DUMP
1178 const int err = MPI_Ssend (const_cast<char*>(sendBuffer), bytes, MPI_CHAR,
1179 destRank, tag_, *rawMpiComm_);
1181 "Teuchos::MpiComm::send: MPI_Ssend() failed with error \""
1182 << mpiErrorCodeToString (err) <<
"\".");
1185 template<
typename Ordinal>
1187 MpiComm<Ordinal>::ssend (
const Ordinal bytes,
1188 const char sendBuffer[],
1190 const int tag)
const
1192 TEUCHOS_COMM_TIME_MONITOR(
"Teuchos::MpiComm::ssend(...)" );
1194 MPI_Ssend (const_cast<char*>(sendBuffer), bytes, MPI_CHAR,
1195 destRank, tag, *rawMpiComm_);
1197 "Teuchos::MpiComm::send: MPI_Ssend() failed with error \""
1198 << mpiErrorCodeToString (err) <<
"\".");
1201 template<
typename Ordinal>
1202 void MpiComm<Ordinal>::readySend(
1203 const ArrayView<const char> &sendBuffer,
1207 TEUCHOS_COMM_TIME_MONITOR(
"Teuchos::MpiComm::readySend" );
1209 #ifdef TEUCHOS_MPI_COMM_DUMP
1211 dumpBuffer<Ordinal,char>(
1212 "Teuchos::MpiComm<Ordinal>::readySend(...)"
1213 ,
"sendBuffer", bytes, sendBuffer
1216 #endif // TEUCHOS_MPI_COMM_DUMP
1219 MPI_Rsend (const_cast<char*>(sendBuffer.getRawPtr()), static_cast<int>(sendBuffer.size()),
1220 MPI_CHAR, destRank, tag_, *rawMpiComm_);
1222 "Teuchos::MpiComm::readySend: MPI_Rsend() failed with error \""
1223 << mpiErrorCodeToString (err) <<
"\".");
1227 template<
typename Ordinal>
1228 void MpiComm<Ordinal>::
1229 readySend (
const Ordinal bytes,
1230 const char sendBuffer[],
1232 const int tag)
const
1234 TEUCHOS_COMM_TIME_MONITOR(
"Teuchos::MpiComm::readySend" );
1236 MPI_Rsend (const_cast<char*> (sendBuffer), bytes,
1237 MPI_CHAR, destRank, tag, *rawMpiComm_);
1239 "Teuchos::MpiComm::readySend: MPI_Rsend() failed with error \""
1240 << mpiErrorCodeToString (err) <<
"\".");
1244 template<
typename Ordinal>
1246 MpiComm<Ordinal>::receive (
const int sourceRank,
1247 const Ordinal bytes,
1248 char recvBuffer[])
const
1250 TEUCHOS_COMM_TIME_MONITOR(
"Teuchos::MpiComm::receive(...)" );
1255 const int theSrcRank = (sourceRank < 0) ? MPI_ANY_SOURCE : sourceRank;
1258 const int err = MPI_Recv (recvBuffer, bytes, MPI_CHAR, theSrcRank, tag_,
1259 *rawMpiComm_, &status);
1261 "Teuchos::MpiComm::receive: MPI_Recv() failed with error \""
1262 << mpiErrorCodeToString (err) <<
"\".");
1264 #ifdef TEUCHOS_MPI_COMM_DUMP
1266 dumpBuffer<Ordinal,char> (
"Teuchos::MpiComm<Ordinal>::receive(...)",
1267 "recvBuffer", bytes, recvBuffer);
1269 #endif // TEUCHOS_MPI_COMM_DUMP
1272 return status.MPI_SOURCE;
1276 template<
typename Ordinal>
1277 RCP<CommRequest<Ordinal> >
1278 MpiComm<Ordinal>::isend (
const ArrayView<const char> &sendBuffer,
1279 const int destRank)
const
1282 TEUCHOS_COMM_TIME_MONITOR(
"Teuchos::MpiComm::isend(...)" );
1284 MPI_Request rawMpiRequest = MPI_REQUEST_NULL;
1286 MPI_Isend (const_cast<char*> (sendBuffer.getRawPtr ()),
1287 as<Ordinal> (sendBuffer.size ()), MPI_CHAR,
1288 destRank, tag_, *rawMpiComm_, &rawMpiRequest);
1290 "Teuchos::MpiComm::isend: MPI_Isend() failed with error \""
1291 << mpiErrorCodeToString (err) <<
"\".");
1293 return mpiCommRequest<Ordinal> (rawMpiRequest, sendBuffer.size ());
1297 template<
typename Ordinal>
1298 RCP<CommRequest<Ordinal> >
1300 isend (
const ArrayView<const char> &sendBuffer,
1302 const int tag)
const
1305 TEUCHOS_COMM_TIME_MONITOR(
"Teuchos::MpiComm::isend(...)" );
1307 MPI_Request rawMpiRequest = MPI_REQUEST_NULL;
1309 MPI_Isend (const_cast<char*> (sendBuffer.getRawPtr ()),
1310 as<Ordinal> (sendBuffer.size ()), MPI_CHAR,
1311 destRank, tag, *rawMpiComm_, &rawMpiRequest);
1313 "Teuchos::MpiComm::isend: MPI_Isend() failed with error \""
1314 << mpiErrorCodeToString (err) <<
"\".");
1316 return mpiCommRequest<Ordinal> (rawMpiRequest, sendBuffer.size ());
1320 template<
typename Ordinal>
1321 RCP<CommRequest<Ordinal> >
1322 MpiComm<Ordinal>::ireceive (
const ArrayView<char> &recvBuffer,
1323 const int sourceRank)
const
1325 TEUCHOS_COMM_TIME_MONITOR(
"Teuchos::MpiComm::ireceive(...)" );
1330 const int theSrcRank = (sourceRank < 0) ? MPI_ANY_SOURCE : sourceRank;
1332 MPI_Request rawMpiRequest = MPI_REQUEST_NULL;
1334 MPI_Irecv (const_cast<char*>(recvBuffer.getRawPtr()), recvBuffer.size(),
1335 MPI_CHAR, theSrcRank, tag_, *rawMpiComm_, &rawMpiRequest);
1337 "Teuchos::MpiComm::ireceive: MPI_Irecv() failed with error \""
1338 << mpiErrorCodeToString (err) <<
"\".");
1340 return mpiCommRequest<Ordinal> (rawMpiRequest, recvBuffer.size());
1343 template<
typename Ordinal>
1344 RCP<CommRequest<Ordinal> >
1345 MpiComm<Ordinal>::ireceive (
const ArrayView<char> &recvBuffer,
1346 const int sourceRank,
1347 const int tag)
const
1349 TEUCHOS_COMM_TIME_MONITOR(
"Teuchos::MpiComm::ireceive(...)" );
1354 const int theSrcRank = (sourceRank < 0) ? MPI_ANY_SOURCE : sourceRank;
1356 MPI_Request rawMpiRequest = MPI_REQUEST_NULL;
1358 MPI_Irecv (const_cast<char*> (recvBuffer.getRawPtr ()), recvBuffer.size (),
1359 MPI_CHAR, theSrcRank, tag, *rawMpiComm_, &rawMpiRequest);
1361 "Teuchos::MpiComm::ireceive: MPI_Irecv() failed with error \""
1362 << mpiErrorCodeToString (err) <<
"\".");
1364 return mpiCommRequest<Ordinal> (rawMpiRequest, recvBuffer.size ());
1369 template<
typename Ordinal>
1371 waitAllImpl (
const ArrayView<RCP<CommRequest<Ordinal> > >& requests,
1372 const ArrayView<MPI_Status>& rawMpiStatuses)
1374 typedef typename ArrayView<RCP<CommRequest<Ordinal> > >::size_type size_type;
1375 const size_type count = requests.size();
1379 std::logic_error,
"Teuchos::MpiComm's waitAllImpl: rawMpiStatus.size() = "
1380 << rawMpiStatuses.size() <<
" != requests.size() = " << requests.size()
1381 <<
". Please report this bug to the Tpetra developers.");
1394 bool someNullRequests =
false;
1395 Array<MPI_Request> rawMpiRequests (count, MPI_REQUEST_NULL);
1396 for (
int i = 0; i < count; ++i) {
1397 RCP<CommRequest<Ordinal> > request = requests[i];
1399 RCP<MpiCommRequestBase<Ordinal> > mpiRequest =
1400 rcp_dynamic_cast<MpiCommRequestBase<Ordinal> > (request);
1408 rawMpiRequests[i] = mpiRequest->releaseRawMpiRequest();
1411 rawMpiRequests[i] = MPI_REQUEST_NULL;
1412 someNullRequests =
true;
1425 const int err = MPI_Waitall (count, rawMpiRequests.getRawPtr(),
1426 rawMpiStatuses.getRawPtr());
1436 if (err != MPI_SUCCESS) {
1437 if (err == MPI_ERR_IN_STATUS) {
1445 Array<std::pair<size_type, int> > errorLocationsAndCodes;
1446 for (size_type k = 0; k < rawMpiStatuses.size(); ++k) {
1447 const int curErr = rawMpiStatuses[k].MPI_ERROR;
1448 if (curErr != MPI_SUCCESS) {
1449 errorLocationsAndCodes.push_back (std::make_pair (k, curErr));
1452 const size_type numErrs = errorLocationsAndCodes.size();
1457 std::ostringstream os;
1458 os <<
"Teuchos::MpiComm::waitAll: MPI_Waitall() failed with error \""
1459 << mpiErrorCodeToString (err) <<
"\". Of the " << count
1460 <<
" total request" << (count != 1 ?
"s" :
"") <<
", " << numErrs
1461 <<
" failed. Here are the indices of the failed requests, and the "
1462 "error codes extracted from their returned MPI_Status objects:"
1464 for (size_type k = 0; k < numErrs; ++k) {
1465 const size_type errInd = errorLocationsAndCodes[k].first;
1466 os <<
"Request " << errInd <<
": MPI_ERROR = "
1467 << mpiErrorCodeToString (rawMpiStatuses[errInd].MPI_ERROR)
1470 if (someNullRequests) {
1471 os <<
" On input to MPI_Waitall, there was at least one MPI_"
1472 "Request that was MPI_REQUEST_NULL. MPI_Waitall should not "
1473 "normally fail in that case, but we thought we should let you know "
1482 std::ostringstream os;
1483 os <<
"Teuchos::MpiComm::waitAll: MPI_Waitall() failed with error \""
1484 << mpiErrorCodeToString (err) <<
"\".";
1485 if (someNullRequests) {
1486 os <<
" On input to MPI_Waitall, there was at least one MPI_Request "
1487 "that was MPI_REQUEST_NULL. MPI_Waitall should not normally fail in "
1488 "that case, but we thought we should let you know regardless.";
1496 std::fill (requests.begin(), requests.end(), null);
1502 template<
typename Ordinal>
1504 waitAllImpl (
const ArrayView<RCP<CommRequest<Ordinal> > >& requests)
1506 typedef typename ArrayView<RCP<CommRequest<Ordinal> > >::size_type size_type;
1507 const size_type count = requests.size ();
1520 bool someNullRequests =
false;
1521 Array<MPI_Request> rawMpiRequests (count, MPI_REQUEST_NULL);
1522 for (
int i = 0; i < count; ++i) {
1523 RCP<CommRequest<Ordinal> > request = requests[i];
1524 if (! request.is_null ()) {
1525 RCP<MpiCommRequestBase<Ordinal> > mpiRequest =
1526 rcp_dynamic_cast<MpiCommRequestBase<Ordinal> > (request);
1534 rawMpiRequests[i] = mpiRequest->releaseRawMpiRequest ();
1537 rawMpiRequests[i] = MPI_REQUEST_NULL;
1538 someNullRequests =
true;
1548 const int err = MPI_Waitall (count, rawMpiRequests.getRawPtr(),
1549 MPI_STATUSES_IGNORE);
1559 if (err != MPI_SUCCESS) {
1560 std::ostringstream os;
1561 os <<
"Teuchos::MpiComm::waitAll: MPI_Waitall() failed with error \""
1562 << mpiErrorCodeToString (err) <<
"\".";
1563 if (someNullRequests) {
1564 os << std::endl <<
"On input to MPI_Waitall, there was at least one "
1565 "MPI_Request that was MPI_REQUEST_NULL. MPI_Waitall should not "
1566 "normally fail in that case, but we thought we should let you know "
1577 std::fill (requests.begin(), requests.end(), null);
1584 template<
typename Ordinal>
1587 waitAll (
const ArrayView<RCP<CommRequest<Ordinal> > >& requests)
const
1589 TEUCHOS_COMM_TIME_MONITOR(
"Teuchos::MpiComm::waitAll(requests)" );
1592 waitAllImpl<Ordinal> (requests);
1596 template<
typename Ordinal>
1599 waitAll (
const ArrayView<RCP<CommRequest<Ordinal> > >& requests,
1600 const ArrayView<RCP<CommStatus<Ordinal> > >& statuses)
const
1602 TEUCHOS_COMM_TIME_MONITOR(
"Teuchos::MpiComm::waitAll(requests, statuses)" );
1604 typedef typename ArrayView<RCP<CommRequest<Ordinal> > >::size_type size_type;
1605 const size_type count = requests.size();
1608 std::invalid_argument,
"Teuchos::MpiComm::waitAll: requests.size() = "
1609 << count <<
" != statuses.size() = " << statuses.size() <<
".");
1611 Array<MPI_Status> rawMpiStatuses (count);
1612 waitAllImpl<Ordinal> (requests, rawMpiStatuses());
1615 for (size_type i = 0; i < count; ++i) {
1616 statuses[i] = mpiCommStatus<Ordinal> (rawMpiStatuses[i]);
1621 template<
typename Ordinal>
1622 RCP<CommStatus<Ordinal> >
1623 MpiComm<Ordinal>::wait (
const Ptr<RCP<CommRequest<Ordinal> > >& request)
const
1625 TEUCHOS_COMM_TIME_MONITOR(
"Teuchos::MpiComm::wait(...)" );
1631 RCP<CommStatus<Ordinal> > status = (*request)->wait ();
1639 template<
typename Ordinal>
1640 RCP< Comm<Ordinal> >
1641 MpiComm<Ordinal>::duplicate()
const
1643 MPI_Comm origRawComm = *rawMpiComm_;
1644 MPI_Comm newRawComm = MPI_COMM_NULL;
1645 const int err = MPI_Comm_dup (origRawComm, &newRawComm);
1647 "::MpiComm::duplicate: MPI_Comm_dup failed with the following error: "
1648 << mpiErrorCodeToString (err));
1653 RCP<OpaqueWrapper<MPI_Comm> > wrapped =
1654 opaqueWrapper<MPI_Comm> (newRawComm, details::safeCommFree);
1658 RCP<MpiComm<Ordinal> > newComm =
1659 rcp (
new MpiComm<Ordinal> (wrapped.getConst (), minTag_));
1660 return rcp_implicit_cast<Comm<Ordinal> > (newComm);
1664 template<
typename Ordinal>
1665 RCP< Comm<Ordinal> >
1666 MpiComm<Ordinal>::split(
const int color,
const int key)
const
1669 const int splitReturn =
1670 MPI_Comm_split (*rawMpiComm_,
1671 color < 0 ? MPI_UNDEFINED : color,
1675 splitReturn != MPI_SUCCESS,
1677 "Teuchos::MpiComm::split: Failed to create communicator with color "
1678 << color <<
"and key " << key <<
". MPI_Comm_split failed with error \""
1679 << mpiErrorCodeToString (splitReturn) <<
"\".");
1680 if (newComm == MPI_COMM_NULL) {
1681 return RCP< Comm<Ordinal> >();
1683 RCP<const OpaqueWrapper<MPI_Comm> > wrapped =
1684 opaqueWrapper<MPI_Comm> (newComm, details::safeCommFree);
1689 return rcp (
new MpiComm<Ordinal> (wrapped, minTag_));
1694 template<
typename Ordinal>
1695 RCP< Comm<Ordinal> >
1696 MpiComm<Ordinal>::createSubcommunicator(
const ArrayView<const int> &ranks)
const
1698 int err = MPI_SUCCESS;
1701 MPI_Group thisGroup;
1702 err = MPI_Comm_group (*rawMpiComm_, &thisGroup);
1704 "Failed to obtain the current communicator's group. "
1705 "MPI_Comm_group failed with error \""
1706 << mpiErrorCodeToString (err) <<
"\".");
1714 err = MPI_Group_incl (thisGroup, ranks.size(),
1715 const_cast<int*
> (ranks.getRawPtr ()), &newGroup);
1717 "Failed to create subgroup. MPI_Group_incl failed with error \""
1718 << mpiErrorCodeToString (err) <<
"\".");
1723 err = MPI_Comm_create (*rawMpiComm_, newGroup, &newComm);
1725 "Failed to create subcommunicator. MPI_Comm_create failed with error \""
1726 << mpiErrorCodeToString (err) <<
"\".");
1733 (void) MPI_Group_free (&newGroup);
1734 (void) MPI_Group_free (&thisGroup);
1739 err = MPI_Group_free (&newGroup);
1741 "Failed to free subgroup. MPI_Group_free failed with error \""
1742 << mpiErrorCodeToString (err) <<
"\".");
1743 err = MPI_Group_free (&thisGroup);
1745 "Failed to free subgroup. MPI_Group_free failed with error \""
1746 << mpiErrorCodeToString (err) <<
"\".");
1748 if (newComm == MPI_COMM_NULL) {
1749 return RCP<Comm<Ordinal> > ();
1751 using Teuchos::details::safeCommFree;
1752 typedef OpaqueWrapper<MPI_Comm> ow_type;
1753 RCP<const ow_type> wrapper =
1754 rcp_implicit_cast<
const ow_type> (opaqueWrapper (newComm, safeCommFree));
1759 return rcp (
new MpiComm<Ordinal> (wrapper, minTag_));
1767 template<
typename Ordinal>
1768 std::string MpiComm<Ordinal>::description()
const
1770 std::ostringstream oss;
1776 <<
",rawMpiComm="<<
static_cast<MPI_Comm
>(*rawMpiComm_)
1782 #ifdef TEUCHOS_MPI_COMM_DUMP
1783 template<
typename Ordinal>
1784 bool MpiComm<Ordinal>::show_dump =
false;
1791 template<
typename Ordinal>
1792 void MpiComm<Ordinal>::assertRank(
const int rank,
const std::string &rankName)
const
1795 ! ( 0 <= rank && rank < size_ ), std::logic_error
1796 ,
"Error, "<<rankName<<
" = " << rank <<
" is not < 0 or is not"
1797 " in the range [0,"<<size_-1<<
"]!"
1805 template<
typename Ordinal>
1807 Teuchos::createMpiComm(
1808 const RCP<
const OpaqueWrapper<MPI_Comm> > &rawMpiComm
1811 if( rawMpiComm.get()!=NULL && *rawMpiComm != MPI_COMM_NULL )
1812 return rcp(
new MpiComm<Ordinal>(rawMpiComm));
1813 return Teuchos::null;
1817 template<
typename Ordinal>
1819 Teuchos::createMpiComm(
1820 const RCP<
const OpaqueWrapper<MPI_Comm> > &rawMpiComm,
1821 const int defaultTag
1824 if( rawMpiComm.get()!=NULL && *rawMpiComm != MPI_COMM_NULL )
1825 return rcp(
new MpiComm<Ordinal>(rawMpiComm, defaultTag));
1826 return Teuchos::null;
1830 template<
typename Ordinal>
1832 Teuchos::getRawMpiComm(
const Comm<Ordinal> &comm)
1835 dyn_cast<
const MpiComm<Ordinal> >(comm).getRawMpiComm()
1840 #endif // HAVE_TEUCHOS_MPI
1841 #endif // TEUCHOS_MPI_COMM_HPP
RCP< T > rcp(const boost::shared_ptr< T > &sptr)
Conversion function that takes in a boost::shared_ptr object and spits out a Teuchos::RCP object...
bool is_null(const std::shared_ptr< T > &p)
Returns true if p.get()==NULL.
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
Macro for throwing an exception with breakpointing to ease debugging.
T_To & dyn_cast(T_From &from)
Dynamic casting utility function meant to replace dynamic_cast<T&> by throwing a better documented er...
Teuchos header file which uses auto-configuration information to include necessary C++ headers...
Tabbing class for helping to create formated, indented output for a basic_FancyOStream object...
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
Deprecated.
static RCP< FancyOStream > getDefaultOStream()
Get the default output stream object.
void send(const Packet sendBuffer[], const Ordinal count, const int destRank, const int tag, const Comm< Ordinal > &comm)
Variant of send() that takes a tag (and restores the correct order of arguments). ...
RCP< CommRequest< Ordinal > > ireceive(const ArrayRCP< Packet > &recvBuffer, const int sourceRank, const int tag, const Comm< Ordinal > &comm)
Variant of ireceive that takes a tag argument (and restores the correct order of arguments).
Defines basic traits for the ordinal field type.
TypeTo as(const TypeFrom &t)
Convert from one value type to another.
void ssend(const Packet sendBuffer[], const Ordinal count, const int destRank, const int tag, const Comm< Ordinal > &comm)
Variant of ssend() that takes a tag (and restores the correct order of arguments).
Smart reference counting pointer class for automatic garbage collection.
Implementation detail of Teuchos' MPI wrapper.
#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 ...
Defines basic traits returning the name of a type in a portable and readable way. ...
Definition of Teuchos::as, for conversions between types.
void readySend(const Packet sendBuffer[], const Ordinal count, const int destRank, const int tag, const Comm< Ordinal > &comm)
Variant of readySend() that accepts a message tag.
std::string typeName(const T &t)
Template function for returning the concrete type name of a passed-in object.