|
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 00046 00047 #include "Teuchos_DefaultSerialComm.hpp" 00048 #include "Teuchos_CommHelpers.hpp" 00049 #include "Teuchos_DefaultComm.hpp" 00050 #include "Teuchos_DefaultSerialComm.hpp" 00051 #include "Teuchos_getConst.hpp" 00052 #include "Teuchos_as.hpp" 00053 00054 #ifdef HAVE_TEUCHOS_QD 00055 #include <qd/dd_real.h> 00056 #endif 00057 00058 namespace std { 00059 00060 00061 template <typename Packet> 00062 ostream & operator<< ( ostream& os, const pair<Packet, Packet>& arg) 00063 { 00064 os << "(" << arg.first << "," << arg.second << ")"; 00065 return os; 00066 } 00067 00068 00069 } // namespace std 00070 00071 00072 namespace Teuchos { 00073 00074 00075 template<typename Packet> 00076 struct ScalarTraits<std::pair<Packet,Packet> > 00077 { 00078 typedef ScalarTraits<Packet> PST; 00079 typedef std::pair<typename PST::magnitudeType, typename PST::magnitudeType> magnitudeType; 00080 static const bool isComplex = PST::isComplex; 00081 static const bool isComparable = PST::isComparable; 00082 static const bool hasMachineParameters = PST::hasMachineParameters; 00083 // Not defined: eps(), sfmin(), base(), prec(), t(), rnd(), emin(), rmin(), emax(), rmax() 00084 static inline magnitudeType magnitude(std::pair<Packet,Packet> a) { return std::pair<Packet,Packet>( PST::magnitude(a.first), PST::magnitude(a.second) ); } 00085 static inline std::pair<Packet,Packet> zero() { return std::pair<Packet,Packet>(PST::zero(),PST::zero()); } 00086 static inline std::pair<Packet,Packet> one() { return std::pair<Packet,Packet>(PST::one(), PST::one()); } 00087 static inline std::pair<Packet,Packet> conjugate(std::pair<Packet,Packet> x) { return std::pair<Packet,Packet>(PST::conjugate(x.first), PST::conjugate(x.second) ); } 00088 static inline std::pair<Packet,Packet> real(std::pair<Packet,Packet> x) { return std::pair<Packet,Packet>(PST::real(x.first), PST::real(x.second) ); } 00089 static inline std::pair<Packet,Packet> imag(std::pair<Packet,Packet> x) { return std::pair<Packet,Packet>(PST::imag(x.first), PST::imag(x.second) ); } 00090 static inline bool isnaninf(std::pair<Packet,Packet> x) { return PST::isnaninf(x.first) || PST::isnaninf(x.second); } 00091 static inline void seedrandom(unsigned int s) { PST::seedrandom(s); } 00092 static inline std::pair<Packet,Packet> random() { return std::pair<Packet,Packet>( PST::random(), PST::random() ); } 00093 static inline std::string name() { return "std::pair<" + Teuchos::TypeNameTraits<Packet>::name() + "," + Teuchos::TypeNameTraits<Packet>::name() + ">"; } 00094 static inline std::pair<Packet,Packet> squareroot(std::pair<Packet,Packet> x) { return std::pair<Packet,Packet>(PST::squareroot(x.first), PST::squareroot(x.second)); } 00095 static inline std::pair<Packet,Packet> pow(std::pair<Packet,Packet> x, std::pair<Packet,Packet> y) { return std::pair<Packet,Packet>( PST::pow(x.first,y.first), PST::pow(x.second,y.second) ); } 00096 }; 00097 00098 template<class Packet, class ConvertToPacket> 00099 class ValueTypeConversionTraits<std::pair<Packet,Packet>, ConvertToPacket> { 00100 public: 00101 static std::pair<Packet,Packet> convert( const ConvertToPacket t ) 00102 { 00103 return std::pair<Packet,Packet>(t,t); 00104 } 00105 static std::pair<Packet,Packet> safeConvert( const ConvertToPacket t ) 00106 { 00107 return std::pair<Packet,Packet>(t,t); 00108 } 00109 }; 00110 00111 00112 } // namespace Teuchos 00113 00114 00115 namespace { 00116 00117 00118 using Teuchos::as; 00119 using Teuchos::RCP; 00120 using Teuchos::rcp; 00121 using Teuchos::Array; 00122 using Teuchos::Comm; 00123 using Teuchos::DefaultComm; 00124 using Teuchos::GlobalMPISession; 00125 using Teuchos::defaultSmallNumber; 00126 using Teuchos::outArg; 00127 00128 00129 bool testMpi = true; 00130 00131 00132 double errorTolSlack = 1e+1; 00133 00134 00135 00136 TEUCHOS_STATIC_SETUP() 00137 { 00138 00139 Teuchos::CommandLineProcessor &clp = Teuchos::UnitTestRepository::getCLP(); 00140 00141 clp.addOutputSetupOptions(true); 00142 00143 clp.setOption( 00144 "test-mpi", "test-serial", &testMpi, 00145 "Test MPI (if available) or force test of serial. In a serial build," 00146 " this option is ignored and a serial comm is always used." ); 00147 00148 clp.setOption( 00149 "error-tol-slack", &errorTolSlack, 00150 "Slack off of machine epsilon used to check test results" ); 00151 00152 } 00153 00154 00155 template<class Ordinal> 00156 RCP<const Comm<Ordinal> > getDefaultComm() 00157 { 00158 if (testMpi) { 00159 return DefaultComm<Ordinal>::getComm(); 00160 } 00161 return rcp(new Teuchos::SerialComm<Ordinal>); 00162 } 00163 00164 00165 TEUCHOS_UNIT_TEST_TEMPLATE_1_DECL( DefaultMpiComm, basic, Ordinal ) 00166 { 00167 RCP<const Comm<Ordinal> > comm = getDefaultComm<Ordinal>(); 00168 out << "comm = " << Teuchos::describe(*comm); 00169 TEST_EQUALITY( size(*comm), GlobalMPISession::getNProc() ); 00170 } 00171 00172 00173 TEUCHOS_UNIT_TEST_TEMPLATE_2_DECL( DefaultMpiComm, reduceAllAndScatter_1, Ordinal, Packet ) 00174 { 00175 00176 typedef Teuchos::ScalarTraits<Packet> PT; 00177 typedef typename PT::magnitudeType PacketMag; 00178 //typedef Teuchos::ScalarTraits<PacketMag> PMT; // unused 00179 00180 RCP<const Comm<Ordinal> > comm = getDefaultComm<Ordinal>(); 00181 const Ordinal numProcs = size(*comm); 00182 00183 #ifdef TEUCHOS_MPI_COMM_DUMP 00184 Teuchos::MpiComm<Ordinal>::show_dump = true; 00185 #endif 00186 00187 Array<Packet> sendBuffer(as<Ordinal>(numProcs)); 00188 for (Ordinal k = 0; k < numProcs; ++k) { 00189 sendBuffer[k] = as<Packet>(1); 00190 } 00191 00192 Array<Ordinal> recvCounts(as<Ordinal>(numProcs), as<Ordinal>(1)); 00193 00194 Array<Packet> myGlobalReducts(1); 00195 00196 Teuchos::reduceAllAndScatter<Ordinal,Packet>( 00197 *comm, Teuchos::REDUCE_SUM, 00198 as<Ordinal>(sendBuffer.size()), &sendBuffer[0], 00199 &recvCounts[0], &myGlobalReducts[0] 00200 ); 00201 00202 if (std::numeric_limits<Packet>::is_integer) { 00203 TEST_EQUALITY( myGlobalReducts[0], as<Packet>(numProcs) ); 00204 } 00205 else { 00206 const PacketMag local_errorTolSlack = static_cast<PacketMag>(errorTolSlack); 00207 TEST_FLOATING_EQUALITY( myGlobalReducts[0], as<Packet>(numProcs), 00208 as<PacketMag>(defaultSmallNumber<PacketMag>() * local_errorTolSlack / (double)numProcs) 00209 ); 00210 } 00211 00212 } 00213 00214 00215 TEUCHOS_UNIT_TEST_TEMPLATE_2_DECL( DefaultMpiComm, reduceAllAndScatter_2, Ordinal, Packet ) 00216 { 00217 00218 typedef Teuchos::ScalarTraits<Packet> PT; 00219 typedef typename PT::magnitudeType PacketMag; 00220 //typedef Teuchos::ScalarTraits<PacketMag> PMT; // unused 00221 00222 RCP<const Comm<Ordinal> > comm = getDefaultComm<Ordinal>(); 00223 const Ordinal numProcs = size(*comm); 00224 const Ordinal procRank = rank(*comm); 00225 00226 Array<Packet> sendBuffer(as<Ordinal>(numProcs)); 00227 for (Ordinal k = 0; k < numProcs; ++k) { 00228 sendBuffer[k] = as<Packet>(procRank + k); 00229 } 00230 00231 Array<Ordinal> recvCounts(as<Ordinal>(numProcs), as<Ordinal>(1)); 00232 00233 Array<Packet> myGlobalReducts(1); 00234 00235 Teuchos::reduceAllAndScatter<Ordinal,Packet>( 00236 *comm, Teuchos::REDUCE_SUM, 00237 as<Ordinal>(sendBuffer.size()), &sendBuffer[0], 00238 &recvCounts[0], &myGlobalReducts[0] 00239 ); 00240 00241 const Packet expectedMyGlobalReduct = as<Packet>( 00242 numProcs * procRank + ((numProcs - 1) * numProcs)/2 00243 ); 00244 00245 if (std::numeric_limits<Packet>::is_integer) { 00246 TEST_EQUALITY( myGlobalReducts[0], expectedMyGlobalReduct ); 00247 } 00248 else { 00249 const PacketMag local_errorTolSlack = static_cast<PacketMag>(errorTolSlack); 00250 TEST_FLOATING_EQUALITY( myGlobalReducts[0], expectedMyGlobalReduct, 00251 as<PacketMag>(defaultSmallNumber<PacketMag>() * local_errorTolSlack / (double)numProcs) 00252 ); 00253 } 00254 00255 } 00256 00257 00258 TEUCHOS_UNIT_TEST_TEMPLATE_2_DECL( DefaultMpiComm, ReadySend1, Ordinal, Packet ) 00259 { 00260 00261 using Teuchos::broadcast; 00262 using Teuchos::readySend; 00263 using Teuchos::wait; 00264 using Teuchos::as; 00265 using Teuchos::rcpFromRef; 00266 using Teuchos::outArg; 00267 using Teuchos::isend; 00268 using Teuchos::ireceive; 00269 using Teuchos::wait; 00270 using Teuchos::SerialComm; 00271 using Teuchos::is_null; 00272 using Teuchos::arcp; 00273 using Teuchos::arcpClone; 00274 using Teuchos::rcp_dynamic_cast; 00275 using Teuchos::ArrayRCP; 00276 using Teuchos::ptr; 00277 typedef Teuchos::ScalarTraits<Packet> PT; 00278 //typedef typename PT::magnitudeType PacketMag; // unused 00279 //typedef Teuchos::ScalarTraits<PacketMag> PMT; // unused 00280 00281 RCP<const Comm<Ordinal> > comm = getDefaultComm<Ordinal>(); 00282 const Ordinal numProcs = size(*comm); 00283 const Ordinal procRank = rank(*comm); 00284 00285 if ( 00286 numProcs == 1 00287 && 00288 !is_null(rcp_dynamic_cast<const SerialComm<Ordinal> >(comm)) 00289 ) 00290 { 00291 out << "\nThis is Teuchos::SerialComm which does not support readySend!\n"; 00292 return; // Pass! 00293 } 00294 00295 PT::seedrandom(as<unsigned int>(procRank)); 00296 Packet origSendData = PT::random(); 00297 Packet origRecvData = PT::random(); 00298 broadcast<Ordinal, Packet>( *comm, 0, outArg(origSendData) ); 00299 00300 Packet sendData = origSendData; 00301 Packet recvData = origRecvData; 00302 00303 RCP<Teuchos::CommRequest<Ordinal> > recvRequest; 00304 00305 // Post non-block receive on proc 0 00306 if (procRank == 0) { 00307 // Post non-blocking receive from proc n-1 00308 recvRequest = ireceive<Ordinal, Packet>( 00309 *comm, 00310 rcp(&recvData,false), 00311 numProcs-1 00312 ); 00313 } 00314 barrier(*comm); 00315 00316 if (procRank == numProcs-1) { 00317 // ready send from proc n-1 to proc 0 00318 // send data in sendData 00319 readySend<Ordinal, Packet>( 00320 *comm, 00321 sendData, 00322 0 00323 ); 00324 } 00325 barrier(*comm); 00326 00327 if (procRank == 0) { 00328 // wait for request on 0 00329 wait( *comm, outArg(recvRequest) ); 00330 } 00331 barrier(*comm); 00332 00333 // test that all procs have recvRequest == Teuchos::null 00334 TEST_EQUALITY_CONST( recvRequest, Teuchos::null ); 00335 00336 // proc 0 should have recvData == sendData 00337 if (procRank == 0) { 00338 TEST_EQUALITY( recvData, sendData ); 00339 } 00340 // other procs should have recvData == origRecvData (i.e., unchanged) 00341 else { 00342 TEST_EQUALITY( recvData, origRecvData ); 00343 } 00344 // all procs should have sendData == origSendData 00345 TEST_EQUALITY( sendData, origSendData ); 00346 00347 // All procs fail if any proc fails 00348 int globalSuccess_int = -1; 00349 reduceAll( *comm, Teuchos::REDUCE_SUM, success ? 0 : 1, outArg(globalSuccess_int) ); 00350 TEST_EQUALITY_CONST( globalSuccess_int, 0 ); 00351 } 00352 00353 00354 TEUCHOS_UNIT_TEST_TEMPLATE_2_DECL( DefaultMpiComm, ReadySend, Ordinal, Packet ) 00355 { 00356 00357 using Teuchos::broadcast; 00358 using Teuchos::readySend; 00359 using Teuchos::wait; 00360 using Teuchos::as; 00361 using Teuchos::rcpFromRef; 00362 using Teuchos::outArg; 00363 using Teuchos::isend; 00364 using Teuchos::ireceive; 00365 using Teuchos::wait; 00366 using Teuchos::SerialComm; 00367 using Teuchos::is_null; 00368 using Teuchos::arcp; 00369 using Teuchos::arcpClone; 00370 using Teuchos::rcp_dynamic_cast; 00371 using Teuchos::ArrayRCP; 00372 typedef Teuchos::ScalarTraits<Packet> PT; 00373 //typedef typename PT::magnitudeType PacketMag; // unused 00374 //typedef Teuchos::ScalarTraits<PacketMag> PMT; // unused 00375 00376 RCP<const Comm<Ordinal> > comm = getDefaultComm<Ordinal>(); 00377 const Ordinal numProcs = size(*comm); 00378 const Ordinal procRank = rank(*comm); 00379 00380 if ( 00381 numProcs == 1 00382 && 00383 !is_null(rcp_dynamic_cast<const SerialComm<Ordinal> >(comm)) 00384 ) 00385 { 00386 out << "\nThis is Teuchos::SerialComm which does not support readySend!\n"; 00387 return; // Pass! 00388 } 00389 00390 const int dataLen = 3; 00391 00392 const ArrayRCP<Packet> origSendData = arcp<Packet>(dataLen); 00393 const ArrayRCP<Packet> origRecvData = arcp<Packet>(dataLen); 00394 PT::seedrandom(as<unsigned int>(procRank)); 00395 for (int j = 0; j < dataLen; ++j) { 00396 origSendData[j] = PT::random(); 00397 origRecvData[j] = PT::random(); 00398 } 00399 broadcast<Ordinal, Packet>( *comm, 0, origSendData() ); 00400 00401 const ArrayRCP<Packet> sendData = arcpClone<Packet>(origSendData()); 00402 const ArrayRCP<Packet> recvData = arcpClone<Packet>(origRecvData()); 00403 00404 RCP<Teuchos::CommRequest<Ordinal> > recvRequest; 00405 00406 // both proc 0 and proc n-1 will post non-block receives, into recvData 00407 // then proc 0 will initiate a ready-send to proc n-1; the latter will initiate a wait 00408 // a barrier 00409 // then proc n-1 will initiate a ready-send to proc 0 of the data from recvData; the latter will initiate a wait 00410 // a barrier 00411 // now both of these procs should have matching data in sendData and recvData 00412 00413 // Post non-block receive on both procs 00414 if (procRank == 0) { 00415 // Post non-blocking receive from proc n-1 00416 recvRequest = ireceive<Ordinal, Packet>( 00417 *comm, 00418 recvData.persistingView(0, dataLen), 00419 numProcs-1 00420 ); 00421 } 00422 else if (procRank == numProcs-1) { 00423 // Post non-blocking receive from proc 0 00424 recvRequest = ireceive<Ordinal, Packet>( 00425 *comm, 00426 recvData.persistingView(0, dataLen), 00427 0 00428 ); 00429 } 00430 barrier(*comm); 00431 00432 if (procRank == 0) { 00433 // ready send from proc 0 to proc n-1 00434 // send data in sendData 00435 readySend<Ordinal, Packet>( 00436 *comm, 00437 sendData(), 00438 numProcs-1 00439 ); 00440 } 00441 else if (procRank == numProcs-1) { 00442 // wait for request on proc n-1 00443 wait( *comm, outArg(recvRequest) ); 00444 } 00445 barrier(*comm); 00446 00447 if (procRank == 0) { 00448 // wait for request on 0 00449 wait( *comm, outArg(recvRequest) ); 00450 } 00451 else if (procRank == numProcs-1) { 00452 // ready send from proc n-1 to proc 0 00453 // send data in recvData: THIS IS IMPORTANT: SEE ABOVE 00454 readySend<Ordinal, Packet>( 00455 *comm, 00456 recvData(), 00457 0 00458 ); 00459 } 00460 barrier(*comm); 00461 00462 // test that all procs (even non-participating) have recvRequest == Teuchos::null 00463 TEST_EQUALITY_CONST( recvRequest, Teuchos::null ); 00464 00465 // participating procs should have recvData == sendData 00466 if (procRank == 0 || procRank == numProcs-1) { 00467 TEST_COMPARE_ARRAYS( recvData, sendData ); 00468 } 00469 // non-participating procs should have recvData == origRecvData (i.e., unchanged) 00470 else { 00471 TEST_COMPARE_ARRAYS( recvData, origRecvData ); 00472 } 00473 // all procs should have sendData == origSendData 00474 TEST_COMPARE_ARRAYS( sendData, origSendData ); 00475 00476 // All procs fail if any proc fails 00477 int globalSuccess_int = -1; 00478 reduceAll( *comm, Teuchos::REDUCE_SUM, success ? 0 : 1, outArg(globalSuccess_int) ); 00479 TEST_EQUALITY_CONST( globalSuccess_int, 0 ); 00480 } 00481 00482 00483 TEUCHOS_UNIT_TEST_TEMPLATE_2_DECL( DefaultMpiComm, NonblockingSendReceive, Ordinal, Packet ) 00484 { 00485 using Teuchos::as; 00486 using Teuchos::rcpFromRef; 00487 using Teuchos::outArg; 00488 using Teuchos::isend; 00489 using Teuchos::ireceive; 00490 using Teuchos::wait; 00491 using Teuchos::SerialComm; 00492 using Teuchos::rcp_dynamic_cast; 00493 using std::endl; 00494 typedef Teuchos::ScalarTraits<Packet> PT; 00495 //typedef typename PT::magnitudeType PacketMag; // unused 00496 //typedef Teuchos::ScalarTraits<PacketMag> PMT; // unused 00497 00498 RCP<const Comm<Ordinal> > comm = getDefaultComm<Ordinal>(); 00499 const Ordinal numProcs = size(*comm); 00500 const Ordinal procRank = rank(*comm); 00501 00502 if ( 00503 numProcs == 1 00504 && 00505 !is_null(rcp_dynamic_cast<const SerialComm<Ordinal> >(comm)) 00506 ) 00507 { 00508 out << "\nThis is Teuchos::SerialComm which does not yet support isend/ireceive!\n"; 00509 return; // Pass! 00510 } 00511 00512 // Only use randomize on one proc and then broacast 00513 Packet orig_input_data = PT::random(); 00514 broadcast( *comm, 0, &orig_input_data ); 00515 00516 const Packet orig_output_data = as<Packet>(-1); 00517 00518 const Packet input_data = orig_input_data; 00519 Packet output_data = orig_output_data; 00520 00521 RCP<Teuchos::CommRequest<Ordinal> > recvRequest; 00522 RCP<Teuchos::CommRequest<Ordinal> > sendRequest; 00523 00524 out << "Exchanging messages" << endl; 00525 00526 if (procRank == 0) { 00527 // Create copy of data to make sure that persisting relationship is 00528 // maintained! 00529 sendRequest = isend<Ordinal, Packet>( 00530 *comm, Teuchos::rcp(new Packet(input_data)), numProcs-1); 00531 } 00532 if (procRank == numProcs-1) { 00533 // We will need to read output_data after wait(...) below 00534 recvRequest = ireceive<Ordinal, Packet>( 00535 *comm, rcpFromRef(output_data), 0); 00536 } 00537 00538 out << "Waiting for messages" << endl; 00539 00540 if (procRank == 0) { 00541 wait( *comm, outArg(sendRequest) ); 00542 } 00543 if (procRank == numProcs-1) { 00544 wait( *comm, outArg(recvRequest) ); 00545 } 00546 00547 TEST_EQUALITY_CONST( sendRequest, Teuchos::null ); 00548 TEST_EQUALITY_CONST( recvRequest, Teuchos::null ); 00549 00550 out << "Testing message correctness" << endl; 00551 00552 if (procRank == numProcs-1) { 00553 TEST_EQUALITY( output_data, input_data ); 00554 } 00555 else { 00556 TEST_EQUALITY( output_data, orig_output_data ); 00557 } 00558 TEST_EQUALITY( input_data, orig_input_data ); 00559 00560 // All procs fail if any proc fails 00561 int globalSuccess_int = -1; 00562 reduceAll( *comm, Teuchos::REDUCE_SUM, success ? 0 : 1, outArg(globalSuccess_int) ); 00563 TEST_EQUALITY_CONST( globalSuccess_int, 0 ); 00564 } 00565 00566 00567 TEUCHOS_UNIT_TEST_TEMPLATE_2_DECL( DefaultMpiComm, NonblockingSendReceiveSet, Ordinal, Packet ) 00568 { 00569 using Teuchos::as; 00570 using Teuchos::rcpFromRef; 00571 using Teuchos::outArg; 00572 using Teuchos::arcp; 00573 using Teuchos::arcpClone; 00574 using Teuchos::ArrayRCP; 00575 using Teuchos::isend; 00576 using Teuchos::ireceive; 00577 using Teuchos::wait; 00578 using Teuchos::broadcast; 00579 using Teuchos::SerialComm; 00580 using Teuchos::rcp_dynamic_cast; 00581 using std::cerr; 00582 using std::endl; 00583 typedef Teuchos::ScalarTraits<Packet> PT; 00584 //typedef typename PT::magnitudeType PacketMag; // unused 00585 //typedef Teuchos::ScalarTraits<PacketMag> PMT; // unused 00586 00587 RCP<const Comm<Ordinal> > comm = getDefaultComm<Ordinal>(); 00588 const Ordinal numProcs = size(*comm); 00589 const Ordinal procRank = rank(*comm); 00590 00591 if ( 00592 numProcs == 1 00593 && 00594 !is_null(rcp_dynamic_cast<const SerialComm<Ordinal> >(comm)) 00595 ) 00596 { 00597 out << "\nThis is Teuchos::SerialComm which does not yet support isend/ireceive!\n"; 00598 return; // Pass! 00599 } 00600 00601 const int numSendRecv = 4; 00602 const int sendLen = 3; 00603 00604 cerr << "Creating data" << endl; 00605 00606 const ArrayRCP<Packet> origInputData = arcp<Packet>(numSendRecv*sendLen); 00607 const ArrayRCP<Packet> origOutputData = arcp<Packet>(numSendRecv*sendLen); 00608 { 00609 int offset = 0; 00610 for (int i = 0; i < numSendRecv; ++i, offset += sendLen) { 00611 const ArrayRCP<Packet> origInputData_i = 00612 origInputData.persistingView(offset, sendLen); 00613 const ArrayRCP<Packet> origOutputData_i = 00614 origOutputData.persistingView(offset, sendLen); 00615 for (int j = 0; j < sendLen; ++j) { 00616 origInputData_i[j] = PT::random(); 00617 origOutputData_i[j] = PT::random(); 00618 } 00619 } 00620 } 00621 cerr << "Broadcasting data" << endl; 00622 broadcast<Ordinal, Packet>( *comm, 0, origInputData() ); 00623 00624 const ArrayRCP<Packet> inputData = arcpClone<Packet>(origInputData()); 00625 const ArrayRCP<Packet> outputData = arcpClone<Packet>(origOutputData()); 00626 00627 Array<RCP<Teuchos::CommRequest<Ordinal> > > recvRequests; 00628 Array<RCP<Teuchos::CommRequest<Ordinal> > > sendRequests; 00629 00630 cerr << "Exchanging data" << endl; 00631 00632 // Send from proc 0 to proc numProcs-1 00633 if (procRank == 0) { 00634 // Create copy of data to make sure that persisting relationship is 00635 // maintained! 00636 int offset = 0; 00637 for (int i = 0; i < numSendRecv; ++i, offset += sendLen) { 00638 sendRequests.push_back( 00639 isend<Ordinal, Packet>( 00640 *comm, 00641 arcpClone<Packet>(inputData(offset, sendLen)), 00642 numProcs-1 00643 ) 00644 ); 00645 } 00646 } 00647 00648 // Receive from proc 0 on proc numProcs-1 00649 if (procRank == numProcs-1) { 00650 // We will need to read output_data after wait(...) below 00651 int offset = 0; 00652 for (int i = 0; i < numSendRecv; ++i, offset += sendLen) { 00653 recvRequests.push_back( 00654 ireceive<Ordinal, Packet>( 00655 *comm, outputData.persistingView(offset, sendLen), 0 00656 ) 00657 ); 00658 } 00659 } 00660 00661 cerr << "Waiting on messages" << endl; 00662 00663 if (procRank == 0) { 00664 waitAll( *comm, sendRequests() ); 00665 } 00666 if (procRank == numProcs-1) { 00667 waitAll( *comm, recvRequests() ); 00668 } 00669 00670 cerr << "Testing received data" << endl; 00671 00672 if (!sendRequests.empty()) { 00673 for (int i = 0; i < numSendRecv; ++i) { 00674 TEST_EQUALITY_CONST( sendRequests[i], Teuchos::null ); 00675 } 00676 } 00677 00678 if (!recvRequests.empty()) { 00679 for (int i = 0; i < numSendRecv; ++i) { 00680 TEST_EQUALITY_CONST( recvRequests[i], Teuchos::null ); 00681 } 00682 } 00683 // ToDo: Write a test macro for this in one shot! 00684 00685 if (procRank == numProcs-1) { 00686 TEST_COMPARE_ARRAYS( outputData, inputData ); 00687 } 00688 else { 00689 TEST_COMPARE_ARRAYS( outputData, origOutputData ); 00690 } 00691 TEST_COMPARE_ARRAYS( inputData, origInputData ); 00692 00693 // All procs fail if any proc fails 00694 int globalSuccess_int = -1; 00695 reduceAll( *comm, Teuchos::REDUCE_SUM, success ? 0 : 1, outArg(globalSuccess_int) ); 00696 TEST_EQUALITY_CONST( globalSuccess_int, 0 ); 00697 00698 } 00699 00700 TEUCHOS_UNIT_TEST_TEMPLATE_1_DECL(DefaultMpiComm, duplicate, Ordinal) 00701 { 00702 RCP< const Comm<Ordinal> > comm = getDefaultComm<Ordinal>(); 00703 int initialRank = comm->getRank(); 00704 int initialSize = comm->getSize(); 00705 00706 RCP< const Comm<Ordinal> > newComm = comm->duplicate(); 00707 TEST_EQUALITY(newComm->getSize(), initialSize); 00708 TEST_EQUALITY(newComm->getRank(), initialRank); 00709 00710 // TODO Make sure the communication space is distinct. 00711 } 00712 00713 TEUCHOS_UNIT_TEST_TEMPLATE_1_DECL(DefaultMpiComm, split, Ordinal) { 00714 RCP< const Comm<Ordinal> > comm = getDefaultComm<Ordinal>(); 00715 int initialRank = comm->getRank(); 00716 int initialSize = comm->getSize(); 00717 00718 // Partition this communicator into two: one with the odd ranks and one with 00719 // the even ones. Pass a common key for everyone to maintain the same 00720 // ordering as in the initial communicator. 00721 RCP< const Comm<Ordinal> > newComm = comm->split(initialRank % 2, 0); 00722 00723 // Check the size of the new communicator and my rank within it. 00724 int halfSize = initialSize / 2; 00725 int newSize = newComm->getSize(); 00726 int newRank = newComm->getRank(); 00727 if (initialSize % 2 == 0) { 00728 TEST_EQUALITY(newSize, halfSize); 00729 } 00730 else { 00731 TEST_EQUALITY(newSize, initialRank % 2 == 0 ? halfSize + 1 : halfSize); 00732 } 00733 TEST_EQUALITY(newRank, initialRank / 2); 00734 00735 // Negative color values get a null communicator. 00736 RCP< const Comm<Ordinal> > shouldBeNull = comm->split(-1, 0); 00737 TEST_ASSERT(shouldBeNull.is_null()); 00738 } 00739 00740 00741 namespace { 00742 00743 00744 template<typename ValueType> 00745 class MonotoneSequence 00746 { 00747 ValueType currentValue_; 00748 public: 00749 typedef ValueType value_type; 00750 00751 MonotoneSequence(const value_type& initialValue) : currentValue_(initialValue) 00752 {} 00753 00754 value_type operator()() 00755 { 00756 return currentValue_++; 00757 } 00758 }; 00759 00760 00761 } // namepsace 00762 00763 00764 TEUCHOS_UNIT_TEST_TEMPLATE_1_DECL(DefaultMpiComm, createSubcommunicator, Ordinal) { 00765 RCP< const Comm<Ordinal> > comm = getDefaultComm<Ordinal>(); 00766 int initialRank = comm->getRank(); 00767 int initialSize = comm->getSize(); 00768 00769 // Create a new communicator that reverses all of the ranks. 00770 std::vector< int > ranks(initialSize); 00771 std::generate(ranks.begin(), ranks.end(), MonotoneSequence<int>(0)); 00772 std::reverse(ranks.begin(), ranks.end()); 00773 RCP< const Comm<Ordinal> > newComm = comm->createSubcommunicator(ranks); 00774 TEST_EQUALITY(newComm->getSize(), initialSize); 00775 int expectedNewRank = initialSize - initialRank - 1; 00776 TEST_EQUALITY(newComm->getRank(), expectedNewRank); 00777 00778 // Processes that aren't in the group get a null communicator. 00779 std::vector<int> rank0Only(1, 0); 00780 RCP< const Comm<Ordinal> > rank0Comm = comm->createSubcommunicator(rank0Only); 00781 // Original rank 0 should be valid, all others should be null. 00782 if (initialRank == 0) { 00783 TEST_ASSERT(rank0Comm.is_valid_ptr()); 00784 } else { 00785 TEST_ASSERT(rank0Comm.is_null()); 00786 } 00787 } 00788 00789 00790 #ifdef HAVE_TEUCHOS_MPI 00791 00792 00793 TEUCHOS_UNIT_TEST(DefaultMpiComm, TagConsistency ) 00794 { 00795 using Teuchos::tuple; using Teuchos::inoutArg; 00796 00797 const Teuchos::RCP<const Teuchos::Comm<int> > defaultComm = 00798 Teuchos::DefaultComm<int>::getComm(); 00799 const int comm_size = defaultComm->getSize(); 00800 const int comm_rank = defaultComm->getRank(); 00801 00802 // Must have at least two processes to run this test! 00803 if (comm_size < 2) { 00804 return; 00805 } 00806 00807 // Create a subcomm that contains just two processes 00808 const Teuchos::RCP<const Teuchos::Comm<int> > masterComm = 00809 defaultComm->createSubcommunicator(tuple<int>(0, 1)()); 00810 00811 if (comm_rank <= 1) { 00812 00813 const int masterComm_size = masterComm->getSize(); 00814 (void) masterComm_size; // Forestall "unused variable" warning. 00815 const int masterComm_rank = masterComm->getRank(); 00816 00817 // Split the main communicator into 2 overlapping groups 00818 Teuchos::RCP<const Teuchos::Comm<int> > comm_1 = 00819 masterComm->createSubcommunicator(tuple<int>(0, 1)()); 00820 Teuchos::RCP<const Teuchos::Comm<int> > comm_2 = 00821 masterComm->createSubcommunicator(tuple<int>(0)()); 00822 00823 // Create another communicator. 00824 Teuchos::RCP<const Teuchos::Comm<int> > comm_3 = 00825 masterComm->createSubcommunicator(tuple<int>(0, 1)()); 00826 00827 // Get my mpi tag for comm 3. 00828 int my_tag = Teuchos::rcp_dynamic_cast<const Teuchos::MpiComm<int> >( 00829 comm_3 )->getTag(); 00830 00831 // Collect the tags for comm 3. 00832 int tag1 = 0; 00833 if (masterComm_rank == 0) { tag1 = my_tag; } 00834 masterComm->barrier(); 00835 Teuchos::broadcast( *masterComm, 0, inoutArg(tag1) ); 00836 00837 int tag2 = 0; 00838 if (masterComm_rank == 1) { tag2 = my_tag; } 00839 masterComm->barrier(); 00840 Teuchos::broadcast( *masterComm, 1, inoutArg(tag2) ); 00841 00842 // This currently fails. 00843 TEST_EQUALITY( tag1, tag2 ); 00844 00845 } 00846 00847 } 00848 00849 00850 #endif // HAVE_TEUCHOS_MPI 00851 00852 00853 // 00854 // Instantiations 00855 // 00856 00857 00858 #ifdef HAVE_TEUCHOS_COMPLEX 00859 # define UNIT_TEST_TEMPLATE_2_INSTANT_COMPLEX_FLOAT(TEST_GROUP, TEST_NAME, ORDINAL)\ 00860 typedef std::complex<float> ComplexFloat; \ 00861 TEUCHOS_UNIT_TEST_TEMPLATE_2_INSTANT(TEST_GROUP, TEST_NAME, ORDINAL, ComplexFloat) 00862 # define UNIT_TEST_TEMPLATE_2_INSTANT_COMPLEX_DOUBLE(TEST_GROUP, TEST_NAME, ORDINAL)\ 00863 typedef std::complex<double> ComplexDouble; \ 00864 TEUCHOS_UNIT_TEST_TEMPLATE_2_INSTANT(TEST_GROUP, TEST_NAME, ORDINAL, ComplexDouble) 00865 #else 00866 # define UNIT_TEST_TEMPLATE_2_INSTANT_COMPLEX_FLOAT(TEST_GROUP, TEST_NAME, ORDINAL) 00867 # define UNIT_TEST_TEMPLATE_2_INSTANT_COMPLEX_DOUBLE(TEST_GROUP, TEST_NAME, ORDINAL) 00868 #endif 00869 00870 00871 #define UNIT_TEST_GROUP_ORDINAL_PACKET( ORDINAL, PACKET ) \ 00872 TEUCHOS_UNIT_TEST_TEMPLATE_2_INSTANT( DefaultMpiComm, reduceAllAndScatter_1, ORDINAL, PACKET ) \ 00873 TEUCHOS_UNIT_TEST_TEMPLATE_2_INSTANT( DefaultMpiComm, reduceAllAndScatter_2, ORDINAL, PACKET ) \ 00874 TEUCHOS_UNIT_TEST_TEMPLATE_2_INSTANT( DefaultMpiComm, NonblockingSendReceive, ORDINAL, PACKET ) \ 00875 TEUCHOS_UNIT_TEST_TEMPLATE_2_INSTANT( DefaultMpiComm, NonblockingSendReceiveSet, ORDINAL, PACKET ) \ 00876 TEUCHOS_UNIT_TEST_TEMPLATE_2_INSTANT( DefaultMpiComm, ReadySend1, ORDINAL, PACKET ) \ 00877 TEUCHOS_UNIT_TEST_TEMPLATE_2_INSTANT( DefaultMpiComm, ReadySend, ORDINAL, PACKET ) 00878 00879 #ifdef HAVE_TEUCHOS_QD 00880 # define UNIT_TEST_GROUP_ORDINAL_QD(ORDINAL) \ 00881 UNIT_TEST_GROUP_ORDINAL_PACKET(ORDINAL, dd_real) \ 00882 UNIT_TEST_GROUP_ORDINAL_PACKET(ORDINAL, qd_real) 00883 #else 00884 # define UNIT_TEST_GROUP_ORDINAL_QD(ORDINAL) 00885 #endif 00886 00887 #define UNIT_TEST_GROUP_ORDINAL_PAIROFPACKETS( ORDINAL, PAIROFPACKETS ) \ 00888 TEUCHOS_UNIT_TEST_TEMPLATE_2_INSTANT( DefaultMpiComm, NonblockingSendReceive, ORDINAL, PAIROFPACKETS ) \ 00889 TEUCHOS_UNIT_TEST_TEMPLATE_2_INSTANT( DefaultMpiComm, NonblockingSendReceiveSet, ORDINAL, PAIROFPACKETS ) \ 00890 TEUCHOS_UNIT_TEST_TEMPLATE_2_INSTANT( DefaultMpiComm, ReadySend1, ORDINAL, PAIROFPACKETS ) \ 00891 TEUCHOS_UNIT_TEST_TEMPLATE_2_INSTANT( DefaultMpiComm, ReadySend, ORDINAL, PAIROFPACKETS ) 00892 00893 #define UNIT_TEST_GROUP_ORDINAL_SUBCOMMUNICATORS( ORDINAL ) \ 00894 TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( DefaultMpiComm, duplicate, ORDINAL ) \ 00895 TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( DefaultMpiComm, split, ORDINAL ) \ 00896 TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( DefaultMpiComm, createSubcommunicator, ORDINAL ) 00897 00898 00899 typedef std::pair<short, short> PairOfShorts; 00900 typedef std::pair<int,int> PairOfInts; 00901 typedef std::pair<float,float> PairOfFloats; 00902 typedef std::pair<double,double> PairOfDoubles; 00903 00904 00905 // Uncomment this for really fast development cycles but make sure to comment 00906 // it back again before checking in so that we can test all the types. 00907 // #define FAST_DEVELOPMENT_UNIT_TEST_BUILD 00908 00909 00910 #ifdef FAST_DEVELOPMENT_UNIT_TEST_BUILD 00911 00912 # define UNIT_TEST_GROUP_ORDINAL( ORDINAL ) \ 00913 UNIT_TEST_GROUP_ORDINAL_PACKET(ORDINAL, double) \ 00914 UNIT_TEST_GROUP_ORDINAL_PAIROFPACKETS(ORDINAL, PairOfDoubles) \ 00915 00916 UNIT_TEST_GROUP_ORDINAL(int) 00917 00918 #else // FAST_DEVELOPMENT_UNIT_TEST_BUILD 00919 00920 # define UNIT_TEST_GROUP_ORDINAL( ORDINAL ) \ 00921 TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( DefaultMpiComm, basic, ORDINAL ) \ 00922 UNIT_TEST_GROUP_ORDINAL_PACKET(ORDINAL, short) \ 00923 UNIT_TEST_GROUP_ORDINAL_PACKET(ORDINAL, int) \ 00924 UNIT_TEST_GROUP_ORDINAL_PACKET(ORDINAL, float) \ 00925 UNIT_TEST_GROUP_ORDINAL_PACKET(ORDINAL, double) \ 00926 UNIT_TEST_TEMPLATE_2_INSTANT_COMPLEX_FLOAT(DefaultMpiComm, reduceAllAndScatter_1, ORDINAL) \ 00927 UNIT_TEST_TEMPLATE_2_INSTANT_COMPLEX_FLOAT(DefaultMpiComm, reduceAllAndScatter_2, ORDINAL) \ 00928 UNIT_TEST_TEMPLATE_2_INSTANT_COMPLEX_FLOAT(DefaultMpiComm, NonblockingSendReceive, ORDINAL) \ 00929 UNIT_TEST_TEMPLATE_2_INSTANT_COMPLEX_FLOAT(DefaultMpiComm, ReadySend1, ORDINAL) \ 00930 UNIT_TEST_TEMPLATE_2_INSTANT_COMPLEX_FLOAT(DefaultMpiComm, ReadySend, ORDINAL) \ 00931 UNIT_TEST_TEMPLATE_2_INSTANT_COMPLEX_DOUBLE(DefaultMpiComm, reduceAllAndScatter_1, ORDINAL) \ 00932 UNIT_TEST_TEMPLATE_2_INSTANT_COMPLEX_DOUBLE(DefaultMpiComm, reduceAllAndScatter_2, ORDINAL) \ 00933 UNIT_TEST_TEMPLATE_2_INSTANT_COMPLEX_DOUBLE(DefaultMpiComm, NonblockingSendReceive, ORDINAL) \ 00934 UNIT_TEST_TEMPLATE_2_INSTANT_COMPLEX_DOUBLE(DefaultMpiComm, ReadySend1, ORDINAL) \ 00935 UNIT_TEST_TEMPLATE_2_INSTANT_COMPLEX_DOUBLE(DefaultMpiComm, ReadySend, ORDINAL) \ 00936 UNIT_TEST_GROUP_ORDINAL_SUBCOMMUNICATORS(ORDINAL) 00937 00938 # define UNIT_TEST_GROUP_ORDINAL_WITH_PAIRS_AND_QD( ORDINAL ) \ 00939 TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( DefaultMpiComm, basic, ORDINAL ) \ 00940 UNIT_TEST_GROUP_ORDINAL_PACKET(ORDINAL, short) \ 00941 UNIT_TEST_GROUP_ORDINAL_PACKET(ORDINAL, int) \ 00942 UNIT_TEST_GROUP_ORDINAL_PACKET(ORDINAL, float) \ 00943 UNIT_TEST_GROUP_ORDINAL_PACKET(ORDINAL, double) \ 00944 UNIT_TEST_GROUP_ORDINAL_QD(ORDINAL) \ 00945 UNIT_TEST_GROUP_ORDINAL_PAIROFPACKETS(ORDINAL, PairOfShorts) \ 00946 UNIT_TEST_GROUP_ORDINAL_PAIROFPACKETS(ORDINAL, PairOfInts) \ 00947 UNIT_TEST_GROUP_ORDINAL_PAIROFPACKETS(ORDINAL, PairOfFloats) \ 00948 UNIT_TEST_GROUP_ORDINAL_PAIROFPACKETS(ORDINAL, PairOfDoubles) \ 00949 UNIT_TEST_TEMPLATE_2_INSTANT_COMPLEX_FLOAT(DefaultMpiComm, reduceAllAndScatter_1, ORDINAL) \ 00950 UNIT_TEST_TEMPLATE_2_INSTANT_COMPLEX_FLOAT(DefaultMpiComm, reduceAllAndScatter_2, ORDINAL) \ 00951 UNIT_TEST_TEMPLATE_2_INSTANT_COMPLEX_FLOAT(DefaultMpiComm, NonblockingSendReceive, ORDINAL) \ 00952 UNIT_TEST_TEMPLATE_2_INSTANT_COMPLEX_FLOAT(DefaultMpiComm, ReadySend1, ORDINAL) \ 00953 UNIT_TEST_TEMPLATE_2_INSTANT_COMPLEX_FLOAT(DefaultMpiComm, ReadySend, ORDINAL) \ 00954 UNIT_TEST_TEMPLATE_2_INSTANT_COMPLEX_DOUBLE(DefaultMpiComm, reduceAllAndScatter_1, ORDINAL) \ 00955 UNIT_TEST_TEMPLATE_2_INSTANT_COMPLEX_DOUBLE(DefaultMpiComm, reduceAllAndScatter_2, ORDINAL) \ 00956 UNIT_TEST_TEMPLATE_2_INSTANT_COMPLEX_DOUBLE(DefaultMpiComm, NonblockingSendReceive, ORDINAL) \ 00957 UNIT_TEST_TEMPLATE_2_INSTANT_COMPLEX_DOUBLE(DefaultMpiComm, ReadySend1, ORDINAL) \ 00958 UNIT_TEST_TEMPLATE_2_INSTANT_COMPLEX_DOUBLE(DefaultMpiComm, ReadySend, ORDINAL) 00959 00960 typedef short int ShortInt; 00961 UNIT_TEST_GROUP_ORDINAL(ShortInt) 00962 UNIT_TEST_GROUP_ORDINAL_WITH_PAIRS_AND_QD(int) 00963 typedef long int LongInt; 00964 UNIT_TEST_GROUP_ORDINAL(LongInt) // can't do QD with LongInt, one of the tests complains 00965 00966 # ifdef HAVE_TEUCHOS_LONG_LONG_INT 00967 typedef long long int LongLongInt; 00968 UNIT_TEST_GROUP_ORDINAL(LongLongInt) 00969 # endif 00970 00971 #endif // FAST_DEVELOPMENT_UNIT_TEST_BUILD 00972 00973 00974 } // namespace
1.7.6.1