TIMPI
Loading...
Searching...
No Matches
Public Member Functions | Private Attributes | List of all members
TIMPI::TIMPIInit Class Reference

The TIMPIInit class, when constructed, initializes any dependent libraries (e.g. More...

#include <timpi_init.h>

Public Member Functions

 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.
 
 TIMPIInit (int argc, const char *const *argv, int mpi_thread_requested=0, bool handle_mpi_errors=false)
 
virtual ~TIMPIInit ()
 Destructor.
 
const Communicatorcomm () const
 Returns the Communicator created by this object, which will be a compatibility shim if MPI is not enabled, or a wrapper for the user-input MPI_Comm if we were constructed with one, or a wrapper for MPI_COMM_WORLD by default.
 
Communicatorcomm ()
 

Private Attributes

std::unique_ptr< Communicator_comm
 
std::unique_ptr< SemiPermanent::Ref_ref
 
bool i_initialized_mpi
 
MPI_Errhandler my_errhandler
 
bool err_handler_set
 

Detailed Description

The TIMPIInit class, when constructed, initializes any dependent libraries (e.g.

MPI).

For many users, a single TIMPIInit object should be created at the start of your main() function.

Since "it is best not to perform much more than a return rc after calling MPI_Finalize", applications which want to do anything after TIMPIInit destruction should manage MPI initialization and finalization manually.

Definition at line 57 of file timpi_init.h.

Constructor & Destructor Documentation

◆ TIMPIInit() [1/2]

TIMPI::TIMPIInit::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.

This will e.g. call MPI_Init_thread if MPI is available and enabled and has not already been initialized.

mpi_thread_requested should be set to 0 when MPI_THREAD_SINGLE is desired, 1 when MPI_THREAD_FUNNELED initialization is desired, 2 when MPI_THREAD_SERIALIZED is desaired, and 3 when MPI_THREAD_MULTIPLE is desired

handle_mpi_errors should be set to true to use the "timpi_not_implemented()" behavior (e.g. throwing an exception) as an MPI error handler, which can aid in debugging.

When building with MPI, this method may take an optional parameter to use a user-specified MPI communicator.

Definition at line 44 of file timpi_init.C.

47 :
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}
MPI_Errhandler my_errhandler
Definition timpi_init.h:113
std::unique_ptr< SemiPermanent::Ref > _ref
Definition timpi_init.h:108
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

References _comm, _ref, TIMPI::cast_int(), err_handler_set, i_initialized_mpi, my_errhandler, and TIMPI_MPI_Handler().

◆ TIMPIInit() [2/2]

TIMPI::TIMPIInit::TIMPIInit ( int  argc,
const char *const argv,
int  mpi_thread_requested = 0,
bool  handle_mpi_errors = false 
)

Definition at line 125 of file timpi_init.C.

128{
129 this->_comm = std::make_unique<Communicator>(); // So comm() doesn't dereference null
130 this->_ref = std::make_unique<SemiPermanent::Ref>();
131}

References _comm, and _ref.

◆ ~TIMPIInit()

TIMPI::TIMPIInit::~TIMPIInit ( )
virtual

Destructor.

Finalizes MPI if that was initialized by TIMPIInit.

Definition at line 136 of file timpi_init.C.

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}
void barrier() const
Pause execution until all processors reach a certain point.
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

References _comm, _ref, TIMPI::Communicator::barrier(), TIMPI::cast_int(), comm(), err_handler_set, i_initialized_mpi, and my_errhandler.

Member Function Documentation

◆ comm() [1/2]

Communicator & TIMPI::TIMPIInit::comm ( )
inline

Definition at line 102 of file timpi_init.h.

102{ return *_comm; }

References _comm.

◆ comm() [2/2]

const Communicator & TIMPI::TIMPIInit::comm ( ) const
inline

Returns the Communicator created by this object, which will be a compatibility shim if MPI is not enabled, or a wrapper for the user-input MPI_Comm if we were constructed with one, or a wrapper for MPI_COMM_WORLD by default.

Definition at line 100 of file timpi_init.h.

100{ return *_comm; }

References _comm.

Referenced by ~TIMPIInit().

Member Data Documentation

◆ _comm

std::unique_ptr<Communicator> TIMPI::TIMPIInit::_comm
private

Definition at line 105 of file timpi_init.h.

Referenced by comm(), comm(), TIMPIInit(), TIMPIInit(), and ~TIMPIInit().

◆ _ref

std::unique_ptr<SemiPermanent::Ref> TIMPI::TIMPIInit::_ref
private

Definition at line 108 of file timpi_init.h.

Referenced by TIMPIInit(), TIMPIInit(), and ~TIMPIInit().

◆ err_handler_set

bool TIMPI::TIMPIInit::err_handler_set
private

Definition at line 114 of file timpi_init.h.

Referenced by TIMPIInit(), and ~TIMPIInit().

◆ i_initialized_mpi

bool TIMPI::TIMPIInit::i_initialized_mpi
private

Definition at line 111 of file timpi_init.h.

Referenced by TIMPIInit(), and ~TIMPIInit().

◆ my_errhandler

MPI_Errhandler TIMPI::TIMPIInit::my_errhandler
private

Definition at line 113 of file timpi_init.h.

Referenced by TIMPIInit(), and ~TIMPIInit().


The documentation for this class was generated from the following files: