Teuchos - Trilinos Tools Package Version of the Day
Teuchos_GlobalMPISession.cpp
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 bool GlobalMPISession::haveMPIState_ = false;
00056 bool GlobalMPISession::mpiIsFinalized_ = false;
00057 int GlobalMPISession::rank_ = 0 ;
00058 int GlobalMPISession::nProc_ = 1 ;
00059 
00060 GlobalMPISession::GlobalMPISession( int* argc, char*** argv, std::ostream *out )
00061 {
00062   std::ostringstream oss;
00063 
00064   // Above is used to create all output before sending to *out to avoid
00065   // jumbled parallel output between processors
00066 
00067 #ifdef HAVE_MPI
00068   // initialize MPI
00069         int mpiHasBeenStarted = 0, mpierr = 0;
00070         MPI_Initialized(&mpiHasBeenStarted);
00071         TEUCHOS_TEST_FOR_EXCEPTION_PRINT(
00072     mpiHasBeenStarted, std::runtime_error
00073     ,"Error, you can only call this constructor once!"
00074     ,out
00075     );
00076 
00077   mpierr = ::MPI_Init (argc, (char ***) argv);
00078   TEUCHOS_TEST_FOR_EXCEPTION_PRINT(
00079     mpierr != 0, std::runtime_error
00080     ,"Error code=" << mpierr << " detected in GlobalMPISession::GlobalMPISession(argc,argv)"
00081     ,out
00082     );
00083 
00084   initialize(out); // Get NProc_ and rank_
00085 
00086   int nameLen;
00087         char procName[MPI_MAX_PROCESSOR_NAME];
00088   mpierr = ::MPI_Get_processor_name(procName,&nameLen);
00089   TEUCHOS_TEST_FOR_EXCEPTION_PRINT(
00090     mpierr != 0, std::runtime_error
00091     ,"Error code=" << mpierr << " detected in MPI_Get_processor_name()"
00092     ,out
00093     );
00094 
00095   oss << "Teuchos::GlobalMPISession::GlobalMPISession(): started processor with name "
00096       << procName << " and rank " << rank_ << "!" << std::endl;
00097 
00098 #else
00099   oss << "Teuchos::GlobalMPISession::GlobalMPISession(): started serial run" << std::endl;
00100 #endif
00101 #ifndef TEUCHOS_SUPPRESS_PROC_STARTUP_BANNER
00102   // See if we should suppress the startup banner
00103   bool printStartupBanner = true;
00104   const std::string suppress_option("--teuchos-suppress-startup-banner");
00105   for( int opt_i = 0; opt_i < *argc; ++opt_i ) {
00106     if( suppress_option == (*argv)[opt_i] ) {
00107       // We are suppressing the output!
00108       printStartupBanner = false;
00109       // Remove this option!
00110       // Note that (*argv)[*argc]==0 but convention so we copy it too!
00111       for( int i = opt_i; i < *argc; ++i )
00112         (*argv)[i] = (*argv)[i+1];
00113       --*argc;
00114     }
00115   }
00116   if( out && printStartupBanner )
00117     *out << oss.str() << std::flush;
00118 #endif
00119 }
00120 
00121 GlobalMPISession::~GlobalMPISession()
00122 {
00123   haveMPIState_ = false;
00124 #ifdef HAVE_MPI
00125   const int mpierr = ::MPI_Finalize();
00126   mpiIsFinalized_ = (mpierr == 0);
00127   if (mpierr != 0)
00128     std::cerr << "Error code " << mpierr << " returned from MPI_Finalize()\n";
00129 #else
00130   mpiIsFinalized_ = true;
00131 #endif
00132 }
00133 
00134 
00135 bool GlobalMPISession::mpiIsInitialized() {
00136   justInTimeInitialize();
00137   return haveMPIState_;
00138 }
00139 
00140 
00141 bool GlobalMPISession::mpiIsFinalized()
00142 {
00143   return mpiIsFinalized_;
00144 }
00145 
00146 
00147 int GlobalMPISession::getRank()
00148 {
00149   justInTimeInitialize();
00150   return rank_;
00151 }
00152 
00153 
00154 int GlobalMPISession::getNProc() {
00155   justInTimeInitialize();
00156   return nProc_;
00157 }
00158 
00159 
00160 void GlobalMPISession::barrier()
00161 {
00162   justInTimeInitialize();
00163 #ifdef HAVE_MPI
00164   MPI_Barrier(MPI_COMM_WORLD);
00165 #endif
00166 }
00167 
00168 
00169 int GlobalMPISession::sum(int localVal)
00170 {
00171   justInTimeInitialize();
00172 #ifdef HAVE_MPI
00173   int globalSum = -1;
00174   MPI_Allreduce(&localVal, &globalSum, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD); 
00175   return globalSum;
00176 #else
00177   return localVal;
00178 #endif
00179 }
00180 
00181 
00182 void GlobalMPISession::allGather(int localVal, const ArrayView<int> &allVals)
00183 {
00184   justInTimeInitialize();
00185   TEUCHOS_ASSERT_EQUALITY(allVals.size(), getNProc());
00186 #ifdef HAVE_MPI
00187   MPI_Allgather( &localVal, 1, MPI_INT, allVals.getRawPtr(), 1, MPI_INT,
00188     MPI_COMM_WORLD); 
00189 #else
00190   allVals[0] = localVal;
00191 #endif
00192 }
00193 
00194 
00195 // private
00196 
00197 
00198 void GlobalMPISession::initialize( std::ostream *out )
00199 {
00200 #ifdef HAVE_MPI
00201 
00202   if(mpiIsFinalized_) {
00203     // MPI has aleady been finalized so we have a serial machine again!
00204     rank_ = 0;
00205     nProc_ = 1;
00206     return;
00207   }
00208 
00209   if(haveMPIState_)
00210     return; // We already have what we need!
00211 
00212   // We don't have the state of MPI so the constructor for this class must not
00213   // have been called.  However, if MPI has been called in another way we
00214   // can still get the state of MPI_COMM_WORLD here.
00215 
00216   int mpiHasBeenStarted = 0, mpierr = 0;
00217   MPI_Initialized(&mpiHasBeenStarted);
00218 
00219   if(!mpiHasBeenStarted)
00220     return;  // We have to give up and just leave NProc_ and rank_ at the default values.
00221 
00222   // Get the state of MPI
00223 
00224   mpierr = ::MPI_Comm_rank( MPI_COMM_WORLD, &rank_ );
00225   TEUCHOS_TEST_FOR_EXCEPTION_PRINT(
00226     mpierr != 0, std::runtime_error
00227     ,"Error code=" << mpierr << " detected in MPI_Comm_rank()"
00228     ,out
00229     );
00230 
00231   mpierr = ::MPI_Comm_size( MPI_COMM_WORLD, &nProc_ );
00232   TEUCHOS_TEST_FOR_EXCEPTION_PRINT(
00233     mpierr != 0, std::runtime_error
00234     ,"Error code=" << mpierr << " detected in MPI_Comm_size()"
00235     ,out
00236     );
00237 
00238   haveMPIState_ = true;
00239   mpiIsFinalized_ = false;
00240 
00241 #endif // HAVE_MPI
00242 
00243 }
00244 
00245 
00246 void GlobalMPISession::justInTimeInitialize()
00247 {
00248   if(!haveMPIState_)
00249     initialize(&std::cerr);
00250 }
00251 
00252 
00253 } // namespace Teuchos
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines