|
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_CommHelpers.hpp" 00045 #include "Teuchos_DefaultComm.hpp" 00046 #include "Teuchos_VerboseObject.hpp" 00047 #include "Teuchos_StandardCatchMacros.hpp" 00048 #include "Teuchos_GlobalMPISession.hpp" 00049 #include "Teuchos_CommandLineProcessor.hpp" 00050 #include "Teuchos_Version.hpp" 00051 #include "Teuchos_ScalarTraits.hpp" 00052 #include "Teuchos_OrdinalTraits.hpp" 00053 #include "Teuchos_TimeMonitor.hpp" 00054 #include "Teuchos_as.hpp" 00055 00056 00057 // 00058 // Unit test for Teuchos::Comm 00059 // 00060 00061 template<typename Ordinal> 00062 bool checkSumResult( 00063 const Teuchos::Comm<Ordinal> &comm, 00064 const Teuchos::RCP<Teuchos::FancyOStream> &out, 00065 const bool result 00066 ) 00067 { 00068 *out << "\nChecking that the above test passed in all processes ..."; 00069 int thisResult = ( result ? 1 : 0 ); 00070 int sumResult = -1; 00071 reduceAll(comm,Teuchos::REDUCE_SUM,Ordinal(1),&thisResult,&sumResult); 00072 const bool passed = sumResult==size(comm); 00073 if(passed) 00074 *out << " passed\n"; 00075 else 00076 *out << " (sumResult="<<sumResult<<"!=numProcs) failed\n"; 00077 return passed; 00078 } 00079 00080 00081 template<typename Ordinal, typename Packet> 00082 bool testComm( 00083 const Teuchos::Comm<Ordinal> &comm, 00084 const Teuchos::RCP<Teuchos::FancyOStream> &out 00085 ) 00086 { 00087 using Teuchos::RCP; 00088 using Teuchos::rcp; 00089 using Teuchos::FancyOStream; 00090 using Teuchos::VerboseObjectBase; 00091 using Teuchos::OSTab; 00092 using Teuchos::dyn_cast; 00093 using Teuchos::as; 00094 00095 typedef Teuchos::ScalarTraits<Packet> ST; 00096 typedef Teuchos::OrdinalTraits<Ordinal> OT; 00097 00098 OSTab tab(out); 00099 00100 bool success = true, result; 00101 00102 *out 00103 << "\n***" 00104 << "\n*** testComm<"<<OT::name()<<","<<ST::name()<<">(...)" 00105 << "\n***\n"; 00106 00107 *out << "\nTesting Comm = " << comm.description() << "\n"; 00108 00109 const int procRank = rank(comm); 00110 const int numProcs = size(comm); 00111 00112 *out 00113 << "\nnumProcs = size(comm) = " << numProcs << "\n" 00114 << "\nprocRank = rank(comm) = " << procRank << "\n"; 00115 00116 const Ordinal count = numProcs*2; 00117 00118 Teuchos::Array<Packet> sendBuff(count), recvBuff(count), recvBuff2(count); 00119 for( int i = 0; i < count; ++i ) 00120 sendBuff[i] = Packet(procRank+1)*Packet(i); 00121 00122 // 00123 // send/receive 00124 // 00125 00126 if(numProcs > 1) { 00127 00128 #ifdef TEUCHOS_MPI_COMM_DUMP 00129 Teuchos::MpiComm<Ordinal>::show_dump = true; 00130 #endif 00131 00132 if(procRank==numProcs-1) { 00133 *out << "\nSending data from p="<<procRank<<" to the root process (see p=0 output!) ...\n"; 00134 send(comm,count,&sendBuff[0],0); 00135 } 00136 00137 if(procRank==0) { 00138 *out << "\nReceiving data specifically from p="<<numProcs-1<<" ...\n"; 00139 std::fill_n(&recvBuff[0],count,Packet(0)); 00140 const int sourceRank = receive(comm,numProcs-1,count,&recvBuff[0]); 00141 result = sourceRank ==numProcs-1; 00142 *out 00143 << "\nChecking that sourceRank="<<sourceRank<<" == numProcs-1="<<(numProcs-1) 00144 << " : " << (result ? "passed" : "falied" ) << "\n"; 00145 *out << "\nChecking that recvBuffer[] == numProcs * sendBuffer[] ..."; 00146 result = true; 00147 for( int i = 0; i < count; ++i ) { 00148 const Packet expected = Packet(numProcs)*sendBuff[i]; 00149 if( recvBuff[i] != expected ) { 00150 result = false; 00151 *out 00152 << "\n recvBuffer["<<i<<"]="<<recvBuff[i] 00153 << " == numProcs*sendBuffer["<<i<<"]="<<expected<<" : failed"; 00154 } 00155 } 00156 if(result) { 00157 *out << " passed\n"; 00158 } 00159 else { 00160 *out << "\n"; 00161 success = false; 00162 } 00163 } 00164 00165 #ifdef TEUCHOS_MPI_COMM_DUMP 00166 Teuchos::MpiComm<Ordinal>::show_dump = false; 00167 #endif 00168 00169 } 00170 00171 00172 // 00173 // broadcast/reduceAll(sum) 00174 // 00175 00176 if(procRank==0) { 00177 std::copy(&sendBuff[0],&sendBuff[0]+count,&recvBuff[0]); 00178 *out << "\nSending broadcast of data from sendBuff[] in root process to recvBuff[] in each process ...\n"; 00179 } 00180 else { 00181 std::fill_n(&recvBuff[0],count,Packet(0)); 00182 *out << "\nReceiving broadcast of data from root process into recvBuff[] ...\n"; 00183 } 00184 00185 broadcast(comm,0,count,&recvBuff[0]); 00186 00187 *out << "\nSumming broadcasted data recvBuff[] over all processes into recvBuff2[] ...\n"; 00188 00189 reduceAll(comm,Teuchos::REDUCE_SUM,count,&recvBuff[0],&recvBuff2[0]); 00190 00191 *out << "\nChecking that recvBuff2[i] == numProcs * i ..."; 00192 result = true; 00193 for( int i = 0; i < count; ++i ) { 00194 const Packet expected = Packet(numProcs)*Packet(i); 00195 //*out << "\nexpected["<<i<<"]=numProcs*i="<<Packet(numProcs)<<"*"<<Packet(i)<<"="<<expected<<"\n"; 00196 if( recvBuff2[i] != expected ) { 00197 result = false; 00198 *out 00199 << "\n recvBuffer2["<<i<<"]="<<recvBuff2[i] 00200 << " == numProcs*"<<i<<"="<<expected<<" : failed"; 00201 } 00202 } 00203 if(result) { 00204 *out << " passed\n"; 00205 } 00206 else { 00207 *out << "\n"; 00208 success = false; 00209 } 00210 00211 result = checkSumResult(comm,out,result); 00212 if(!result) success = false; 00213 00214 // 00215 // reduceAll(min) 00216 // 00217 00218 if( ST::isComparable ) { 00219 00220 *out << "\nTaking min of sendBuff[] and putting it in recvBuff[] ...\n"; 00221 00222 reduceAll(comm,Teuchos::REDUCE_MIN,count,&sendBuff[0],&recvBuff[0]); 00223 00224 *out << "\nChecking that recvBuff[i] == i ..."; 00225 result = true; 00226 for( int i = 0; i < count; ++i ) { 00227 const Packet expected = Packet(i); 00228 //*out << "\nexpected["<<i<<"]=numProcs*i="<<Packet(numProcs)<<"*"<<Packet(i)<<"="<<expected<<"\n"; 00229 if( recvBuff[i] != expected ) { 00230 result = false; 00231 *out 00232 << "\n recvBuffer["<<i<<"]="<<recvBuff[i] 00233 << " == "<<i<<"="<<expected<<" : failed"; 00234 } 00235 } 00236 if(result) { 00237 *out << " passed\n"; 00238 } 00239 else { 00240 *out << "\n"; 00241 success = false; 00242 } 00243 00244 result = checkSumResult(comm,out,result); 00245 if(!result) success = false; 00246 00247 } 00248 00249 // 00250 // reduceAll(max) 00251 // 00252 00253 if( ST::isComparable ) { 00254 00255 *out << "\nTaking max of sendBuff[] and putting it in recvBuff[] ...\n"; 00256 00257 reduceAll(comm,Teuchos::REDUCE_MAX,count,&sendBuff[0],&recvBuff[0]); 00258 00259 *out << "\nChecking that recvBuff[i] == numProcs*i ..."; 00260 result = true; 00261 for( int i = 0; i < count; ++i ) { 00262 const Packet expected = Packet(numProcs)*Packet(i); 00263 //*out << "\nexpected["<<i<<"]=numProcs*i="<<Packet(numProcs)<<"*"<<Packet(i)<<"="<<expected<<"\n"; 00264 if( recvBuff[i] != expected ) { 00265 result = false; 00266 *out 00267 << "\n recvBuffer["<<i<<"]="<<recvBuff[i] 00268 << " == numProcs*"<<i<<"="<<expected<<" : failed"; 00269 } 00270 } 00271 if(result) { 00272 *out << " passed\n"; 00273 } 00274 else { 00275 *out << "\n"; 00276 success = false; 00277 } 00278 00279 result = checkSumResult(comm,out,result); 00280 if(!result) success = false; 00281 00282 } 00283 00284 // 00285 // gatherAll 00286 // 00287 00288 *out << "\nGathering all data from sendBuff[] in each process to all processes to allRecvBuff ...\n"; 00289 00290 Teuchos::Array<Packet> 00291 allRecvBuff(count*numProcs); 00292 00293 gatherAll(comm,count,&sendBuff[0],Ordinal(allRecvBuff.size()),&allRecvBuff[0]); 00294 00295 *out << "\nChecking that allRecvBuff[count*k+i] == (k+1) * i ..."; 00296 result = true; 00297 for( int k = 0; k < numProcs; ++k ) { 00298 for( int i = 0; i < count; ++i ) { 00299 const Packet expected = Packet(k+1)*Packet(i); 00300 if( allRecvBuff[count*k+i] != expected ) { 00301 result = false; 00302 *out 00303 << "\n allRecvBuff["<<count<<"*"<<k<<"+"<<i<<"]="<<allRecvBuff[count*k+i] 00304 << " == (k+1)*i="<<expected<<" : failed"; 00305 } 00306 } 00307 } 00308 if(result) { 00309 *out << " passed\n"; 00310 } 00311 else { 00312 *out << "\n"; 00313 success = false; 00314 } 00315 00316 result = checkSumResult(comm,out,result); 00317 if(!result) success = false; 00318 00319 // 00320 // scan 00321 // 00322 00323 *out << "\nPerforming a scan sum of sendBuff[] into recvBuff[] ...\n"; 00324 00325 std::fill_n(&recvBuff[0],count,Packet(0)); 00326 00327 scan(comm,Teuchos::REDUCE_SUM,count,&sendBuff[0],&recvBuff[0]); 00328 00329 *out << "\nChecking that recvBuff[i] == sum(k+1,k=0...procRank) * i ..."; 00330 result = true; 00331 int sumProcRank = 0; 00332 for( int k = 0; k <= procRank; ++k ) sumProcRank += (k+1); 00333 for( int i = 0; i < count; ++i ) { 00334 const Packet expected = Packet(sumProcRank)*Packet(i); 00335 //*out << "\nexpected["<<i<<"]=sum(k+1,k=0...procRank)*i="<<Packet(sumProcRank)<<"*"<<Packet(i)<<"="<<expected<<"\n"; 00336 if( recvBuff[i] != expected ) { 00337 result = false; 00338 *out 00339 << "\n recvBuffer["<<i<<"]="<<recvBuff[i] 00340 << " == sum(k+1,k=0...procRank)*"<<i<<"="<<expected<<" : failed"; 00341 } 00342 } 00343 if(result) { 00344 *out << " passed\n"; 00345 } 00346 else { 00347 *out << "\n"; 00348 success = false; 00349 } 00350 00351 result = checkSumResult(comm,out,result); 00352 if(!result) success = false; 00353 00354 // 00355 // reduceAllAndScatter(...) 00356 // 00357 00358 *out << "\nReducing/summing sendBuff[] and scattering into recvBuff[] ...\n"; 00359 00360 // there are count items in sendbuff the intermediate reduction operation 00361 // will result in a vector of length count each process will recieve 00362 // numItemsPerProcess == count/numProcs == numProcs*2/numProcs == 2 of this 00363 // intermediate reduction 00364 const Ordinal numItemsPerProcess = count/numProcs; 00365 Teuchos::Array<Ordinal> recvCounts(numProcs); 00366 // fill recvCounts with {2,...,2} 00367 std::fill(recvCounts.begin(), recvCounts.end(), numItemsPerProcess); 00368 // initialize recieve buffer to zero 00369 std::fill(recvBuff.begin(),recvBuff.end(),as<Packet>(0)); 00370 00371 reduceAllAndScatter( 00372 comm, Teuchos::REDUCE_SUM, 00373 count, &sendBuff[0], &recvCounts[0], &recvBuff[0] 00374 ); 00375 00376 /* on proc rank, sendBuff[i] == (rank+1)*i 00377 after REDUCE_SUM, 00378 sendBuff[i] == \sum_k (k+1)*i 00379 == i*\sum_k (k+1) 00380 == i*(1+2+...+numProcs) 00381 == i*numProcs*(numProcs+1)/2 00382 */ 00383 *out << "\nChecking that recvBuff[i] == sum(k+1,k=0...numProcs-1) * (offset+i) ..."; 00384 result = true; 00385 int sumProcRanks = (numProcs*(numProcs+1))/2; 00386 for( int i = 0; i < numItemsPerProcess; ++i ) { 00387 const int offset = procRank * numItemsPerProcess; 00388 const Packet expected = Packet(sumProcRanks)*Packet(offset+i); 00389 if( recvBuff[i] != expected ) { 00390 result = false; 00391 *out 00392 << "\n recvBuffer["<<i<<"]="<<recvBuff[i] 00393 << " == sum(k+1,k=0...numProcs-1)*(offset+i)="<<sumProcRanks<<"*"<<(offset+i)<<"="<<expected<<" : failed"; 00394 } 00395 } 00396 for( int i = numItemsPerProcess; i < count; i++ ) { 00397 // latter entries in recvBuff should be unchanged (i.e., still zero) 00398 if ( recvBuff[i] != as<Packet>(0) ) result = false; 00399 } 00400 if(result) { 00401 *out << " passed\n"; 00402 } 00403 else { 00404 *out << "\n"; 00405 success = false; 00406 } 00407 00408 result = checkSumResult(comm,out,result); 00409 if(!result) success = false; 00410 00411 // 00412 // The End! 00413 // 00414 00415 if(success) 00416 *out << "\nCongratulations, all tests for this Comm check out!\n"; 00417 else 00418 *out << "\nOh no, at least one of the tests for this Comm failed!\n"; 00419 00420 return success; 00421 00422 } 00423 00424 template<typename Ordinal> 00425 bool masterTestComm( 00426 const Teuchos::RCP<Teuchos::FancyOStream> &out 00427 ) 00428 { 00429 00430 bool success = true, result; 00431 00432 using Teuchos::RCP; 00433 using Teuchos::rcp; 00434 using Teuchos::FancyOStream; 00435 using Teuchos::VerboseObjectBase; 00436 using Teuchos::OSTab; 00437 00438 typedef Teuchos::OrdinalTraits<Ordinal> OT; 00439 00440 OSTab tab(out); 00441 00442 RCP<const Teuchos::Comm<Ordinal> > 00443 comm = Teuchos::DefaultComm<Ordinal>::getComm(); 00444 00445 #ifdef HAVE_MPI 00446 00447 // Test that the DefaultComm is really a DefaultMpiComm. 00448 RCP<const Teuchos::MpiComm<Ordinal> > 00449 mpiComm = Teuchos::rcp_dynamic_cast<const Teuchos::MpiComm<Ordinal> >( comm, false ); 00450 00451 if (mpiComm == Teuchos::null) { 00452 success = false; 00453 *out << "\n*** FAILED to cast the Teuchos::DefaultComm<"<< OT::name() << "> to a Teuchos::MpiComm<" << OT::name() << ">!\n"; 00454 } 00455 else { 00456 *out 00457 << "\n***" 00458 << "\n*** Successfully casted the Teuchos::DefaultComm<"<< OT::name() << "> to a Teuchos::MpiComm<" << OT::name() << ">!" 00459 << "\n***\n"; 00460 00461 // Now get the raw pointer to the MPI_Comm object 00462 RCP<const Teuchos::OpaqueWrapper<MPI_Comm> > 00463 rawMpiComm = mpiComm->getRawMpiComm(); 00464 00465 if (static_cast<MPI_Comm>(*rawMpiComm) == 0) { 00466 success = false; 00467 *out << "\n*** FAILED to get the raw MPI_Comm pointer from the Teuchos::MpiComm<" << OT::name() << ">!\n"; 00468 } 00469 else { 00470 *out 00471 << "\n***" 00472 << "\n*** Successfully got the raw MPI_Comm pointer from the Teuchos::MpiComm<" << OT::name() << ">!" 00473 << "\n***\n"; 00474 } 00475 } 00476 00477 #endif 00478 00479 *out 00480 << "\n***" 00481 << "\n*** Created a Comm of type " << comm->description() << " for testing" 00482 << "\n***\n"; 00483 00484 *out << "\nOrdinal type = "<<OT::name()<<" with an extent of "<<sizeof(Ordinal)<<" bytes\n"; 00485 00486 if( comm->getSize() <= 4 ) { 00487 result = testComm<Ordinal,char>(*comm,out); 00488 if(!result) success = false; 00489 } 00490 00491 result = testComm<Ordinal,int>(*comm,out); 00492 if(!result) success = false; 00493 00494 result = testComm<Ordinal,size_t>(*comm,out); 00495 if(!result) success = false; 00496 00497 result = testComm<Ordinal,float>(*comm,out); 00498 if(!result) success = false; 00499 00500 result = testComm<Ordinal,double>(*comm,out); 00501 if(!result) success = false; 00502 00503 #ifdef HAVE_TEUCHOS_COMPLEX 00504 00505 result = testComm<Ordinal,std::complex<float> >(*comm,out); 00506 if(!result) success = false; 00507 00508 result = testComm<Ordinal,std::complex<double> >(*comm,out); 00509 if(!result) success = false; 00510 00511 #endif // HAVE_TEUCHOS_COMPLEX 00512 00513 return success; 00514 00515 } 00516 00517 // 00518 // Main driver program 00519 // 00520 00521 int main(int argc, char* argv[]) 00522 { 00523 00524 using Teuchos::RCP; 00525 using Teuchos::rcp; 00526 using Teuchos::FancyOStream; 00527 using Teuchos::VerboseObjectBase; 00528 using Teuchos::OSTab; 00529 using Teuchos::CommandLineProcessor; 00530 00531 bool success = true, result; 00532 00533 Teuchos::GlobalMPISession mpiSession(&argc,&argv); 00534 00535 try { 00536 00537 CommandLineProcessor clp; 00538 clp.throwExceptions(false); 00539 clp.addOutputSetupOptions(true); 00540 00541 bool showTimers = true; 00542 00543 clp.setOption( "show-timers", "no-show-timers", &showTimers, "Determine if timers are shown or not" ); 00544 00545 CommandLineProcessor::EParseCommandLineReturn 00546 parse_return = clp.parse(argc,argv); 00547 if( parse_return != CommandLineProcessor::PARSE_SUCCESSFUL ) 00548 return parse_return; 00549 00550 RCP<FancyOStream> 00551 out = VerboseObjectBase::getDefaultOStream(); 00552 00553 *out << std::endl << Teuchos::Teuchos_Version() << std::endl << std::endl; 00554 00555 result = masterTestComm<short int>(out); 00556 if(!result) success = false; 00557 00558 result = masterTestComm<int>(out); 00559 if(!result) success = false; 00560 00561 result = masterTestComm<long int>(out); 00562 if(!result) success = false; 00563 00564 if(showTimers) { 00565 Teuchos::TimeMonitor::summarize( 00566 *out<<"\n" 00567 ,out->getOutputToRootOnly() < 0 // Show local time or not 00568 ); 00569 } 00570 00571 if(success) 00572 *out << "\nEnd Result: TEST PASSED\n"; 00573 00574 } 00575 TEUCHOS_STANDARD_CATCH_STATEMENTS(true,std::cerr,success); 00576 00577 return ( success ? 0 : 1 ); 00578 00579 }
1.7.6.1