Teuchos Package Browser (Single Doxygen Collection)  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
Teuchos_GlobalMPISession.cpp
Go to the documentation of this file.
00001 // @HEADER
00002 // ***********************************************************************
00003 //
00004 //                    Teuchos: Common Tools Package
00005 //                 Copyright (2004) Sandia Corporation
00006 //
00007 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
00008 // license for use of this work by or on behalf of the U.S. Government.
00009 //
00010 // Redistribution and use in source and binary forms, with or without
00011 // modification, are permitted provided that the following conditions are
00012 // met:
00013 //
00014 // 1. Redistributions of source code must retain the above copyright
00015 // notice, this list of conditions and the following disclaimer.
00016 //
00017 // 2. Redistributions in binary form must reproduce the above copyright
00018 // notice, this list of conditions and the following disclaimer in the
00019 // documentation and/or other materials provided with the distribution.
00020 //
00021 // 3. Neither the name of the Corporation nor the names of the
00022 // contributors may be used to endorse or promote products derived from
00023 // this software without specific prior written permission.
00024 //
00025 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
00026 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00027 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00028 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
00029 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00030 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00031 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00032 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00033 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00034 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00035 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00036 //
00037 // Questions? Contact Michael A. Heroux (maherou@sandia.gov)
00038 //
00039 // ***********************************************************************
00040 // @HEADER
00041 
00042 #include "Teuchos_GlobalMPISession.hpp"
00043 #include "Teuchos_Assert.hpp"
00044 
00045 // The header file does not at all depend on MPI routines or types,
00046 // so we can defer inclusion of mpi.h to here.  This also fixes Bug
00047 // 5631:  https://software.sandia.gov/bugzilla/show_bug.cgi?id=5631
00048 #ifdef HAVE_MPI
00049 #include "mpi.h"
00050 #endif
00051 
00052 
00053 namespace Teuchos {
00054 
00055 
00056 bool GlobalMPISession::haveMPIState_ = false;
00057 bool GlobalMPISession::mpiIsFinalized_ = false;
00058 int GlobalMPISession::rank_ = 0 ;
00059 int GlobalMPISession::nProc_ = 1 ;
00060 
00061 
00062 GlobalMPISession::GlobalMPISession( int* argc, char*** argv, std::ostream *out )
00063 {
00064   std::ostringstream oss;
00065 
00066   // Above is used to create all output before sending to *out to avoid
00067   // jumbled parallel output between processors
00068 
00069 #ifdef HAVE_MPI
00070 
00071   int mpierr = 0;
00072 
00073   // Assert that MPI is not already initialized
00074   int mpiHasBeenStarted = 0;
00075   MPI_Initialized(&mpiHasBeenStarted);
00076   if (mpiHasBeenStarted) {
00077     if (out) {
00078       *out << "GlobalMPISession(): Error, MPI_Intialized() return true,"
00079            << " calling std::terminate()!\n"
00080            << std::flush;
00081     }
00082     std::terminate();
00083   }
00084 
00085   // Initialize MPI
00086   mpierr = ::MPI_Init(argc, (char ***) argv);
00087   if (mpierr != 0) {
00088     if (out) {
00089       *out << "GlobalMPISession(): Error, MPI_Init() returned error code="
00090            << mpierr << "!=0, calling std::terminate()!\n"
00091            << std::flush;
00092     }
00093     std::terminate();
00094   }
00095 
00096   initialize(out); // Get NProc_ and rank_
00097 
00098   int nameLen;
00099   char procName[MPI_MAX_PROCESSOR_NAME];
00100   mpierr = ::MPI_Get_processor_name(procName, &nameLen);
00101   if (mpierr != 0) {
00102     if (out) {
00103       *out << "GlobalMPISession():  Error, MPI_Get_processor_name() error code="
00104            << mpierr << "!=0, calling std::terminate()!\n"
00105            << std::flush;
00106     }
00107     std::terminate();
00108   }
00109 
00110   oss << "Teuchos::GlobalMPISession::GlobalMPISession(): started processor with name "
00111       << procName << " and rank " << rank_ << "!" << std::endl;
00112 
00113 #else
00114 
00115   oss << "Teuchos::GlobalMPISession::GlobalMPISession(): started serial run"
00116       << std::endl;
00117 
00118 #endif
00119 
00120 #ifndef TEUCHOS_SUPPRESS_PROC_STARTUP_BANNER
00121 
00122   // See if we should suppress the startup banner
00123   bool printStartupBanner = true;
00124   const std::string suppress_option("--teuchos-suppress-startup-banner");
00125   for ( int opt_i = 0; opt_i < *argc; ++opt_i ) {
00126     if ( suppress_option == (*argv)[opt_i] ) {
00127       // We are suppressing the output!
00128       printStartupBanner = false;
00129       // Remove this option!
00130       // Note that (*argv)[*argc]==0 but convention so we copy it too!
00131       for( int i = opt_i; i < *argc; ++i )
00132         (*argv)[i] = (*argv)[i+1];
00133       --*argc;
00134     }
00135   }
00136   if (out && printStartupBanner) {
00137     *out << oss.str() << std::flush;
00138   }
00139 
00140 #endif
00141 
00142 }
00143 
00144 
00145 GlobalMPISession::~GlobalMPISession()
00146 {
00147   haveMPIState_ = false;
00148 #ifdef HAVE_MPI
00149   const int mpierr = ::MPI_Finalize();
00150   mpiIsFinalized_ = (mpierr == 0);
00151   if (mpierr != 0)
00152     std::cerr << "Error code " << mpierr << " returned from MPI_Finalize()\n";
00153 #else
00154   mpiIsFinalized_ = true;
00155 #endif
00156 }
00157 
00158 
00159 bool GlobalMPISession::mpiIsInitialized() {
00160   justInTimeInitialize();
00161   return haveMPIState_;
00162 }
00163 
00164 
00165 bool GlobalMPISession::mpiIsFinalized()
00166 {
00167   return mpiIsFinalized_;
00168 }
00169 
00170 
00171 int GlobalMPISession::getRank()
00172 {
00173   justInTimeInitialize();
00174   return rank_;
00175 }
00176 
00177 
00178 int GlobalMPISession::getNProc() {
00179   justInTimeInitialize();
00180   return nProc_;
00181 }
00182 
00183 
00184 void GlobalMPISession::barrier()
00185 {
00186   justInTimeInitialize();
00187 #ifdef HAVE_MPI
00188   MPI_Barrier(MPI_COMM_WORLD);
00189 #endif
00190 }
00191 
00192 
00193 int GlobalMPISession::sum(int localVal)
00194 {
00195   justInTimeInitialize();
00196 #ifdef HAVE_MPI
00197   int globalSum = -1;
00198   MPI_Allreduce(&localVal, &globalSum, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
00199   return globalSum;
00200 #else
00201   return localVal;
00202 #endif
00203 }
00204 
00205 
00206 void GlobalMPISession::allGather(int localVal, const ArrayView<int> &allVals)
00207 {
00208   justInTimeInitialize();
00209   TEUCHOS_ASSERT_EQUALITY(allVals.size(), getNProc());
00210 #ifdef HAVE_MPI
00211   MPI_Allgather( &localVal, 1, MPI_INT, allVals.getRawPtr(), 1, MPI_INT,
00212     MPI_COMM_WORLD);
00213 #else
00214   allVals[0] = localVal;
00215 #endif
00216 }
00217 
00218 
00219 // private
00220 
00221 
00222 void GlobalMPISession::initialize( std::ostream *out )
00223 {
00224 #ifdef HAVE_MPI
00225 
00226   if(mpiIsFinalized_) {
00227     // MPI has aleady been finalized so we have a serial machine again!
00228     rank_ = 0;
00229     nProc_ = 1;
00230     return;
00231   }
00232 
00233   if(haveMPIState_) {
00234     return; // We already have what we need!
00235   }
00236 
00237   // We don't have the state of MPI so the constructor for this class must not
00238   // have been called.  However, if MPI has been called in another way we
00239   // can still get the state of MPI_COMM_WORLD here.
00240 
00241   int mpiHasBeenStarted = 0;
00242   MPI_Initialized(&mpiHasBeenStarted);
00243 
00244   if(!mpiHasBeenStarted)
00245     return;  // We have to give up and just leave NProc_ and rank_ at the default values.
00246 
00247   // Get the state of MPI
00248   // Don't throw exceptions here since this part of the code
00249   // is used by TEUCHOS_STANDARD_CATCH_STATEMENTS().
00250   // See bug #6192 <https://software.sandia.gov/bugzilla/show_bug.cgi?id=6192>.
00251   int mpierr = 0;
00252   mpierr = ::MPI_Comm_rank( MPI_COMM_WORLD, &rank_ );
00253   if (mpierr != 0) {
00254     *out << "Error code=" << mpierr << " detected in MPI_Comm_rank()"
00255          << std::endl;
00256   }
00257 
00258   mpierr = ::MPI_Comm_size( MPI_COMM_WORLD, &nProc_ );
00259   if (mpierr != 0) {
00260     *out << "Error code=" << mpierr << " detected in MPI_Comm_size()"
00261          << std::endl;
00262   }
00263 
00264   haveMPIState_ = true;
00265   mpiIsFinalized_ = false;
00266 
00267 #endif // HAVE_MPI
00268 
00269 }
00270 
00271 
00272 void GlobalMPISession::justInTimeInitialize()
00273 {
00274   if(!haveMPIState_)
00275     initialize(&std::cerr);
00276 }
00277 
00278 
00279 } // namespace Teuchos
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines