Comm_test.cpp

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