42 #ifndef TEUCHOS_MPI_COMM_HPP 43 #define TEUCHOS_MPI_COMM_HPP 53 #ifdef HAVE_TEUCHOS_MPI 55 #include "Teuchos_Comm.hpp" 56 #include "Teuchos_CommUtilities.hpp" 58 #include "Teuchos_OpaqueWrapper.hpp" 60 #include "Teuchos_SerializationTraitsHelpers.hpp" 61 #include "Teuchos_Workspace.hpp" 64 #include "Teuchos_Assert.hpp" 71 #ifdef TEUCHOS_MPI_COMM_DUMP 72 # include "Teuchos_VerboseObject.hpp" 79 mpiErrorCodeToString (
const int err);
95 void safeCommFree (MPI_Comm* comm);
101 int setCommErrhandler (MPI_Comm comm, MPI_Errhandler handler);
105 #ifdef TEUCHOS_MPI_COMM_DUMP 106 template<
typename Ordinal,
typename T>
108 const std::string &funcName,
const std::string &buffName
109 ,
const Ordinal bytes,
const T buff[]
116 <<
"\n" << funcName <<
"::" << buffName <<
":\n";
118 for( Ordinal i = 0; i < bytes; ++i ) {
119 *out << buffName <<
"[" << i <<
"] = '" << buff[i] <<
"'\n";
123 #endif // TEUCHOS_MPI_COMM_DUMP 136 template<
class OrdinalType>
137 class MpiCommStatus :
public CommStatus<OrdinalType> {
139 MpiCommStatus (MPI_Status status) : status_ (status) {}
142 virtual ~MpiCommStatus() {}
145 OrdinalType getSourceRank () {
return status_.MPI_SOURCE; }
148 OrdinalType getTag () {
return status_.MPI_TAG; }
151 OrdinalType getError () {
return status_.MPI_ERROR; }
164 template<
class OrdinalType>
165 inline RCP<MpiCommStatus<OrdinalType> >
166 mpiCommStatus (MPI_Status rawMpiStatus)
168 return rcp (
new MpiCommStatus<OrdinalType> (rawMpiStatus));
186 template<
class OrdinalType>
187 class MpiCommRequestBase :
public CommRequest<OrdinalType> {
190 MpiCommRequestBase () :
191 rawMpiRequest_ (MPI_REQUEST_NULL)
195 MpiCommRequestBase (MPI_Request rawMpiRequest) :
196 rawMpiRequest_ (rawMpiRequest)
206 MPI_Request releaseRawMpiRequest()
208 MPI_Request tmp_rawMpiRequest = rawMpiRequest_;
209 rawMpiRequest_ = MPI_REQUEST_NULL;
210 return tmp_rawMpiRequest;
214 bool isNull()
const {
215 return rawMpiRequest_ == MPI_REQUEST_NULL;
219 MPI_Status rawMpiStatus;
222 MPI_Test(&rawMpiRequest_, &flag, &rawMpiStatus);
232 RCP<CommStatus<OrdinalType> > wait () {
233 MPI_Status rawMpiStatus;
236 const int err = MPI_Wait (&rawMpiRequest_, &rawMpiStatus);
238 err != MPI_SUCCESS, std::runtime_error,
239 "Teuchos: MPI_Wait() failed with error \"" 240 << mpiErrorCodeToString (err));
242 return mpiCommStatus<OrdinalType> (rawMpiStatus);
249 RCP<CommStatus<OrdinalType> > cancel () {
250 if (rawMpiRequest_ == MPI_REQUEST_NULL) {
254 int err = MPI_Cancel (&rawMpiRequest_);
256 err != MPI_SUCCESS, std::runtime_error,
257 "Teuchos: MPI_Cancel failed with the following error: " 258 << mpiErrorCodeToString (err));
265 err = MPI_Wait (&rawMpiRequest_, &status);
267 "Teuchos::MpiCommStatus::cancel: MPI_Wait failed with the following " 268 "error: " << mpiErrorCodeToString (err));
269 return mpiCommStatus<OrdinalType> (status);
274 virtual ~MpiCommRequestBase () {
275 if (rawMpiRequest_ != MPI_REQUEST_NULL) {
278 const int err = MPI_Cancel (&rawMpiRequest_);
279 if (err == MPI_SUCCESS) {
296 (void) MPI_Wait (&rawMpiRequest_, MPI_STATUS_IGNORE);
303 MPI_Request rawMpiRequest_;
321 template<
class OrdinalType>
322 class MpiCommRequest :
public MpiCommRequestBase<OrdinalType> {
326 MpiCommRequestBase<OrdinalType> (MPI_REQUEST_NULL),
331 MpiCommRequest (MPI_Request rawMpiRequest,
333 MpiCommRequestBase<OrdinalType> (rawMpiRequest),
334 numBytes_ (numBytesInMessage)
347 virtual ~MpiCommRequest () {}
362 template<
class OrdinalType>
363 inline RCP<MpiCommRequest<OrdinalType> >
364 mpiCommRequest (MPI_Request rawMpiRequest,
367 return rcp (
new MpiCommRequest<OrdinalType> (rawMpiRequest, numBytes));
385 template<
typename Ordinal>
386 class MpiComm :
public Comm<Ordinal> {
411 explicit MpiComm (MPI_Comm rawMpiComm);
427 MpiComm (
const RCP<
const OpaqueWrapper<MPI_Comm> >& rawMpiComm);
446 MpiComm (
const RCP<
const OpaqueWrapper<MPI_Comm> >& rawMpiComm,
447 const int defaultTag);
465 MpiComm (
const MpiComm<Ordinal>& other);
468 RCP<const OpaqueWrapper<MPI_Comm> > getRawMpiComm ()
const {
536 void setErrorHandler (
const RCP<
const OpaqueWrapper<MPI_Errhandler> >& errHandler);
543 virtual int getRank()
const;
546 virtual int getSize()
const;
549 virtual void barrier()
const;
552 virtual void broadcast(
553 const int rootRank,
const Ordinal bytes,
char buffer[]
558 gather (
const Ordinal sendBytes,
const char sendBuffer[],
559 const Ordinal recvBytes,
char recvBuffer[],
560 const int root)
const;
562 virtual void gatherAll(
563 const Ordinal sendBytes,
const char sendBuffer[]
564 ,
const Ordinal recvBytes,
char recvBuffer[]
567 virtual void reduceAll(
568 const ValueTypeReductionOp<Ordinal,char> &reductOp
569 ,
const Ordinal bytes,
const char sendBuffer[],
char globalReducts[]
573 const ValueTypeReductionOp<Ordinal,char> &reductOp
574 ,
const Ordinal bytes,
const char sendBuffer[],
char scanReducts[]
578 const Ordinal bytes,
const char sendBuffer[],
const int destRank
582 send (
const Ordinal bytes,
583 const char sendBuffer[],
585 const int tag)
const;
588 const Ordinal bytes,
const char sendBuffer[],
const int destRank
592 ssend (
const Ordinal bytes,
593 const char sendBuffer[],
595 const int tag)
const;
598 const int sourceRank,
const Ordinal bytes,
char recvBuffer[]
602 const ArrayView<const char> &sendBuffer,
608 const char sendBuffer[],
610 const int tag)
const;
612 virtual RCP<CommRequest<Ordinal> > isend(
613 const ArrayView<const char> &sendBuffer,
617 virtual RCP<CommRequest<Ordinal> >
618 isend (
const ArrayView<const char> &sendBuffer,
620 const int tag)
const;
622 virtual RCP<CommRequest<Ordinal> >
ireceive(
623 const ArrayView<char> &Buffer,
627 virtual RCP<CommRequest<Ordinal> >
628 ireceive (
const ArrayView<char> &Buffer,
629 const int sourceRank,
630 const int tag)
const;
632 virtual void waitAll(
633 const ArrayView<RCP<CommRequest<Ordinal> > > &requests
637 waitAll (
const ArrayView<RCP<CommRequest<Ordinal> > >& requests,
638 const ArrayView<RCP<CommStatus<Ordinal> > >& statuses)
const;
640 virtual RCP<CommStatus<Ordinal> >
641 wait (
const Ptr<RCP<CommRequest<Ordinal> > >& request)
const;
643 virtual RCP< Comm<Ordinal> > duplicate()
const;
645 virtual RCP< Comm<Ordinal> > split(
const int color,
const int key)
const;
647 virtual RCP< Comm<Ordinal> > createSubcommunicator(
648 const ArrayView<const int>& ranks)
const;
655 std::string description()
const;
661 static int const minTag_ = 26000;
662 static int const maxTag_ = 26099;
669 int getTag ()
const {
return tag_; }
676 void setupMembersFromComm();
677 static int tagCounter_;
686 RCP<const OpaqueWrapper<MPI_Comm> > rawMpiComm_;
704 RCP<const OpaqueWrapper<MPI_Errhandler> > customErrorHandler_;
706 void assertRank(
const int rank,
const std::string &rankName)
const;
711 #ifdef TEUCHOS_MPI_COMM_DUMP 713 static bool show_dump;
714 #endif // TEUCHOS_MPI_COMM_DUMP 732 template<
typename Ordinal>
733 RCP<MpiComm<Ordinal> >
735 const RCP<
const OpaqueWrapper<MPI_Comm> > &rawMpiComm
752 template<
typename Ordinal>
753 RCP<MpiComm<Ordinal> >
755 const RCP<
const OpaqueWrapper<MPI_Comm> > &rawMpiComm,
787 template<
typename Ordinal>
789 getRawMpiComm(
const Comm<Ordinal> &comm);
799 template<
typename Ordinal>
800 int MpiComm<Ordinal>::tagCounter_ = MpiComm<Ordinal>::minTag_;
806 template<
typename Ordinal>
808 MpiComm (
const RCP<
const OpaqueWrapper<MPI_Comm> >& rawMpiComm)
811 rawMpiComm.get () == NULL, std::invalid_argument,
812 "Teuchos::MpiComm constructor: The input RCP is null.");
814 *rawMpiComm == MPI_COMM_NULL, std::invalid_argument,
815 "Teuchos::MpiComm constructor: The given MPI_Comm is MPI_COMM_NULL.");
817 rawMpiComm_ = rawMpiComm;
831 setupMembersFromComm ();
835 template<
typename Ordinal>
837 MpiComm (
const RCP<
const OpaqueWrapper<MPI_Comm> >& rawMpiComm,
838 const int defaultTag)
841 rawMpiComm.get () == NULL, std::invalid_argument,
842 "Teuchos::MpiComm constructor: The input RCP is null.");
844 *rawMpiComm == MPI_COMM_NULL, std::invalid_argument,
845 "Teuchos::MpiComm constructor: The given MPI_Comm is MPI_COMM_NULL.");
847 rawMpiComm_ = rawMpiComm;
849 int err = MPI_Comm_size (*rawMpiComm_, &size_);
851 "Teuchos::MpiComm constructor: MPI_Comm_size failed with " 852 "error \"" << mpiErrorCodeToString (err) <<
"\".");
854 err = MPI_Comm_rank (*rawMpiComm_, &rank_);
856 "Teuchos::MpiComm constructor: MPI_Comm_rank failed with " 857 "error \"" << mpiErrorCodeToString (err) <<
"\".");
862 template<
typename Ordinal>
863 MpiComm<Ordinal>::MpiComm (MPI_Comm rawMpiComm)
866 std::invalid_argument,
"Teuchos::MpiComm constructor: The given MPI_Comm " 867 "is MPI_COMM_NULL.");
871 rawMpiComm_ = opaqueWrapper<MPI_Comm> (rawMpiComm);
885 setupMembersFromComm ();
889 template<
typename Ordinal>
890 MpiComm<Ordinal>::MpiComm (
const MpiComm<Ordinal>& other) :
891 rawMpiComm_ (opaqueWrapper<MPI_Comm> (MPI_COMM_NULL))
894 RCP<const OpaqueWrapper<MPI_Comm> > origCommPtr = other.getRawMpiComm ();
896 "Teuchos::MpiComm copy constructor: " 897 "The input's getRawMpiComm() method returns null.");
898 MPI_Comm origComm = *origCommPtr;
900 "Teuchos::MpiComm copy constructor: " 901 "The input's raw MPI_Comm is MPI_COMM_NULL.");
909 rawMpiComm_ = origCommPtr;
913 const int err = MPI_Comm_dup (origComm, &newComm);
915 "Teuchos::MpiComm copy constructor: MPI_Comm_dup failed with " 916 "the following error: " << mpiErrorCodeToString (err));
918 rawMpiComm_ = opaqueWrapper (newComm, details::safeCommFree);
921 setupMembersFromComm ();
925 template<
typename Ordinal>
926 void MpiComm<Ordinal>::setupMembersFromComm ()
928 int err = MPI_Comm_size (*rawMpiComm_, &size_);
930 "Teuchos::MpiComm constructor: MPI_Comm_size failed with " 931 "error \"" << mpiErrorCodeToString (err) <<
"\".");
932 err = MPI_Comm_rank (*rawMpiComm_, &rank_);
934 "Teuchos::MpiComm constructor: MPI_Comm_rank failed with " 935 "error \"" << mpiErrorCodeToString (err) <<
"\".");
938 if (tagCounter_ > maxTag_) {
939 tagCounter_ = minTag_;
941 tag_ = tagCounter_++;
951 MPI_Bcast (&tag_, 1, MPI_INT, 0, *rawMpiComm_);
955 template<
typename Ordinal>
958 setErrorHandler (
const RCP<
const OpaqueWrapper<MPI_Errhandler> >& errHandler)
961 const int err = details::setCommErrhandler (*getRawMpiComm (), *errHandler);
963 "Teuchos::MpiComm: Setting the MPI_Comm's error handler failed with " 964 "error \"" << mpiErrorCodeToString (err) <<
"\".");
968 customErrorHandler_ = errHandler;
975 template<
typename Ordinal>
976 int MpiComm<Ordinal>::getRank()
const 982 template<
typename Ordinal>
983 int MpiComm<Ordinal>::getSize()
const 989 template<
typename Ordinal>
990 void MpiComm<Ordinal>::barrier()
const 992 TEUCHOS_COMM_TIME_MONITOR(
995 const int err = MPI_Barrier (*rawMpiComm_);
997 "Teuchos::MpiComm::barrier: MPI_Barrier failed with error \"" 998 << mpiErrorCodeToString (err) <<
"\".");
1002 template<
typename Ordinal>
1003 void MpiComm<Ordinal>::broadcast(
1004 const int rootRank,
const Ordinal bytes,
char buffer[]
1007 TEUCHOS_COMM_TIME_MONITOR(
1010 const int err = MPI_Bcast (buffer, bytes, MPI_CHAR, rootRank, *rawMpiComm_);
1012 "Teuchos::MpiComm::broadcast: MPI_Bcast failed with error \"" 1013 << mpiErrorCodeToString (err) <<
"\".");
1017 template<
typename Ordinal>
1018 void MpiComm<Ordinal>::gatherAll(
1019 const Ordinal sendBytes,
const char sendBuffer[],
1020 const Ordinal recvBytes,
char recvBuffer[]
1023 TEUCHOS_COMM_TIME_MONITOR(
1028 MPI_Allgather (const_cast<char *>(sendBuffer), sendBytes, MPI_CHAR,
1029 recvBuffer, sendBytes, MPI_CHAR, *rawMpiComm_);
1034 "Teuchos::MpiComm::gatherAll: MPI_Allgather failed with error \"" 1035 << mpiErrorCodeToString (err) <<
"\".");
1039 template<
typename Ordinal>
1041 MpiComm<Ordinal>::gather (
const Ordinal sendBytes,
1042 const char sendBuffer[],
1043 const Ordinal recvBytes,
1045 const int root)
const 1049 TEUCHOS_COMM_TIME_MONITOR(
1053 MPI_Gather (const_cast<char *> (sendBuffer), sendBytes, MPI_CHAR,
1054 recvBuffer, sendBytes, MPI_CHAR, root, *rawMpiComm_);
1056 "Teuchos::MpiComm::gather: MPI_Gather failed with error \"" 1057 << mpiErrorCodeToString (err) <<
"\".");
1061 template<
typename Ordinal>
1064 reduceAll (
const ValueTypeReductionOp<Ordinal,char> &reductOp,
1065 const Ordinal bytes,
1066 const char sendBuffer[],
1067 char globalReducts[])
const 1069 TEUCHOS_COMM_TIME_MONITOR(
"Teuchos::MpiComm::reduceAll(...)" );
1070 int err = MPI_SUCCESS;
1072 Details::MpiReductionOp<Ordinal> opWrap (reductOp);
1073 MPI_Op op = Details::setMpiReductionOp (opWrap);
1082 MPI_Datatype char_block;
1083 err = MPI_Type_contiguous (bytes, MPI_CHAR, &char_block);
1085 err != MPI_SUCCESS, std::runtime_error,
"Teuchos::reduceAll: " 1086 "MPI_Type_contiguous failed with error \"" << mpiErrorCodeToString (err)
1088 err = MPI_Type_commit (&char_block);
1090 err != MPI_SUCCESS, std::runtime_error,
"Teuchos::reduceAll: " 1091 "MPI_Type_commit failed with error \"" << mpiErrorCodeToString (err)
1094 if (sendBuffer == globalReducts) {
1098 err = MPI_Allreduce (MPI_IN_PLACE, globalReducts, 1,
1099 char_block, op, *rawMpiComm_);
1102 err = MPI_Allreduce (const_cast<char*> (sendBuffer), globalReducts, 1,
1103 char_block, op, *rawMpiComm_);
1105 if (err != MPI_SUCCESS) {
1110 (void) MPI_Type_free (&char_block);
1112 true, std::runtime_error,
"Teuchos::reduceAll (MPI, custom op): " 1113 "MPI_Allreduce failed with error \"" << mpiErrorCodeToString (err)
1116 err = MPI_Type_free (&char_block);
1118 err != MPI_SUCCESS, std::runtime_error,
"Teuchos::reduceAll: " 1119 "MPI_Type_free failed with error \"" << mpiErrorCodeToString (err)
1124 template<
typename Ordinal>
1125 void MpiComm<Ordinal>::scan(
1126 const ValueTypeReductionOp<Ordinal,char> &reductOp
1127 ,
const Ordinal bytes,
const char sendBuffer[],
char scanReducts[]
1130 TEUCHOS_COMM_TIME_MONITOR(
"Teuchos::MpiComm::scan(...)" );
1132 Details::MpiReductionOp<Ordinal> opWrap (reductOp);
1133 MPI_Op op = Details::setMpiReductionOp (opWrap);
1135 MPI_Scan (const_cast<char*> (sendBuffer), scanReducts, bytes, MPI_CHAR,
1138 "Teuchos::MpiComm::scan: MPI_Scan() failed with error \"" 1139 << mpiErrorCodeToString (err) <<
"\".");
1143 template<
typename Ordinal>
1145 MpiComm<Ordinal>::send (
const Ordinal bytes,
1146 const char sendBuffer[],
1147 const int destRank)
const 1149 TEUCHOS_COMM_TIME_MONITOR(
"Teuchos::MpiComm::send(...)" );
1151 #ifdef TEUCHOS_MPI_COMM_DUMP 1153 dumpBuffer<Ordinal,char>(
1154 "Teuchos::MpiComm<Ordinal>::send(...)" 1155 ,
"sendBuffer", bytes, sendBuffer
1158 #endif // TEUCHOS_MPI_COMM_DUMP 1160 const int err = MPI_Send (const_cast<char*>(sendBuffer), bytes, MPI_CHAR,
1161 destRank, tag_, *rawMpiComm_);
1163 "Teuchos::MpiComm::send: MPI_Send() failed with error \"" 1164 << mpiErrorCodeToString (err) <<
"\".");
1168 template<
typename Ordinal>
1170 MpiComm<Ordinal>::send (
const Ordinal bytes,
1171 const char sendBuffer[],
1173 const int tag)
const 1175 TEUCHOS_COMM_TIME_MONITOR(
"Teuchos::MpiComm::send(...)" );
1176 const int err = MPI_Send (const_cast<char*> (sendBuffer), bytes, MPI_CHAR,
1177 destRank, tag, *rawMpiComm_);
1179 "Teuchos::MpiComm::send: MPI_Send() failed with error \"" 1180 << mpiErrorCodeToString (err) <<
"\".");
1184 template<
typename Ordinal>
1186 MpiComm<Ordinal>::ssend (
const Ordinal bytes,
1187 const char sendBuffer[],
1188 const int destRank)
const 1190 TEUCHOS_COMM_TIME_MONITOR(
"Teuchos::MpiComm::ssend(...)" );
1192 #ifdef TEUCHOS_MPI_COMM_DUMP 1194 dumpBuffer<Ordinal,char>(
1195 "Teuchos::MpiComm<Ordinal>::send(...)" 1196 ,
"sendBuffer", bytes, sendBuffer
1199 #endif // TEUCHOS_MPI_COMM_DUMP 1201 const int err = MPI_Ssend (const_cast<char*>(sendBuffer), bytes, MPI_CHAR,
1202 destRank, tag_, *rawMpiComm_);
1204 "Teuchos::MpiComm::send: MPI_Ssend() failed with error \"" 1205 << mpiErrorCodeToString (err) <<
"\".");
1208 template<
typename Ordinal>
1210 MpiComm<Ordinal>::ssend (
const Ordinal bytes,
1211 const char sendBuffer[],
1213 const int tag)
const 1215 TEUCHOS_COMM_TIME_MONITOR(
"Teuchos::MpiComm::ssend(...)" );
1217 MPI_Ssend (const_cast<char*>(sendBuffer), bytes, MPI_CHAR,
1218 destRank, tag, *rawMpiComm_);
1220 "Teuchos::MpiComm::send: MPI_Ssend() failed with error \"" 1221 << mpiErrorCodeToString (err) <<
"\".");
1224 template<
typename Ordinal>
1225 void MpiComm<Ordinal>::readySend(
1226 const ArrayView<const char> &sendBuffer,
1230 TEUCHOS_COMM_TIME_MONITOR(
"Teuchos::MpiComm::readySend" );
1232 #ifdef TEUCHOS_MPI_COMM_DUMP 1234 dumpBuffer<Ordinal,char>(
1235 "Teuchos::MpiComm<Ordinal>::readySend(...)" 1236 ,
"sendBuffer", bytes, sendBuffer
1239 #endif // TEUCHOS_MPI_COMM_DUMP 1242 MPI_Rsend (const_cast<char*>(sendBuffer.getRawPtr()), static_cast<int>(sendBuffer.size()),
1243 MPI_CHAR, destRank, tag_, *rawMpiComm_);
1245 "Teuchos::MpiComm::readySend: MPI_Rsend() failed with error \"" 1246 << mpiErrorCodeToString (err) <<
"\".");
1250 template<
typename Ordinal>
1251 void MpiComm<Ordinal>::
1252 readySend (
const Ordinal bytes,
1253 const char sendBuffer[],
1255 const int tag)
const 1257 TEUCHOS_COMM_TIME_MONITOR(
"Teuchos::MpiComm::readySend" );
1259 MPI_Rsend (const_cast<char*> (sendBuffer), bytes,
1260 MPI_CHAR, destRank, tag, *rawMpiComm_);
1262 "Teuchos::MpiComm::readySend: MPI_Rsend() failed with error \"" 1263 << mpiErrorCodeToString (err) <<
"\".");
1267 template<
typename Ordinal>
1269 MpiComm<Ordinal>::receive (
const int sourceRank,
1270 const Ordinal bytes,
1271 char recvBuffer[])
const 1273 TEUCHOS_COMM_TIME_MONITOR(
"Teuchos::MpiComm::receive(...)" );
1278 const int theSrcRank = (sourceRank < 0) ? MPI_ANY_SOURCE : sourceRank;
1281 const int err = MPI_Recv (recvBuffer, bytes, MPI_CHAR, theSrcRank, tag_,
1282 *rawMpiComm_, &status);
1284 "Teuchos::MpiComm::receive: MPI_Recv() failed with error \"" 1285 << mpiErrorCodeToString (err) <<
"\".");
1287 #ifdef TEUCHOS_MPI_COMM_DUMP 1289 dumpBuffer<Ordinal,char> (
"Teuchos::MpiComm<Ordinal>::receive(...)",
1290 "recvBuffer", bytes, recvBuffer);
1292 #endif // TEUCHOS_MPI_COMM_DUMP 1295 return status.MPI_SOURCE;
1299 template<
typename Ordinal>
1300 RCP<CommRequest<Ordinal> >
1301 MpiComm<Ordinal>::isend (
const ArrayView<const char> &sendBuffer,
1302 const int destRank)
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> >
1323 isend (
const ArrayView<const char> &sendBuffer,
1325 const int tag)
const 1328 TEUCHOS_COMM_TIME_MONITOR(
"Teuchos::MpiComm::isend(...)" );
1330 MPI_Request rawMpiRequest = MPI_REQUEST_NULL;
1332 MPI_Isend (const_cast<char*> (sendBuffer.getRawPtr ()),
1333 as<Ordinal> (sendBuffer.size ()), MPI_CHAR,
1334 destRank, tag, *rawMpiComm_, &rawMpiRequest);
1336 "Teuchos::MpiComm::isend: MPI_Isend() failed with error \"" 1337 << mpiErrorCodeToString (err) <<
"\".");
1339 return mpiCommRequest<Ordinal> (rawMpiRequest, sendBuffer.size ());
1343 template<
typename Ordinal>
1344 RCP<CommRequest<Ordinal> >
1345 MpiComm<Ordinal>::ireceive (
const ArrayView<char> &recvBuffer,
1346 const int sourceRank)
const 1348 TEUCHOS_COMM_TIME_MONITOR(
"Teuchos::MpiComm::ireceive(...)" );
1353 const int theSrcRank = (sourceRank < 0) ? MPI_ANY_SOURCE : sourceRank;
1355 MPI_Request rawMpiRequest = MPI_REQUEST_NULL;
1357 MPI_Irecv (const_cast<char*>(recvBuffer.getRawPtr()), recvBuffer.size(),
1358 MPI_CHAR, theSrcRank, tag_, *rawMpiComm_, &rawMpiRequest);
1360 "Teuchos::MpiComm::ireceive: MPI_Irecv() failed with error \"" 1361 << mpiErrorCodeToString (err) <<
"\".");
1363 return mpiCommRequest<Ordinal> (rawMpiRequest, recvBuffer.size());
1366 template<
typename Ordinal>
1367 RCP<CommRequest<Ordinal> >
1368 MpiComm<Ordinal>::ireceive (
const ArrayView<char> &recvBuffer,
1369 const int sourceRank,
1370 const int tag)
const 1372 TEUCHOS_COMM_TIME_MONITOR(
"Teuchos::MpiComm::ireceive(...)" );
1377 const int theSrcRank = (sourceRank < 0) ? MPI_ANY_SOURCE : sourceRank;
1379 MPI_Request rawMpiRequest = MPI_REQUEST_NULL;
1381 MPI_Irecv (const_cast<char*> (recvBuffer.getRawPtr ()), recvBuffer.size (),
1382 MPI_CHAR, theSrcRank, tag, *rawMpiComm_, &rawMpiRequest);
1384 "Teuchos::MpiComm::ireceive: MPI_Irecv() failed with error \"" 1385 << mpiErrorCodeToString (err) <<
"\".");
1387 return mpiCommRequest<Ordinal> (rawMpiRequest, recvBuffer.size ());
1392 template<
typename Ordinal>
1394 waitAllImpl (
const ArrayView<RCP<CommRequest<Ordinal> > >& requests,
1395 const ArrayView<MPI_Status>& rawMpiStatuses)
1397 typedef typename ArrayView<RCP<CommRequest<Ordinal> > >::size_type size_type;
1398 const size_type count = requests.size();
1402 std::logic_error,
"Teuchos::MpiComm's waitAllImpl: rawMpiStatus.size() = " 1403 << rawMpiStatuses.size() <<
" != requests.size() = " << requests.size()
1404 <<
". Please report this bug to the Tpetra developers.");
1417 bool someNullRequests =
false;
1418 Array<MPI_Request> rawMpiRequests (count, MPI_REQUEST_NULL);
1419 for (
int i = 0; i < count; ++i) {
1420 RCP<CommRequest<Ordinal> > request = requests[i];
1422 RCP<MpiCommRequestBase<Ordinal> > mpiRequest =
1423 rcp_dynamic_cast<MpiCommRequestBase<Ordinal> > (request);
1431 rawMpiRequests[i] = mpiRequest->releaseRawMpiRequest();
1434 rawMpiRequests[i] = MPI_REQUEST_NULL;
1435 someNullRequests =
true;
1448 const int err = MPI_Waitall (count, rawMpiRequests.getRawPtr(),
1449 rawMpiStatuses.getRawPtr());
1459 if (err != MPI_SUCCESS) {
1460 if (err == MPI_ERR_IN_STATUS) {
1468 Array<std::pair<size_type, int> > errorLocationsAndCodes;
1469 for (size_type k = 0; k < rawMpiStatuses.size(); ++k) {
1470 const int curErr = rawMpiStatuses[k].MPI_ERROR;
1471 if (curErr != MPI_SUCCESS) {
1472 errorLocationsAndCodes.push_back (std::make_pair (k, curErr));
1475 const size_type numErrs = errorLocationsAndCodes.size();
1480 std::ostringstream os;
1481 os <<
"Teuchos::MpiComm::waitAll: MPI_Waitall() failed with error \"" 1482 << mpiErrorCodeToString (err) <<
"\". Of the " << count
1483 <<
" total request" << (count != 1 ?
"s" :
"") <<
", " << numErrs
1484 <<
" failed. Here are the indices of the failed requests, and the " 1485 "error codes extracted from their returned MPI_Status objects:" 1487 for (size_type k = 0; k < numErrs; ++k) {
1488 const size_type errInd = errorLocationsAndCodes[k].first;
1489 os <<
"Request " << errInd <<
": MPI_ERROR = " 1490 << mpiErrorCodeToString (rawMpiStatuses[errInd].MPI_ERROR)
1493 if (someNullRequests) {
1494 os <<
" On input to MPI_Waitall, there was at least one MPI_" 1495 "Request that was MPI_REQUEST_NULL. MPI_Waitall should not " 1496 "normally fail in that case, but we thought we should let you know " 1505 std::ostringstream os;
1506 os <<
"Teuchos::MpiComm::waitAll: MPI_Waitall() failed with error \"" 1507 << mpiErrorCodeToString (err) <<
"\".";
1508 if (someNullRequests) {
1509 os <<
" On input to MPI_Waitall, there was at least one MPI_Request " 1510 "that was MPI_REQUEST_NULL. MPI_Waitall should not normally fail in " 1511 "that case, but we thought we should let you know regardless.";
1519 std::fill (requests.begin(), requests.end(), null);
1525 template<
typename Ordinal>
1527 waitAllImpl (
const ArrayView<RCP<CommRequest<Ordinal> > >& requests)
1529 typedef typename ArrayView<RCP<CommRequest<Ordinal> > >::size_type size_type;
1530 const size_type count = requests.size ();
1543 bool someNullRequests =
false;
1544 Array<MPI_Request> rawMpiRequests (count, MPI_REQUEST_NULL);
1545 for (
int i = 0; i < count; ++i) {
1546 RCP<CommRequest<Ordinal> > request = requests[i];
1547 if (! request.is_null ()) {
1548 RCP<MpiCommRequestBase<Ordinal> > mpiRequest =
1549 rcp_dynamic_cast<MpiCommRequestBase<Ordinal> > (request);
1557 rawMpiRequests[i] = mpiRequest->releaseRawMpiRequest ();
1560 rawMpiRequests[i] = MPI_REQUEST_NULL;
1561 someNullRequests =
true;
1571 const int err = MPI_Waitall (count, rawMpiRequests.getRawPtr(),
1572 MPI_STATUSES_IGNORE);
1582 if (err != MPI_SUCCESS) {
1583 std::ostringstream os;
1584 os <<
"Teuchos::MpiComm::waitAll: MPI_Waitall() failed with error \"" 1585 << mpiErrorCodeToString (err) <<
"\".";
1586 if (someNullRequests) {
1587 os << std::endl <<
"On input to MPI_Waitall, there was at least one " 1588 "MPI_Request that was MPI_REQUEST_NULL. MPI_Waitall should not " 1589 "normally fail in that case, but we thought we should let you know " 1600 std::fill (requests.begin(), requests.end(), null);
1607 template<
typename Ordinal>
1610 waitAll (
const ArrayView<RCP<CommRequest<Ordinal> > >& requests)
const 1612 TEUCHOS_COMM_TIME_MONITOR(
"Teuchos::MpiComm::waitAll(requests)" );
1615 waitAllImpl<Ordinal> (requests);
1619 template<
typename Ordinal>
1622 waitAll (
const ArrayView<RCP<CommRequest<Ordinal> > >& requests,
1623 const ArrayView<RCP<CommStatus<Ordinal> > >& statuses)
const 1625 TEUCHOS_COMM_TIME_MONITOR(
"Teuchos::MpiComm::waitAll(requests, statuses)" );
1627 typedef typename ArrayView<RCP<CommRequest<Ordinal> > >::size_type size_type;
1628 const size_type count = requests.size();
1631 std::invalid_argument,
"Teuchos::MpiComm::waitAll: requests.size() = " 1632 << count <<
" != statuses.size() = " << statuses.size() <<
".");
1634 Array<MPI_Status> rawMpiStatuses (count);
1635 waitAllImpl<Ordinal> (requests, rawMpiStatuses());
1638 for (size_type i = 0; i < count; ++i) {
1639 statuses[i] = mpiCommStatus<Ordinal> (rawMpiStatuses[i]);
1644 template<
typename Ordinal>
1645 RCP<CommStatus<Ordinal> >
1646 MpiComm<Ordinal>::wait (
const Ptr<RCP<CommRequest<Ordinal> > >& request)
const 1648 TEUCHOS_COMM_TIME_MONITOR(
"Teuchos::MpiComm::wait(...)" );
1654 RCP<CommStatus<Ordinal> > status = (*request)->wait ();
1662 template<
typename Ordinal>
1663 RCP< Comm<Ordinal> >
1664 MpiComm<Ordinal>::duplicate()
const 1666 MPI_Comm origRawComm = *rawMpiComm_;
1667 MPI_Comm newRawComm = MPI_COMM_NULL;
1668 const int err = MPI_Comm_dup (origRawComm, &newRawComm);
1670 "::MpiComm::duplicate: MPI_Comm_dup failed with the following error: " 1671 << mpiErrorCodeToString (err));
1676 RCP<OpaqueWrapper<MPI_Comm> > wrapped =
1677 opaqueWrapper<MPI_Comm> (newRawComm, details::safeCommFree);
1681 RCP<MpiComm<Ordinal> > newComm =
1682 rcp (
new MpiComm<Ordinal> (wrapped.getConst (), minTag_));
1683 return rcp_implicit_cast<Comm<Ordinal> > (newComm);
1687 template<
typename Ordinal>
1688 RCP< Comm<Ordinal> >
1689 MpiComm<Ordinal>::split(
const int color,
const int key)
const 1692 const int splitReturn =
1693 MPI_Comm_split (*rawMpiComm_,
1694 color < 0 ? MPI_UNDEFINED : color,
1698 splitReturn != MPI_SUCCESS,
1700 "Teuchos::MpiComm::split: Failed to create communicator with color " 1701 << color <<
"and key " << key <<
". MPI_Comm_split failed with error \"" 1702 << mpiErrorCodeToString (splitReturn) <<
"\".");
1703 if (newComm == MPI_COMM_NULL) {
1704 return RCP< Comm<Ordinal> >();
1706 RCP<const OpaqueWrapper<MPI_Comm> > wrapped =
1707 opaqueWrapper<MPI_Comm> (newComm, details::safeCommFree);
1712 return rcp (
new MpiComm<Ordinal> (wrapped, minTag_));
1717 template<
typename Ordinal>
1718 RCP< Comm<Ordinal> >
1719 MpiComm<Ordinal>::createSubcommunicator(
const ArrayView<const int> &ranks)
const 1721 int err = MPI_SUCCESS;
1724 MPI_Group thisGroup;
1725 err = MPI_Comm_group (*rawMpiComm_, &thisGroup);
1727 "Failed to obtain the current communicator's group. " 1728 "MPI_Comm_group failed with error \"" 1729 << mpiErrorCodeToString (err) <<
"\".");
1737 err = MPI_Group_incl (thisGroup, ranks.size(),
1738 const_cast<int*
> (ranks.getRawPtr ()), &newGroup);
1740 "Failed to create subgroup. MPI_Group_incl failed with error \"" 1741 << mpiErrorCodeToString (err) <<
"\".");
1746 err = MPI_Comm_create (*rawMpiComm_, newGroup, &newComm);
1748 "Failed to create subcommunicator. MPI_Comm_create failed with error \"" 1749 << mpiErrorCodeToString (err) <<
"\".");
1756 (void) MPI_Group_free (&newGroup);
1757 (void) MPI_Group_free (&thisGroup);
1762 err = MPI_Group_free (&newGroup);
1764 "Failed to free subgroup. MPI_Group_free failed with error \"" 1765 << mpiErrorCodeToString (err) <<
"\".");
1766 err = MPI_Group_free (&thisGroup);
1768 "Failed to free subgroup. MPI_Group_free failed with error \"" 1769 << mpiErrorCodeToString (err) <<
"\".");
1771 if (newComm == MPI_COMM_NULL) {
1772 return RCP<Comm<Ordinal> > ();
1774 using Teuchos::details::safeCommFree;
1775 typedef OpaqueWrapper<MPI_Comm> ow_type;
1776 RCP<const ow_type> wrapper =
1777 rcp_implicit_cast<
const ow_type> (opaqueWrapper (newComm, safeCommFree));
1782 return rcp (
new MpiComm<Ordinal> (wrapper, minTag_));
1790 template<
typename Ordinal>
1791 std::string MpiComm<Ordinal>::description()
const 1793 std::ostringstream oss;
1799 <<
",rawMpiComm="<<
static_cast<MPI_Comm
>(*rawMpiComm_)
1805 #ifdef TEUCHOS_MPI_COMM_DUMP 1806 template<
typename Ordinal>
1807 bool MpiComm<Ordinal>::show_dump =
false;
1814 template<
typename Ordinal>
1815 void MpiComm<Ordinal>::assertRank(
const int rank,
const std::string &rankName)
const 1818 ! ( 0 <= rank && rank < size_ ), std::logic_error
1819 ,
"Error, "<<rankName<<
" = " << rank <<
" is not < 0 or is not" 1820 " in the range [0,"<<size_-1<<
"]!" 1828 template<
typename Ordinal>
1830 Teuchos::createMpiComm(
1831 const RCP<
const OpaqueWrapper<MPI_Comm> > &rawMpiComm
1834 if( rawMpiComm.get()!=NULL && *rawMpiComm != MPI_COMM_NULL )
1835 return rcp(
new MpiComm<Ordinal>(rawMpiComm));
1836 return Teuchos::null;
1840 template<
typename Ordinal>
1842 Teuchos::createMpiComm(
1843 const RCP<
const OpaqueWrapper<MPI_Comm> > &rawMpiComm,
1844 const int defaultTag
1847 if( rawMpiComm.get()!=NULL && *rawMpiComm != MPI_COMM_NULL )
1848 return rcp(
new MpiComm<Ordinal>(rawMpiComm, defaultTag));
1849 return Teuchos::null;
1853 template<
typename Ordinal>
1855 Teuchos::getRawMpiComm(
const Comm<Ordinal> &comm)
1858 dyn_cast<
const MpiComm<Ordinal> >(comm).getRawMpiComm()
1863 #endif // HAVE_TEUCHOS_MPI 1864 #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.
Ordinal size_type
Type representing the number of elements in an ArrayRCP or view thereof.
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.
Teuchos implementation details.
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.
The Teuchos namespace contains all of the classes, structs and enums used by Teuchos, as well as a number of utility routines.
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).
static std::string name()
Returns name of this ordinal type.
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.