10 #ifndef TEUCHOS_MPI_COMM_HPP
11 #define TEUCHOS_MPI_COMM_HPP
21 #ifdef HAVE_TEUCHOS_MPI
39 #ifdef TEUCHOS_MPI_COMM_DUMP
47 mpiErrorCodeToString (
const int err);
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> >
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_; }
644 void setupMembersFromComm();
645 static int tagCounter_;
654 RCP<const OpaqueWrapper<MPI_Comm> > rawMpiComm_;
672 RCP<const OpaqueWrapper<MPI_Errhandler> > customErrorHandler_;
674 void assertRank(
const int rank,
const std::string &rankName)
const;
679 #ifdef TEUCHOS_MPI_COMM_DUMP
681 static bool show_dump;
682 #endif // TEUCHOS_MPI_COMM_DUMP
700 template<
typename Ordinal>
701 RCP<MpiComm<Ordinal> >
703 const RCP<
const OpaqueWrapper<MPI_Comm> > &rawMpiComm
720 template<
typename Ordinal>
721 RCP<MpiComm<Ordinal> >
723 const RCP<
const OpaqueWrapper<MPI_Comm> > &rawMpiComm,
755 template<
typename Ordinal>
757 getRawMpiComm(
const Comm<Ordinal> &comm);
767 template<
typename Ordinal>
768 int MpiComm<Ordinal>::tagCounter_ = MpiComm<Ordinal>::minTag_;
774 template<
typename Ordinal>
776 MpiComm (
const RCP<
const OpaqueWrapper<MPI_Comm> >& rawMpiComm)
779 rawMpiComm.get () == NULL, std::invalid_argument,
780 "Teuchos::MpiComm constructor: The input RCP is null.");
782 *rawMpiComm == MPI_COMM_NULL, std::invalid_argument,
783 "Teuchos::MpiComm constructor: The given MPI_Comm is MPI_COMM_NULL.");
785 rawMpiComm_ = rawMpiComm;
799 setupMembersFromComm ();
803 template<
typename Ordinal>
805 MpiComm (
const RCP<
const OpaqueWrapper<MPI_Comm> >& rawMpiComm,
806 const int defaultTag)
809 rawMpiComm.get () == NULL, std::invalid_argument,
810 "Teuchos::MpiComm constructor: The input RCP is null.");
812 *rawMpiComm == MPI_COMM_NULL, std::invalid_argument,
813 "Teuchos::MpiComm constructor: The given MPI_Comm is MPI_COMM_NULL.");
815 rawMpiComm_ = rawMpiComm;
817 int err = MPI_Comm_size (*rawMpiComm_, &size_);
819 "Teuchos::MpiComm constructor: MPI_Comm_size failed with "
820 "error \"" << mpiErrorCodeToString (err) <<
"\".");
822 err = MPI_Comm_rank (*rawMpiComm_, &rank_);
824 "Teuchos::MpiComm constructor: MPI_Comm_rank failed with "
825 "error \"" << mpiErrorCodeToString (err) <<
"\".");
830 template<
typename Ordinal>
831 MpiComm<Ordinal>::MpiComm (MPI_Comm rawMpiComm)
834 std::invalid_argument,
"Teuchos::MpiComm constructor: The given MPI_Comm "
835 "is MPI_COMM_NULL.");
839 rawMpiComm_ = opaqueWrapper<MPI_Comm> (rawMpiComm);
853 setupMembersFromComm ();
857 template<
typename Ordinal>
858 MpiComm<Ordinal>::MpiComm (
const MpiComm<Ordinal>& other) :
859 rawMpiComm_ (opaqueWrapper<MPI_Comm> (MPI_COMM_NULL))
862 RCP<const OpaqueWrapper<MPI_Comm> > origCommPtr = other.getRawMpiComm ();
864 "Teuchos::MpiComm copy constructor: "
865 "The input's getRawMpiComm() method returns null.");
866 MPI_Comm origComm = *origCommPtr;
868 "Teuchos::MpiComm copy constructor: "
869 "The input's raw MPI_Comm is MPI_COMM_NULL.");
877 rawMpiComm_ = origCommPtr;
881 const int err = MPI_Comm_dup (origComm, &newComm);
883 "Teuchos::MpiComm copy constructor: MPI_Comm_dup failed with "
884 "the following error: " << mpiErrorCodeToString (err));
886 rawMpiComm_ = opaqueWrapper (newComm, details::safeCommFree);
889 setupMembersFromComm ();
893 template<
typename Ordinal>
894 void MpiComm<Ordinal>::setupMembersFromComm ()
896 int err = MPI_Comm_size (*rawMpiComm_, &size_);
898 "Teuchos::MpiComm constructor: MPI_Comm_size failed with "
899 "error \"" << mpiErrorCodeToString (err) <<
"\".");
900 err = MPI_Comm_rank (*rawMpiComm_, &rank_);
902 "Teuchos::MpiComm constructor: MPI_Comm_rank failed with "
903 "error \"" << mpiErrorCodeToString (err) <<
"\".");
906 if (tagCounter_ > maxTag_) {
907 tagCounter_ = minTag_;
909 tag_ = tagCounter_++;
919 MPI_Bcast (&tag_, 1, MPI_INT, 0, *rawMpiComm_);
923 template<
typename Ordinal>
926 setErrorHandler (
const RCP<
const OpaqueWrapper<MPI_Errhandler> >& errHandler)
929 const int err = details::setCommErrhandler (*getRawMpiComm (), *errHandler);
931 "Teuchos::MpiComm: Setting the MPI_Comm's error handler failed with "
932 "error \"" << mpiErrorCodeToString (err) <<
"\".");
936 customErrorHandler_ = errHandler;
943 template<
typename Ordinal>
944 int MpiComm<Ordinal>::getRank()
const
950 template<
typename Ordinal>
951 int MpiComm<Ordinal>::getSize()
const
957 template<
typename Ordinal>
958 void MpiComm<Ordinal>::barrier()
const
961 "Teuchos::MpiComm<"<<OrdinalTraits<Ordinal>::name()<<
">::barrier()"
963 const int err = MPI_Barrier (*rawMpiComm_);
965 "Teuchos::MpiComm::barrier: MPI_Barrier failed with error \""
966 << mpiErrorCodeToString (err) <<
"\".");
970 template<
typename Ordinal>
971 void MpiComm<Ordinal>::broadcast(
972 const int rootRank,
const Ordinal bytes,
char buffer[]
976 "Teuchos::MpiComm<"<<OrdinalTraits<Ordinal>::name()<<
">::broadcast(...)"
978 const int err = MPI_Bcast (buffer, bytes, MPI_CHAR, rootRank, *rawMpiComm_);
980 "Teuchos::MpiComm::broadcast: MPI_Bcast failed with error \""
981 << mpiErrorCodeToString (err) <<
"\".");
985 template<
typename Ordinal>
986 void MpiComm<Ordinal>::gatherAll(
987 const Ordinal sendBytes,
const char sendBuffer[],
988 const Ordinal recvBytes,
char recvBuffer[]
992 "Teuchos::MpiComm<"<<OrdinalTraits<Ordinal>::name()<<
">::gatherAll(...)"
996 MPI_Allgather (const_cast<char *>(sendBuffer), sendBytes, MPI_CHAR,
997 recvBuffer, sendBytes, MPI_CHAR, *rawMpiComm_);
1002 "Teuchos::MpiComm::gatherAll: MPI_Allgather failed with error \""
1003 << mpiErrorCodeToString (err) <<
"\".");
1007 template<
typename Ordinal>
1009 MpiComm<Ordinal>::gather (
const Ordinal sendBytes,
1010 const char sendBuffer[],
1011 const Ordinal recvBytes,
1013 const int root)
const
1018 "Teuchos::MpiComm<"<<OrdinalTraits<Ordinal>::name()<<
">::gather(...)"
1021 MPI_Gather (const_cast<char *> (sendBuffer), sendBytes, MPI_CHAR,
1022 recvBuffer, sendBytes, MPI_CHAR, root, *rawMpiComm_);
1024 "Teuchos::MpiComm::gather: MPI_Gather failed with error \""
1025 << mpiErrorCodeToString (err) <<
"\".");
1029 template<
typename Ordinal>
1032 reduceAll (
const ValueTypeReductionOp<Ordinal,char> &reductOp,
1033 const Ordinal bytes,
1034 const char sendBuffer[],
1035 char globalReducts[])
const
1038 int err = MPI_SUCCESS;
1040 if (bytes == 0)
return;
1042 Details::MpiReductionOp<Ordinal> opWrap (reductOp);
1043 MPI_Op op = Details::setMpiReductionOp (opWrap);
1052 MPI_Datatype char_block;
1053 err = MPI_Type_contiguous (bytes, MPI_CHAR, &char_block);
1055 err != MPI_SUCCESS, std::runtime_error,
"Teuchos::reduceAll: "
1056 "MPI_Type_contiguous failed with error \"" << mpiErrorCodeToString (err)
1058 err = MPI_Type_commit (&char_block);
1060 err != MPI_SUCCESS, std::runtime_error,
"Teuchos::reduceAll: "
1061 "MPI_Type_commit failed with error \"" << mpiErrorCodeToString (err)
1064 if (sendBuffer == globalReducts) {
1068 err = MPI_Allreduce (MPI_IN_PLACE, globalReducts, 1,
1069 char_block, op, *rawMpiComm_);
1072 err = MPI_Allreduce (const_cast<char*> (sendBuffer), globalReducts, 1,
1073 char_block, op, *rawMpiComm_);
1075 if (err != MPI_SUCCESS) {
1080 (void) MPI_Type_free (&char_block);
1082 true, std::runtime_error,
"Teuchos::reduceAll (MPI, custom op): "
1083 "MPI_Allreduce failed with error \"" << mpiErrorCodeToString (err)
1086 err = MPI_Type_free (&char_block);
1088 err != MPI_SUCCESS, std::runtime_error,
"Teuchos::reduceAll: "
1089 "MPI_Type_free failed with error \"" << mpiErrorCodeToString (err)
1094 template<
typename Ordinal>
1095 void MpiComm<Ordinal>::scan(
1096 const ValueTypeReductionOp<Ordinal,char> &reductOp
1097 ,
const Ordinal bytes,
const char sendBuffer[],
char scanReducts[]
1102 Details::MpiReductionOp<Ordinal> opWrap (reductOp);
1103 MPI_Op op = Details::setMpiReductionOp (opWrap);
1105 MPI_Scan (const_cast<char*> (sendBuffer), scanReducts, bytes, MPI_CHAR,
1108 "Teuchos::MpiComm::scan: MPI_Scan() failed with error \""
1109 << mpiErrorCodeToString (err) <<
"\".");
1113 template<
typename Ordinal>
1116 const char sendBuffer[],
1117 const int destRank)
const
1121 #ifdef TEUCHOS_MPI_COMM_DUMP
1123 dumpBuffer<Ordinal,char>(
1124 "Teuchos::MpiComm<Ordinal>::send(...)"
1125 ,
"sendBuffer", bytes, sendBuffer
1128 #endif // TEUCHOS_MPI_COMM_DUMP
1130 const int err = MPI_Send (const_cast<char*>(sendBuffer), bytes, MPI_CHAR,
1131 destRank, tag_, *rawMpiComm_);
1133 "Teuchos::MpiComm::send: MPI_Send() failed with error \""
1134 << mpiErrorCodeToString (err) <<
"\".");
1138 template<
typename Ordinal>
1141 const char sendBuffer[],
1143 const int tag)
const
1146 const int err = MPI_Send (const_cast<char*> (sendBuffer), bytes, MPI_CHAR,
1147 destRank, tag, *rawMpiComm_);
1149 "Teuchos::MpiComm::send: MPI_Send() failed with error \""
1150 << mpiErrorCodeToString (err) <<
"\".");
1154 template<
typename Ordinal>
1157 const char sendBuffer[],
1158 const int destRank)
const
1162 #ifdef TEUCHOS_MPI_COMM_DUMP
1164 dumpBuffer<Ordinal,char>(
1165 "Teuchos::MpiComm<Ordinal>::send(...)"
1166 ,
"sendBuffer", bytes, sendBuffer
1169 #endif // TEUCHOS_MPI_COMM_DUMP
1171 const int err = MPI_Ssend (const_cast<char*>(sendBuffer), bytes, MPI_CHAR,
1172 destRank, tag_, *rawMpiComm_);
1174 "Teuchos::MpiComm::send: MPI_Ssend() failed with error \""
1175 << mpiErrorCodeToString (err) <<
"\".");
1178 template<
typename Ordinal>
1181 const char sendBuffer[],
1183 const int tag)
const
1187 MPI_Ssend (const_cast<char*>(sendBuffer), bytes, MPI_CHAR,
1188 destRank, tag, *rawMpiComm_);
1190 "Teuchos::MpiComm::send: MPI_Ssend() failed with error \""
1191 << mpiErrorCodeToString (err) <<
"\".");
1194 template<
typename Ordinal>
1196 const ArrayView<const char> &sendBuffer,
1202 #ifdef TEUCHOS_MPI_COMM_DUMP
1204 dumpBuffer<Ordinal,char>(
1205 "Teuchos::MpiComm<Ordinal>::readySend(...)"
1206 ,
"sendBuffer", bytes, sendBuffer
1209 #endif // TEUCHOS_MPI_COMM_DUMP
1212 MPI_Rsend (const_cast<char*>(sendBuffer.getRawPtr()), static_cast<int>(sendBuffer.size()),
1213 MPI_CHAR, destRank, tag_, *rawMpiComm_);
1215 "Teuchos::MpiComm::readySend: MPI_Rsend() failed with error \""
1216 << mpiErrorCodeToString (err) <<
"\".");
1220 template<
typename Ordinal>
1223 const char sendBuffer[],
1225 const int tag)
const
1229 MPI_Rsend (const_cast<char*> (sendBuffer), bytes,
1230 MPI_CHAR, destRank, tag, *rawMpiComm_);
1232 "Teuchos::MpiComm::readySend: MPI_Rsend() failed with error \""
1233 << mpiErrorCodeToString (err) <<
"\".");
1237 template<
typename Ordinal>
1239 MpiComm<Ordinal>::receive (
const int sourceRank,
1240 const Ordinal bytes,
1241 char recvBuffer[])
const
1248 const int theSrcRank = (sourceRank < 0) ? MPI_ANY_SOURCE : sourceRank;
1251 const int err = MPI_Recv (recvBuffer, bytes, MPI_CHAR, theSrcRank, tag_,
1252 *rawMpiComm_, &status);
1254 "Teuchos::MpiComm::receive: MPI_Recv() failed with error \""
1255 << mpiErrorCodeToString (err) <<
"\".");
1257 #ifdef TEUCHOS_MPI_COMM_DUMP
1259 dumpBuffer<Ordinal,char> (
"Teuchos::MpiComm<Ordinal>::receive(...)",
1260 "recvBuffer", bytes, recvBuffer);
1262 #endif // TEUCHOS_MPI_COMM_DUMP
1265 return status.MPI_SOURCE;
1269 template<
typename Ordinal>
1270 RCP<CommRequest<Ordinal> >
1272 const int destRank)
const
1277 MPI_Request rawMpiRequest = MPI_REQUEST_NULL;
1279 MPI_Isend (const_cast<char*> (sendBuffer.getRawPtr ()),
1280 as<Ordinal> (sendBuffer.size ()), MPI_CHAR,
1281 destRank, tag_, *rawMpiComm_, &rawMpiRequest);
1283 "Teuchos::MpiComm::isend: MPI_Isend() failed with error \""
1284 << mpiErrorCodeToString (err) <<
"\".");
1286 return mpiCommRequest<Ordinal> (rawMpiRequest, sendBuffer.size ());
1290 template<
typename Ordinal>
1291 RCP<CommRequest<Ordinal> >
1293 isend (
const ArrayView<const char> &sendBuffer,
1295 const int tag)
const
1300 MPI_Request rawMpiRequest = MPI_REQUEST_NULL;
1302 MPI_Isend (const_cast<char*> (sendBuffer.getRawPtr ()),
1303 as<Ordinal> (sendBuffer.size ()), MPI_CHAR,
1304 destRank, tag, *rawMpiComm_, &rawMpiRequest);
1306 "Teuchos::MpiComm::isend: MPI_Isend() failed with error \""
1307 << mpiErrorCodeToString (err) <<
"\".");
1309 return mpiCommRequest<Ordinal> (rawMpiRequest, sendBuffer.size ());
1313 template<
typename Ordinal>
1314 RCP<CommRequest<Ordinal> >
1316 const int sourceRank)
const
1323 const int theSrcRank = (sourceRank < 0) ? MPI_ANY_SOURCE : sourceRank;
1325 MPI_Request rawMpiRequest = MPI_REQUEST_NULL;
1327 MPI_Irecv (const_cast<char*>(recvBuffer.getRawPtr()), recvBuffer.size(),
1328 MPI_CHAR, theSrcRank, tag_, *rawMpiComm_, &rawMpiRequest);
1330 "Teuchos::MpiComm::ireceive: MPI_Irecv() failed with error \""
1331 << mpiErrorCodeToString (err) <<
"\".");
1333 return mpiCommRequest<Ordinal> (rawMpiRequest, recvBuffer.size());
1336 template<
typename Ordinal>
1337 RCP<CommRequest<Ordinal> >
1339 const int sourceRank,
1340 const int tag)
const
1347 const int theSrcRank = (sourceRank < 0) ? MPI_ANY_SOURCE : sourceRank;
1349 MPI_Request rawMpiRequest = MPI_REQUEST_NULL;
1351 MPI_Irecv (const_cast<char*> (recvBuffer.getRawPtr ()), recvBuffer.size (),
1352 MPI_CHAR, theSrcRank, tag, *rawMpiComm_, &rawMpiRequest);
1354 "Teuchos::MpiComm::ireceive: MPI_Irecv() failed with error \""
1355 << mpiErrorCodeToString (err) <<
"\".");
1357 return mpiCommRequest<Ordinal> (rawMpiRequest, recvBuffer.size ());
1362 template<
typename Ordinal>
1364 waitAllImpl (
const ArrayView<RCP<CommRequest<Ordinal> > >& requests,
1365 const ArrayView<MPI_Status>& rawMpiStatuses)
1367 typedef typename ArrayView<RCP<CommRequest<Ordinal> > >::size_type size_type;
1368 const size_type count = requests.size();
1372 std::logic_error,
"Teuchos::MpiComm's waitAllImpl: rawMpiStatus.size() = "
1373 << rawMpiStatuses.size() <<
" != requests.size() = " << requests.size()
1374 <<
". Please report this bug to the Tpetra developers.");
1387 bool someNullRequests =
false;
1388 Array<MPI_Request> rawMpiRequests (count, MPI_REQUEST_NULL);
1389 for (
int i = 0; i < count; ++i) {
1390 RCP<CommRequest<Ordinal> > request = requests[i];
1392 RCP<MpiCommRequestBase<Ordinal> > mpiRequest =
1393 rcp_dynamic_cast<MpiCommRequestBase<Ordinal> > (request);
1401 rawMpiRequests[i] = mpiRequest->releaseRawMpiRequest();
1404 rawMpiRequests[i] = MPI_REQUEST_NULL;
1405 someNullRequests =
true;
1418 const int err = MPI_Waitall (count, rawMpiRequests.getRawPtr(),
1419 rawMpiStatuses.getRawPtr());
1429 if (err != MPI_SUCCESS) {
1430 if (err == MPI_ERR_IN_STATUS) {
1438 Array<std::pair<size_type, int> > errorLocationsAndCodes;
1439 for (size_type k = 0; k < rawMpiStatuses.size(); ++k) {
1440 const int curErr = rawMpiStatuses[k].MPI_ERROR;
1441 if (curErr != MPI_SUCCESS) {
1442 errorLocationsAndCodes.push_back (std::make_pair (k, curErr));
1445 const size_type numErrs = errorLocationsAndCodes.size();
1450 std::ostringstream os;
1451 os <<
"Teuchos::MpiComm::waitAll: MPI_Waitall() failed with error \""
1452 << mpiErrorCodeToString (err) <<
"\". Of the " << count
1453 <<
" total request" << (count != 1 ?
"s" :
"") <<
", " << numErrs
1454 <<
" failed. Here are the indices of the failed requests, and the "
1455 "error codes extracted from their returned MPI_Status objects:"
1457 for (size_type k = 0; k < numErrs; ++k) {
1458 const size_type errInd = errorLocationsAndCodes[k].first;
1459 os <<
"Request " << errInd <<
": MPI_ERROR = "
1460 << mpiErrorCodeToString (rawMpiStatuses[errInd].MPI_ERROR)
1463 if (someNullRequests) {
1464 os <<
" On input to MPI_Waitall, there was at least one MPI_"
1465 "Request that was MPI_REQUEST_NULL. MPI_Waitall should not "
1466 "normally fail in that case, but we thought we should let you know "
1475 std::ostringstream os;
1476 os <<
"Teuchos::MpiComm::waitAll: MPI_Waitall() failed with error \""
1477 << mpiErrorCodeToString (err) <<
"\".";
1478 if (someNullRequests) {
1479 os <<
" On input to MPI_Waitall, there was at least one MPI_Request "
1480 "that was MPI_REQUEST_NULL. MPI_Waitall should not normally fail in "
1481 "that case, but we thought we should let you know regardless.";
1489 std::fill (requests.begin(), requests.end(),
null);
1495 template<
typename Ordinal>
1497 waitAllImpl (
const ArrayView<RCP<CommRequest<Ordinal> > >& requests)
1499 typedef typename ArrayView<RCP<CommRequest<Ordinal> > >::size_type size_type;
1500 const size_type count = requests.size ();
1513 bool someNullRequests =
false;
1514 Array<MPI_Request> rawMpiRequests (count, MPI_REQUEST_NULL);
1515 for (
int i = 0; i < count; ++i) {
1516 RCP<CommRequest<Ordinal> > request = requests[i];
1517 if (! request.is_null ()) {
1518 RCP<MpiCommRequestBase<Ordinal> > mpiRequest =
1519 rcp_dynamic_cast<MpiCommRequestBase<Ordinal> > (request);
1527 rawMpiRequests[i] = mpiRequest->releaseRawMpiRequest ();
1530 rawMpiRequests[i] = MPI_REQUEST_NULL;
1531 someNullRequests =
true;
1541 const int err = MPI_Waitall (count, rawMpiRequests.getRawPtr(),
1542 MPI_STATUSES_IGNORE);
1552 if (err != MPI_SUCCESS) {
1553 std::ostringstream os;
1554 os <<
"Teuchos::MpiComm::waitAll: MPI_Waitall() failed with error \""
1555 << mpiErrorCodeToString (err) <<
"\".";
1556 if (someNullRequests) {
1557 os << std::endl <<
"On input to MPI_Waitall, there was at least one "
1558 "MPI_Request that was MPI_REQUEST_NULL. MPI_Waitall should not "
1559 "normally fail in that case, but we thought we should let you know "
1570 std::fill (requests.begin(), requests.end(),
null);
1577 template<
typename Ordinal>
1580 waitAll (
const ArrayView<RCP<CommRequest<Ordinal> > >& requests)
const
1585 waitAllImpl<Ordinal> (requests);
1589 template<
typename Ordinal>
1592 waitAll (
const ArrayView<RCP<CommRequest<Ordinal> > >& requests,
1593 const ArrayView<RCP<CommStatus<Ordinal> > >& statuses)
const
1597 typedef typename ArrayView<RCP<CommRequest<Ordinal> > >::size_type size_type;
1598 const size_type count = requests.size();
1601 std::invalid_argument,
"Teuchos::MpiComm::waitAll: requests.size() = "
1602 << count <<
" != statuses.size() = " << statuses.size() <<
".");
1604 Array<MPI_Status> rawMpiStatuses (count);
1605 waitAllImpl<Ordinal> (requests, rawMpiStatuses());
1608 for (size_type i = 0; i < count; ++i) {
1609 statuses[i] = mpiCommStatus<Ordinal> (rawMpiStatuses[i]);
1614 template<
typename Ordinal>
1615 RCP<CommStatus<Ordinal> >
1616 MpiComm<Ordinal>::wait (
const Ptr<RCP<CommRequest<Ordinal> > >& request)
const
1624 RCP<CommStatus<Ordinal> > status = (*request)->wait ();
1632 template<
typename Ordinal>
1633 RCP< Comm<Ordinal> >
1634 MpiComm<Ordinal>::duplicate()
const
1636 MPI_Comm origRawComm = *rawMpiComm_;
1637 MPI_Comm newRawComm = MPI_COMM_NULL;
1638 const int err = MPI_Comm_dup (origRawComm, &newRawComm);
1640 "::MpiComm::duplicate: MPI_Comm_dup failed with the following error: "
1641 << mpiErrorCodeToString (err));
1646 RCP<OpaqueWrapper<MPI_Comm> > wrapped =
1647 opaqueWrapper<MPI_Comm> (newRawComm, details::safeCommFree);
1651 RCP<MpiComm<Ordinal> > newComm =
1652 rcp (
new MpiComm<Ordinal> (wrapped.getConst (), minTag_));
1653 return rcp_implicit_cast<Comm<Ordinal> > (newComm);
1657 template<
typename Ordinal>
1658 RCP< Comm<Ordinal> >
1662 const int splitReturn =
1663 MPI_Comm_split (*rawMpiComm_,
1664 color < 0 ? MPI_UNDEFINED : color,
1668 splitReturn != MPI_SUCCESS,
1670 "Teuchos::MpiComm::split: Failed to create communicator with color "
1671 << color <<
"and key " << key <<
". MPI_Comm_split failed with error \""
1672 << mpiErrorCodeToString (splitReturn) <<
"\".");
1673 if (newComm == MPI_COMM_NULL) {
1674 return RCP< Comm<Ordinal> >();
1676 RCP<const OpaqueWrapper<MPI_Comm> > wrapped =
1677 opaqueWrapper<MPI_Comm> (newComm, details::safeCommFree);
1682 return rcp (
new MpiComm<Ordinal> (wrapped, minTag_));
1687 template<
typename Ordinal>
1688 RCP< Comm<Ordinal> >
1689 MpiComm<Ordinal>::createSubcommunicator(
const ArrayView<const int> &ranks)
const
1691 int err = MPI_SUCCESS;
1694 MPI_Group thisGroup;
1695 err = MPI_Comm_group (*rawMpiComm_, &thisGroup);
1697 "Failed to obtain the current communicator's group. "
1698 "MPI_Comm_group failed with error \""
1699 << mpiErrorCodeToString (err) <<
"\".");
1707 err = MPI_Group_incl (thisGroup, ranks.size(),
1708 const_cast<int*
> (ranks.getRawPtr ()), &newGroup);
1710 "Failed to create subgroup. MPI_Group_incl failed with error \""
1711 << mpiErrorCodeToString (err) <<
"\".");
1716 err = MPI_Comm_create (*rawMpiComm_, newGroup, &newComm);
1718 "Failed to create subcommunicator. MPI_Comm_create failed with error \""
1719 << mpiErrorCodeToString (err) <<
"\".");
1726 (void) MPI_Group_free (&newGroup);
1727 (void) MPI_Group_free (&thisGroup);
1732 err = MPI_Group_free (&newGroup);
1734 "Failed to free subgroup. MPI_Group_free failed with error \""
1735 << mpiErrorCodeToString (err) <<
"\".");
1736 err = MPI_Group_free (&thisGroup);
1738 "Failed to free subgroup. MPI_Group_free failed with error \""
1739 << mpiErrorCodeToString (err) <<
"\".");
1741 if (newComm == MPI_COMM_NULL) {
1742 return RCP<Comm<Ordinal> > ();
1744 using Teuchos::details::safeCommFree;
1745 typedef OpaqueWrapper<MPI_Comm> ow_type;
1746 RCP<const ow_type> wrapper =
1747 rcp_implicit_cast<
const ow_type> (opaqueWrapper (newComm, safeCommFree));
1752 return rcp (
new MpiComm<Ordinal> (wrapper, minTag_));
1760 template<
typename Ordinal>
1761 std::string MpiComm<Ordinal>::description()
const
1763 std::ostringstream oss;
1769 <<
",rawMpiComm="<<
static_cast<MPI_Comm
>(*rawMpiComm_)
1775 #ifdef TEUCHOS_MPI_COMM_DUMP
1776 template<
typename Ordinal>
1777 bool MpiComm<Ordinal>::show_dump =
false;
1784 template<
typename Ordinal>
1785 void MpiComm<Ordinal>::assertRank(
const int rank,
const std::string &rankName)
const
1788 ! ( 0 <= rank && rank < size_ ), std::logic_error
1789 ,
"Error, "<<rankName<<
" = " << rank <<
" is not < 0 or is not"
1790 " in the range [0,"<<size_-1<<
"]!"
1798 template<
typename Ordinal>
1800 Teuchos::createMpiComm(
1801 const RCP<
const OpaqueWrapper<MPI_Comm> > &rawMpiComm
1804 if( rawMpiComm.get()!=NULL && *rawMpiComm != MPI_COMM_NULL )
1805 return rcp(
new MpiComm<Ordinal>(rawMpiComm));
1810 template<
typename Ordinal>
1812 Teuchos::createMpiComm(
1813 const RCP<
const OpaqueWrapper<MPI_Comm> > &rawMpiComm,
1814 const int defaultTag
1817 if( rawMpiComm.get()!=NULL && *rawMpiComm != MPI_COMM_NULL )
1818 return rcp(
new MpiComm<Ordinal>(rawMpiComm, defaultTag));
1823 template<
typename Ordinal>
1825 Teuchos::getRawMpiComm(
const Comm<Ordinal> &comm)
1828 dyn_cast<
const MpiComm<Ordinal> >(comm).getRawMpiComm()
1833 #endif // HAVE_TEUCHOS_MPI
1834 #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...
std::string typeName(const T &t)
Template function for returning the concrete type name of a passed-in 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.
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...
#define TEUCHOS_COMM_TIME_MONITOR(FUNCNAME)
std::vector< std::string > split(const std::string &str, const std::string &delimiters, const size_t start)
Split the given string using the given set of delimiters.
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
Deprecated.
T_To & dyn_cast(T_From &from)
Dynamic casting utility function meant to replace dynamic_cast<T&> by throwing a better documented er...
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). ...
TypeTo as(const TypeFrom &t)
Convert from one value type to another.
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.
RCP< Teuchos::CommRequest< int > > isend(const ArrayRCP< const double > &sendBuffer, const int destRank, const int tag, const Comm< int > &comm)
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).
#define TEUCHOSCOMM_LIB_DLL_EXPORT
Smart reference counting pointer class for automatic garbage collection.
RCP< MpiCommRequest > mpiCommRequest(MPI_Request rawMpiRequest, const ArrayRCP< const char > &buffer)
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.