TIMPI
Loading...
Searching...
No Matches
timpi_init.C
Go to the documentation of this file.
1// The TIMPI Message-Passing Parallelism Library.
2// Copyright (C) 2002-2025 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
3
4// This library is free software; you can redistribute it and/or
5// modify it under the terms of the GNU Lesser General Public
6// License as published by the Free Software Foundation; either
7// version 2.1 of the License, or (at your option) any later version.
8
9// This library is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12// Lesser General Public License for more details.
13
14// You should have received a copy of the GNU Lesser General Public
15// License along with this library; if not, write to the Free Software
16// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
18
19// Local includes
20#include "timpi/timpi_init.h"
21
22#include "timpi/semipermanent.h"
23
24// TIMPI includes
25#include "timpi/communicator.h"
26#include "timpi/timpi_assert.h"
27
28#ifdef TIMPI_ENABLE_EXCEPTIONS
29#include <exception> // For std::uncaught_exceptions
30#endif
31
32#ifdef TIMPI_HAVE_MPI
33void TIMPI_MPI_Handler (MPI_Comm *, int *, ...)
34{
35 timpi_not_implemented();
36}
37#endif
38
39
40namespace TIMPI
41{
42
43#ifdef TIMPI_HAVE_MPI
44TIMPIInit::TIMPIInit (int argc, const char * const * argv,
48 i_initialized_mpi(false),
49 err_handler_set(false)
50{
51 // Check whether the calling program has already initialized
52 // MPI, and avoid duplicate Init/Finalize
53 int flag;
55
56 if (!flag)
57 {
59
61 (MPI_Init_thread (&argc, const_cast<char ***>(&argv),
63
65 {
66 // Ideally, if an MPI stack tells us it's unsafe for us
67 // to use threads, we should scream and die or at least
68 // disable threads.
69 //
70 // In practice, we've encountered one MPI stack (an mvapich2
71 // configuration) that returned MPI_THREAD_SINGLE as a
72 // proper warning, two stacks that handle
73 // MPI_THREAD_FUNNELED properly, and two current stacks plus
74 // a couple old stacks that return MPI_THREAD_SINGLE but
75 // support threaded runs anyway, so we just emit a warning.
76 //
77 std::string thread_type;
79 {
80 case 0:
81 thread_type = "MPI_THREAD_SINGLE";
82 break;
83 case 1:
84 thread_type = "MPI_THREAD_FUNNELED";
85 break;
86 case 2:
87 thread_type = "MPI_THREAD_SERIALIZED";
88 break;
89 case 3:
90 thread_type = "MPI_THREAD_MULTIPLE";
91 break;
92 default:
93 timpi_error_msg("Unsupported mpi thread requested '" << mpi_thread_requested << "'");
94 }
95
96 timpi_warning("Warning: MPI failed to guarantee " << thread_type << "\n"
97 << "for a threaded run.\n"
98 << std::endl);
99 }
100 this->i_initialized_mpi = true;
101 }
102
103 // Duplicate the input communicator for internal use
104 // And get a Communicator copy too, to use
105 // as a default for that API
106 this->_comm = std::make_unique<Communicator>(COMM_WORLD_IN);
107
108 // Let SemiPermanent know we need its objects for a while
109 this->_ref = std::make_unique<SemiPermanent::Ref>();
110
111 // Set up an MPI error handler if requested. This helps us get
112 // into a debugger with a proper stack when an MPI error occurs.
114 {
121 err_handler_set = true;
122 }
123}
124#else
125TIMPIInit::TIMPIInit (int /* argc */, const char * const * /* argv */,
126 int /* mpi_thread_requested */,
127 bool /* handle_mpi_errors */)
128{
129 this->_comm = std::make_unique<Communicator>(); // So comm() doesn't dereference null
130 this->_ref = std::make_unique<SemiPermanent::Ref>();
131}
132#endif
133
134
135
137{
138 // Every processor had better be ready to exit at the same time.
139 // Even if we're not doing parallel_only debugging, we don't want
140 // one processor to try to exit until all others are done working.
141
142 // We could be destructing here because we're unwinding the stack
143 // due to a thrown exception, though. It's possible that an
144 // application is catching exceptions outside of the LibMeshInit
145 // scope, or that we're using a C++ compiler that does unwinding
146 // for uncaught exceptions (the standard says whether to go straight
147 // to terminate() or unwind first is "implementation-defined"). If
148 // *that* is the case then we can't safely communicate with other
149 // processors that might not all be unwinding too.
150#ifdef TIMPI_ENABLE_EXCEPTIONS
151 if (!std::uncaught_exceptions())
152#endif
153 this->comm().barrier();
154
155 // Trigger any SemiPermanent cleanup before potentially finalizing MPI
156 _ref.reset();
157
158#ifdef TIMPI_HAVE_MPI
159 if (err_handler_set)
160 {
161 unsigned int error_code =
163 if (error_code != MPI_SUCCESS)
164 {
165 std::cerr <<
166 "Failure when freeing MPI_Errhandler! Continuing..." <<
167 std::endl;
168 }
169 }
170
171 this->_comm.reset();
172
173 if (this->i_initialized_mpi)
174 {
175 // We can't just timpi_assert here because destructor,
176 // but we ought to report any errors
177 int error_code = MPI_Finalize();
178 if (error_code != MPI_SUCCESS)
179 {
184 std::cerr << "Failure from MPI_Finalize():\n"
185 << error_string << std::endl;
186 }
187 }
188#else
189 this->_comm.reset();
190#endif
191}
192
193
194} // namespace TIMPI
void barrier() const
Pause execution until all processors reach a certain point.
MPI_Errhandler my_errhandler
Definition timpi_init.h:113
std::unique_ptr< SemiPermanent::Ref > _ref
Definition timpi_init.h:108
TIMPIInit(int argc, const char *const *argv, int mpi_thread_requested=0, bool handle_mpi_errors=false, MPI_Comm COMM_WORLD_IN=MPI_COMM_WORLD)
Initialize the library for use, with the command line options provided.
Definition timpi_init.C:44
virtual ~TIMPIInit()
Destructor.
Definition timpi_init.C:136
const Communicator & comm() const
Returns the Communicator created by this object, which will be a compatibility shim if MPI is not ena...
Definition timpi_init.h:100
std::unique_ptr< Communicator > _comm
Definition timpi_init.h:105
Tnew cast_int(Told oldvar)
void TIMPI_MPI_Handler(MPI_Comm *, int *,...)
Definition timpi_init.C:33