Teuchos Package Browser (Single Doxygen Collection) Version of the Day
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 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   mpiIsFinalized_ = true;
00125 #ifdef HAVE_MPI
00126   int mpierr = ::MPI_Finalize();
00127   TEUCHOS_TEST_FOR_EXCEPTION_PRINT(
00128     mpierr != 0, std::runtime_error
00129     ,"Error code=" << mpierr << " detected in MPI_Finalize()"
00130     ,&std::cerr
00131     );
00132 #endif
00133 }
00134 
00135 
00136 bool GlobalMPISession::mpiIsInitialized() {
00137   justInTimeInitialize();
00138   return haveMPIState_;
00139 }
00140 
00141 
00142 bool GlobalMPISession::mpiIsFinalized()
00143 {
00144   return mpiIsFinalized_;
00145 }
00146 
00147 
00148 int GlobalMPISession::getRank()
00149 {
00150   justInTimeInitialize();
00151   return rank_;
00152 }
00153 
00154 
00155 int GlobalMPISession::getNProc() {
00156   justInTimeInitialize();
00157   return nProc_;
00158 }
00159 
00160 
00161 void GlobalMPISession::barrier()
00162 {
00163   justInTimeInitialize();
00164 #ifdef HAVE_MPI
00165   MPI_Barrier(MPI_COMM_WORLD);
00166 #endif
00167 }
00168 
00169 
00170 int GlobalMPISession::sum(int localVal)
00171 {
00172   justInTimeInitialize();
00173 #ifdef HAVE_MPI
00174   int globalSum = -1;
00175   MPI_Allreduce(&localVal, &globalSum, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD); 
00176   return globalSum;
00177 #else
00178   return localVal;
00179 #endif
00180 }
00181 
00182 
00183 void GlobalMPISession::allGather(int localVal, const ArrayView<int> &allVals)
00184 {
00185   justInTimeInitialize();
00186   TEUCHOS_ASSERT_EQUALITY(allVals.size(), getNProc());
00187 #ifdef HAVE_MPI
00188   MPI_Allgather( &localVal, 1, MPI_INT, allVals.getRawPtr(), 1, MPI_INT,
00189     MPI_COMM_WORLD); 
00190 #else
00191   allVals[0] = localVal;
00192 #endif
00193 }
00194 
00195 
00196 // private
00197 
00198 
00199 void GlobalMPISession::initialize( std::ostream *out )
00200 {
00201 #ifdef HAVE_MPI
00202 
00203   if(mpiIsFinalized_) {
00204     // MPI has aleady been finalized so we have a serial machine again!
00205     rank_ = 0;
00206     nProc_ = 1;
00207     return;
00208   }
00209 
00210   if(haveMPIState_)
00211     return; // We already have what we need!
00212 
00213   // We don't have the state of MPI so the constructor for this class must not
00214   // have been called.  However, if MPI has been called in another way we
00215   // can still get the state of MPI_COMM_WORLD here.
00216 
00217   int mpiHasBeenStarted = 0, mpierr = 0;
00218   MPI_Initialized(&mpiHasBeenStarted);
00219 
00220   if(!mpiHasBeenStarted)
00221     return;  // We have to give up and just leave NProc_ and rank_ at the default values.
00222 
00223   // Get the state of MPI
00224 
00225   mpierr = ::MPI_Comm_rank( MPI_COMM_WORLD, &rank_ );
00226   TEUCHOS_TEST_FOR_EXCEPTION_PRINT(
00227     mpierr != 0, std::runtime_error
00228     ,"Error code=" << mpierr << " detected in MPI_Comm_rank()"
00229     ,out
00230     );
00231 
00232   mpierr = ::MPI_Comm_size( MPI_COMM_WORLD, &nProc_ );
00233   TEUCHOS_TEST_FOR_EXCEPTION_PRINT(
00234     mpierr != 0, std::runtime_error
00235     ,"Error code=" << mpierr << " detected in MPI_Comm_size()"
00236     ,out
00237     );
00238 
00239   haveMPIState_ = true;
00240   mpiIsFinalized_ = false;
00241 
00242 #endif // HAVE_MPI
00243 
00244 }
00245 
00246 
00247 void GlobalMPISession::justInTimeInitialize()
00248 {
00249   if(!haveMPIState_)
00250     initialize(&std::cerr);
00251 }
00252 
00253 
00254 } // namespace Teuchos
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines