|
Teuchos Package Browser (Single Doxygen Collection)
Version of the Day
|
00001 /* 00002 // @HEADER 00003 // *********************************************************************** 00004 // 00005 // Teuchos: Common Tools Package 00006 // Copyright (2004) Sandia Corporation 00007 // 00008 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive 00009 // license for use of this work by or on behalf of the U.S. Government. 00010 // 00011 // Redistribution and use in source and binary forms, with or without 00012 // modification, are permitted provided that the following conditions are 00013 // met: 00014 // 00015 // 1. Redistributions of source code must retain the above copyright 00016 // notice, this list of conditions and the following disclaimer. 00017 // 00018 // 2. Redistributions in binary form must reproduce the above copyright 00019 // notice, this list of conditions and the following disclaimer in the 00020 // documentation and/or other materials provided with the distribution. 00021 // 00022 // 3. Neither the name of the Corporation nor the names of the 00023 // contributors may be used to endorse or promote products derived from 00024 // this software without specific prior written permission. 00025 // 00026 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY 00027 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00028 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 00029 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE 00030 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 00031 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 00032 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 00033 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 00034 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 00035 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00036 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00037 // 00038 // Questions? Contact Michael A. Heroux (maherou@sandia.gov) 00039 // 00040 // *********************************************************************** 00041 // @HEADER 00042 */ 00043 00044 #include "Teuchos_UnitTestHarness.hpp" 00045 #include "Teuchos_DefaultMpiComm.hpp" 00046 #include "Teuchos_CommHelpers.hpp" 00047 #include "Teuchos_DefaultComm.hpp" 00048 #include "Teuchos_getConst.hpp" 00049 #include "Teuchos_as.hpp" 00050 00051 namespace std { 00052 00053 template <typename Packet> 00054 ostream & operator<< (ostream& os, const pair<Packet, Packet>& arg) 00055 { 00056 os << "(" << arg.first << "," << arg.second << ")"; 00057 return os; 00058 } 00059 00060 } // namespace std 00061 00062 namespace { 00063 using Teuchos::Array; 00064 using Teuchos::ArrayRCP; 00065 using Teuchos::ArrayView; 00066 using Teuchos::as; 00067 using Teuchos::Comm; 00068 using Teuchos::CommRequest; 00069 using Teuchos::CommStatus; 00070 using Teuchos::ireceive; 00071 using Teuchos::isend; 00072 using Teuchos::MpiComm; 00073 using Teuchos::outArg; 00074 using Teuchos::RCP; 00075 using Teuchos::rcp; 00076 using Teuchos::send; 00077 using Teuchos::waitAll; 00078 using std::endl; 00079 00080 TEUCHOS_STATIC_SETUP() 00081 { 00082 Teuchos::CommandLineProcessor& clp = Teuchos::UnitTestRepository::getCLP (); 00083 clp.addOutputSetupOptions (true); 00084 } 00085 00086 TEUCHOS_UNIT_TEST( MpiCommTag, IrecvSend ) 00087 { 00088 typedef ArrayRCP<int>::size_type size_type; 00089 00090 RCP<const Comm<int> > comm = rcp (new MpiComm<int> (MPI_COMM_WORLD)); 00091 const int myRank = comm->getRank (); 00092 const int numProcs = comm->getSize (); 00093 00094 // If there is only one process, then the left and right neighbors 00095 // are the same, namely the calling process. MPI allows a process 00096 // to send to and receive from itself. On the other hand, we want 00097 // to test blocking sends, and we want to post two sends, so we only 00098 // allow > 1 processes. 00099 if (numProcs == 1) { 00100 out << "numProcs == 1, test passes trivially." << endl; 00101 return; 00102 } 00103 out << "Test setup" << endl; 00104 00105 // If there are only two processes, the left neighbor and the right 00106 // neighbor are the same, namely the other process. 00107 int leftNeighbor = (myRank - 1) % numProcs; 00108 int rightNeighbor = (myRank + 1) % numProcs; 00109 // C doesn't guarantee nonnegativity of the result of the % operator. 00110 if (leftNeighbor < 0) { 00111 leftNeighbor += numProcs; 00112 } 00113 if (rightNeighbor < 0) { 00114 rightNeighbor += numProcs; 00115 } 00116 Array<int> expectedSourceRanks (2); // expected source ranks for receives 00117 expectedSourceRanks[0] = leftNeighbor; 00118 expectedSourceRanks[1] = rightNeighbor; 00119 std::sort (expectedSourceRanks.begin (), expectedSourceRanks.end ()); 00120 00121 // Receive buffer, with subbuffers for each neighbor. 00122 ArrayRCP<int> recvBuf (2); 00123 ArrayRCP<int> leftRecvBuf = recvBuf.persistingView (0, 1); 00124 ArrayRCP<int> rightRecvBuf = recvBuf.persistingView (1, 1); 00125 00126 // Send buffer, with subbuffers for each neighbor. 00127 Array<int> sendBuf (2); 00128 ArrayView<int> leftSendBuf = sendBuf.view (0, 1); 00129 ArrayView<int> rightSendBuf = sendBuf.view (1, 1); 00130 00132 // First round of messages 00134 out << "Round 1 of messages" << endl; 00135 00136 // Tag to use for the first set of messages. 00137 const int tag1 = 42; 00138 00139 // Fill receive buffer with error flags. 00140 for (size_type k = 0; k < recvBuf.size (); ++k) { 00141 recvBuf[k] = -1; 00142 } 00143 00144 // Send my process rank plus the current tag to all neighbors. 00145 for (size_type k = 0; k < sendBuf.size (); ++k) { 00146 sendBuf[k] = myRank + tag1; 00147 } 00148 00149 // Post receives from left and right neighbors. 00150 Array<RCP<CommRequest<int> > > requests (2); 00151 requests[0] = ireceive<int, int> (leftRecvBuf, leftNeighbor, tag1, *comm); 00152 requests[1] = ireceive<int, int> (rightRecvBuf, rightNeighbor, tag1, *comm); 00153 00154 // Post sends to left and right neighbors. 00155 send<int, int> (leftSendBuf.getRawPtr (), as<int> (leftSendBuf.size ()), 00156 leftNeighbor, tag1, *comm); 00157 send<int, int> (rightSendBuf.getRawPtr (), as<int> (rightSendBuf.size ()), 00158 rightNeighbor, tag1, *comm); 00159 00160 // Wait for the receives to complete. 00161 Array<RCP<CommStatus<int> > > statuses (2); 00162 waitAll (*comm, requests (), statuses ()); 00163 00164 // Make sure the source ranks are correct. 00165 Array<int> sourceRanks (2); 00166 for (size_type k = 0; k < 2; ++k) { 00167 sourceRanks[k] = statuses[k]->getSourceRank (); 00168 } 00169 std::sort (sourceRanks.begin (), sourceRanks.end ()); 00170 TEST_EQUALITY( sourceRanks.size (), expectedSourceRanks.size () ); 00171 for (size_type k = 0; k < sourceRanks.size (); ++k) { 00172 TEST_EQUALITY( sourceRanks[k], expectedSourceRanks[k] ); 00173 } 00174 00175 // Make sure the source tags are correct. 00176 for (size_type k = 0; k < statuses.size (); ++k) { 00177 TEST_EQUALITY( statuses[k]->getTag (), tag1 ); 00178 } 00179 00180 // Make sure the message contents are correct. 00181 TEST_EQUALITY( leftRecvBuf[0], leftNeighbor + tag1 ); 00182 TEST_EQUALITY( rightRecvBuf[0], rightNeighbor + tag1 ); 00183 00185 // Second round of messages 00187 out << "Round 2 of messages" << endl; 00188 00189 // Tag to use for the second set of messages. 00190 const int tag2 = 100; 00191 00192 // Fill receive buffer with error flags. 00193 for (size_type k = 0; k < recvBuf.size (); ++k) { 00194 recvBuf[k] = -1; 00195 } 00196 00197 // Send my process rank plus the current tag to all neighbors. 00198 for (size_type k = 0; k < sendBuf.size (); ++k) { 00199 sendBuf[k] = myRank + tag2; 00200 } 00201 00202 // Post receives from left and right neighbors. 00203 requests[0] = ireceive<int, int> (leftRecvBuf, leftNeighbor, tag2, *comm); 00204 requests[1] = ireceive<int, int> (rightRecvBuf, rightNeighbor, tag2, *comm); 00205 00206 // Post sends to left and right neighbors. 00207 send<int, int> (leftSendBuf.getRawPtr (), as<int> (leftSendBuf.size ()), 00208 leftNeighbor, tag2, *comm); 00209 send<int, int> (rightSendBuf.getRawPtr (), as<int> (rightSendBuf.size ()), 00210 rightNeighbor, tag2, *comm); 00211 00212 // Wait for the receives to complete. 00213 waitAll (*comm, requests (), statuses ()); 00214 00215 // Make sure the source ranks are correct. 00216 for (size_type k = 0; k < 2; ++k) { 00217 sourceRanks[k] = statuses[k]->getSourceRank (); 00218 } 00219 std::sort (sourceRanks.begin (), sourceRanks.end ()); 00220 TEST_EQUALITY( sourceRanks.size (), expectedSourceRanks.size () ); 00221 for (size_type k = 0; k < sourceRanks.size (); ++k) { 00222 TEST_EQUALITY( sourceRanks[k], expectedSourceRanks[k] ); 00223 } 00224 00225 // Make sure the source tags are correct. 00226 for (size_type k = 0; k < statuses.size (); ++k) { 00227 TEST_EQUALITY( statuses[k]->getTag (), tag2 ); 00228 } 00229 00230 // Make sure the message contents are correct. 00231 TEST_EQUALITY( leftRecvBuf[0], leftNeighbor + tag2 ); 00232 TEST_EQUALITY( rightRecvBuf[0], rightNeighbor + tag2 ); 00233 00235 // Third round of messages 00237 out << "Round 3 of messages" << endl; 00238 00239 // In this round, we try again with the first tag. This will tell 00240 // us if any first-round messages got mixed up with second-round 00241 // messages. 00242 const int tag3 = tag1; 00243 00244 // Fill receive buffer with error flags. 00245 for (size_type k = 0; k < recvBuf.size (); ++k) { 00246 recvBuf[k] = -1; 00247 } 00248 00249 // Send my process rank plus the current tag to all neighbors. 00250 for (size_type k = 0; k < sendBuf.size (); ++k) { 00251 sendBuf[k] = myRank + tag3; 00252 } 00253 00254 // Post receives from left and right neighbors. 00255 requests[0] = ireceive<int, int> (leftRecvBuf, leftNeighbor, tag3, *comm); 00256 requests[1] = ireceive<int, int> (rightRecvBuf, rightNeighbor, tag3, *comm); 00257 00258 // Post sends to left and right neighbors. 00259 send<int, int> (leftSendBuf.getRawPtr (), as<int> (leftSendBuf.size ()), 00260 leftNeighbor, tag3, *comm); 00261 send<int, int> (rightSendBuf.getRawPtr (), as<int> (rightSendBuf.size ()), 00262 rightNeighbor, tag3, *comm); 00263 00264 // Wait for the receives to complete. 00265 waitAll (*comm, requests (), statuses ()); 00266 00267 // Make sure the source ranks are correct. 00268 for (size_type k = 0; k < 2; ++k) { 00269 sourceRanks[k] = statuses[k]->getSourceRank (); 00270 } 00271 std::sort (sourceRanks.begin (), sourceRanks.end ()); 00272 TEST_EQUALITY( sourceRanks.size (), expectedSourceRanks.size () ); 00273 for (size_type k = 0; k < sourceRanks.size (); ++k) { 00274 TEST_EQUALITY( sourceRanks[k], expectedSourceRanks[k] ); 00275 } 00276 00277 // Make sure the source tags are correct. 00278 for (size_type k = 0; k < statuses.size (); ++k) { 00279 TEST_EQUALITY( statuses[k]->getTag (), tag3 ); 00280 } 00281 00282 // Make sure the message contents are correct. 00283 TEST_EQUALITY( leftRecvBuf[0], leftNeighbor + tag3 ); 00284 TEST_EQUALITY( rightRecvBuf[0], rightNeighbor + tag3 ); 00285 00287 // Final check 00289 out << "Final check" << endl; 00290 00291 // At this point, if we do a barrier, all the processes should reach 00292 // it. None should hang. If this test times out, it probably means 00293 // that not all the processes reached this point. 00294 comm->barrier (); 00295 out << "All processes successfully completed this test." << endl; 00296 } 00297 00298 00299 TEUCHOS_UNIT_TEST( MpiCommTag, IrecvIsend ) 00300 { 00301 typedef ArrayRCP<int>::size_type size_type; 00302 00303 RCP<const Comm<int> > comm = rcp (new MpiComm<int> (MPI_COMM_WORLD)); 00304 const int myRank = comm->getRank (); 00305 const int numProcs = comm->getSize (); 00306 00307 // If there is only one process, then the left and right neighbors 00308 // are the same, namely the calling process. MPI allows a process 00309 // to send to and receive from itself. On the other hand, we want 00310 // to test blocking sends, and we want to post two sends, so we only 00311 // allow > 1 processes. 00312 if (numProcs == 1) { 00313 out << "numProcs == 1, test passes trivially." << endl; 00314 return; 00315 } 00316 out << "Test setup" << endl; 00317 00318 // If there are only two processes, the left neighbor and the right 00319 // neighbor are the same, namely the other process. 00320 int leftNeighbor = (myRank - 1) % numProcs; 00321 int rightNeighbor = (myRank + 1) % numProcs; 00322 // C doesn't guarantee nonnegativity of the result of the % operator. 00323 if (leftNeighbor < 0) { 00324 leftNeighbor += numProcs; 00325 } 00326 if (rightNeighbor < 0) { 00327 rightNeighbor += numProcs; 00328 } 00329 Array<int> expectedSourceRanks (2); // expected source ranks for receives 00330 expectedSourceRanks[0] = leftNeighbor; 00331 expectedSourceRanks[1] = rightNeighbor; 00332 std::sort (expectedSourceRanks.begin (), expectedSourceRanks.end ()); 00333 00334 // Receive buffer, with subbuffers for each neighbor. 00335 ArrayRCP<int> recvBuf (2); 00336 ArrayRCP<int> leftRecvBuf = recvBuf.persistingView (0, 1); 00337 ArrayRCP<int> rightRecvBuf = recvBuf.persistingView (1, 1); 00338 00339 // Send buffer, with subbuffers for each neighbor. 00340 ArrayRCP<int> sendBuf (2); 00341 ArrayRCP<int> leftSendBuf = sendBuf.persistingView (0, 1); 00342 ArrayRCP<int> rightSendBuf = sendBuf.persistingView (1, 1); 00343 00344 // Requests for both nonblocking receives and nonblocking sends. 00345 Array<RCP<CommRequest<int> > > requests (4); 00346 // Statuses for both nonblocking receives and nonblocking sends. We 00347 // only use these to test that the ranks of the received messages 00348 // were correct. 00349 Array<RCP<CommStatus<int> > > statuses (4); 00350 00352 // First round of messages 00354 out << "Round 1 of messages" << endl; 00355 00356 // Tag to use for the first set of messages. 00357 const int tag1 = 101; 00358 00359 // Fill receive buffer with error flags. 00360 for (size_type k = 0; k < recvBuf.size (); ++k) { 00361 recvBuf[k] = -1; 00362 } 00363 00364 // Send my process rank plus the current tag to all neighbors. 00365 for (size_type k = 0; k < sendBuf.size (); ++k) { 00366 sendBuf[k] = myRank + tag1; 00367 } 00368 00369 // Post receives from left and right neighbors. 00370 requests[0] = ireceive<int, int> (leftRecvBuf, leftNeighbor, tag1, *comm); 00371 requests[1] = ireceive<int, int> (rightRecvBuf, rightNeighbor, tag1, *comm); 00372 00373 // Post sends to left and right neighbors. 00374 requests[2] = isend<int, int> (leftSendBuf, leftNeighbor, tag1, *comm); 00375 requests[3] = isend<int, int> (rightSendBuf, rightNeighbor, tag1, *comm); 00376 00377 // Wait for the receives to complete. 00378 waitAll (*comm, requests (), statuses ()); 00379 00380 // Make sure the source tags are correct. 00381 for (size_type k = 0; k < statuses.size (); ++k) { 00382 TEST_EQUALITY( statuses[k]->getTag (), tag1 ); 00383 } 00384 00385 // Make sure the message contents are correct. 00386 TEST_EQUALITY( leftRecvBuf[0], leftNeighbor + tag1 ); 00387 TEST_EQUALITY( rightRecvBuf[0], rightNeighbor + tag1 ); 00388 00390 // Second round of messages 00392 out << "Round 2 of messages" << endl; 00393 00394 // Tag to use for the second set of messages. 00395 const int tag2 = 202; 00396 00397 // Fill receive buffer with error flags. 00398 for (size_type k = 0; k < recvBuf.size (); ++k) { 00399 recvBuf[k] = -1; 00400 } 00401 00402 // Send my process rank plus the current tag to all neighbors. 00403 for (size_type k = 0; k < sendBuf.size (); ++k) { 00404 sendBuf[k] = myRank + tag2; 00405 } 00406 00407 // Post receives from left and right neighbors. 00408 requests[0] = ireceive<int, int> (leftRecvBuf, leftNeighbor, tag2, *comm); 00409 requests[1] = ireceive<int, int> (rightRecvBuf, rightNeighbor, tag2, *comm); 00410 00411 // Post sends to left and right neighbors. 00412 requests[2] = isend<int, int> (leftSendBuf, leftNeighbor, tag2, *comm); 00413 requests[3] = isend<int, int> (rightSendBuf, rightNeighbor, tag2, *comm); 00414 00415 // Wait for the receives to complete. 00416 waitAll (*comm, requests (), statuses ()); 00417 00418 // Make sure the source tags are correct. 00419 for (size_type k = 0; k < statuses.size (); ++k) { 00420 TEST_EQUALITY( statuses[k]->getTag (), tag2 ); 00421 } 00422 00423 // Make sure the message contents are correct. 00424 TEST_EQUALITY( leftRecvBuf[0], leftNeighbor + tag2 ); 00425 TEST_EQUALITY( rightRecvBuf[0], rightNeighbor + tag2 ); 00426 00428 // Third round of messages 00430 out << "Round 3 of messages" << endl; 00431 00432 // In this round, we try again with the first tag. This will tell 00433 // us if any first-round messages got mixed up with second-round 00434 // messages. 00435 const int tag3 = tag1; 00436 00437 // Fill receive buffer with error flags. 00438 for (size_type k = 0; k < recvBuf.size (); ++k) { 00439 recvBuf[k] = -1; 00440 } 00441 00442 // Send my process rank plus the current tag to all neighbors. 00443 for (size_type k = 0; k < sendBuf.size (); ++k) { 00444 sendBuf[k] = myRank + tag3; 00445 } 00446 00447 // Post receives from left and right neighbors. 00448 requests[0] = ireceive<int, int> (leftRecvBuf, leftNeighbor, tag3, *comm); 00449 requests[1] = ireceive<int, int> (rightRecvBuf, rightNeighbor, tag3, *comm); 00450 00451 // Post sends to left and right neighbors. 00452 requests[2] = isend<int, int> (leftSendBuf, leftNeighbor, tag3, *comm); 00453 requests[3] = isend<int, int> (rightSendBuf, rightNeighbor, tag3, *comm); 00454 00455 // Wait for the receives to complete. 00456 waitAll (*comm, requests (), statuses ()); 00457 00458 // Make sure the source tags are correct. 00459 for (size_type k = 0; k < statuses.size (); ++k) { 00460 TEST_EQUALITY( statuses[k]->getTag (), tag3 ); 00461 } 00462 00463 // Make sure the message contents are correct. 00464 TEST_EQUALITY( leftRecvBuf[0], leftNeighbor + tag3 ); 00465 TEST_EQUALITY( rightRecvBuf[0], rightNeighbor + tag3 ); 00466 00468 // Final check 00470 out << "Final check" << endl; 00471 00472 // At this point, if we do a barrier, all the processes should reach 00473 // it. None should hang. If this test times out, it probably means 00474 // that not all the processes reached this point. 00475 comm->barrier (); 00476 out << "All processes successfully completed this test." << endl; 00477 } 00478 00479 } // namespace
1.7.6.1