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 // 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 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines