Teuchos Package Browser (Single Doxygen Collection) Version of the Day
Comm_test.cpp
Go to the documentation of this file.
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 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines