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