|
Teuchos Package Browser (Single Doxygen Collection)
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 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
1.7.6.1