|
Teuchos - Trilinos Tools Package
Version of the Day
|
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 bool GlobalMPISession::mpiIsInitialized() { 00136 if(!haveMPIState_) 00137 initialize(&std::cerr); 00138 return haveMPIState_; 00139 } 00140 00141 bool GlobalMPISession::mpiIsFinalized() 00142 { 00143 return mpiIsFinalized_; 00144 } 00145 00146 int GlobalMPISession::getRank() 00147 { 00148 if(!haveMPIState_) 00149 initialize(&std::cerr); 00150 return rank_; 00151 } 00152 00153 int GlobalMPISession::getNProc() { 00154 if(!haveMPIState_) 00155 initialize(&std::cerr); 00156 return nProc_; 00157 } 00158 00159 // private 00160 00161 void GlobalMPISession::initialize( std::ostream *out ) 00162 { 00163 #ifdef HAVE_MPI 00164 00165 if(mpiIsFinalized_) { 00166 // MPI has aleady been finalized so we have a serial machine again! 00167 rank_ = 0; 00168 nProc_ = 1; 00169 return; 00170 } 00171 00172 if(haveMPIState_) 00173 return; // We already have what we need! 00174 00175 // We don't have the state of MPI so the constructor for this class must not 00176 // have been called. However, if MPI has been called in another way we 00177 // can still get the state of MPI_COMM_WORLD here. 00178 00179 int mpiHasBeenStarted = 0, mpierr = 0; 00180 MPI_Initialized(&mpiHasBeenStarted); 00181 00182 if(!mpiHasBeenStarted) 00183 return; // We have to give up and just leave NProc_ and rank_ at the default values. 00184 00185 // Get the state of MPI 00186 00187 mpierr = ::MPI_Comm_rank( MPI_COMM_WORLD, &rank_ ); 00188 TEUCHOS_TEST_FOR_EXCEPTION_PRINT( 00189 mpierr != 0, std::runtime_error 00190 ,"Error code=" << mpierr << " detected in MPI_Comm_rank()" 00191 ,out 00192 ); 00193 00194 mpierr = ::MPI_Comm_size( MPI_COMM_WORLD, &nProc_ ); 00195 TEUCHOS_TEST_FOR_EXCEPTION_PRINT( 00196 mpierr != 0, std::runtime_error 00197 ,"Error code=" << mpierr << " detected in MPI_Comm_size()" 00198 ,out 00199 ); 00200 00201 haveMPIState_ = true; 00202 mpiIsFinalized_ = false; 00203 00204 #endif // HAVE_MPI 00205 00206 } 00207 00208 } // namespace Teuchos
1.7.6.1