Loading [MathJax]/extensions/tex2jax.js
TIMPI
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends
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. More...
 
 TIMPIInit (int argc, const char *const *argv, int mpi_thread_requested=0, bool handle_mpi_errors=false)
 
virtual ~TIMPIInit ()
 Destructor. More...
 
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. More...
 
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 41 of file timpi_init.C.

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

44  :
45  i_initialized_mpi(false),
46  err_handler_set(false)
47 {
48  // Check whether the calling program has already initialized
49  // MPI, and avoid duplicate Init/Finalize
50  int flag;
51  timpi_call_mpi(MPI_Initialized (&flag));
52 
53  if (!flag)
54  {
55  int mpi_thread_provided;
56 
57  timpi_call_mpi
58  (MPI_Init_thread (&argc, const_cast<char ***>(&argv),
59  mpi_thread_requested, &mpi_thread_provided));
60 
61  if (mpi_thread_provided < mpi_thread_requested)
62  {
63  // Ideally, if an MPI stack tells us it's unsafe for us
64  // to use threads, we should scream and die or at least
65  // disable threads.
66  //
67  // In practice, we've encountered one MPI stack (an mvapich2
68  // configuration) that returned MPI_THREAD_SINGLE as a
69  // proper warning, two stacks that handle
70  // MPI_THREAD_FUNNELED properly, and two current stacks plus
71  // a couple old stacks that return MPI_THREAD_SINGLE but
72  // support threaded runs anyway, so we just emit a warning.
73  //
74  std::string thread_type;
75  switch (mpi_thread_requested)
76  {
77  case 0:
78  thread_type = "MPI_THREAD_SINGLE";
79  break;
80  case 1:
81  thread_type = "MPI_THREAD_FUNNELED";
82  break;
83  case 2:
84  thread_type = "MPI_THREAD_SERIALIZED";
85  break;
86  case 3:
87  thread_type = "MPI_THREAD_MULTIPLE";
88  break;
89  default:
90  timpi_error_msg("Unsupported mpi thread requested '" << mpi_thread_requested << "'");
91  }
92 
93  timpi_warning("Warning: MPI failed to guarantee " << thread_type << "\n"
94  << "for a threaded run.\n"
95  << std::endl);
96  }
97  this->i_initialized_mpi = true;
98  }
99 
100  // Duplicate the input communicator for internal use
101  // And get a Communicator copy too, to use
102  // as a default for that API
103  this->_comm = std::make_unique<Communicator>(COMM_WORLD_IN);
104 
105  // Let SemiPermanent know we need its objects for a while
106  this->_ref = std::make_unique<SemiPermanent::Ref>();
107 
108  // Set up an MPI error handler if requested. This helps us get
109  // into a debugger with a proper stack when an MPI error occurs.
110  if (handle_mpi_errors)
111  {
112  timpi_call_mpi
113  (MPI_Comm_create_errhandler(TIMPI_MPI_Handler, &my_errhandler));
114  timpi_call_mpi
115  (MPI_Comm_set_errhandler(COMM_WORLD_IN, my_errhandler));
116  timpi_call_mpi
117  (MPI_Comm_set_errhandler(MPI_COMM_WORLD, my_errhandler));
118  err_handler_set = true;
119  }
120 }
std::unique_ptr< SemiPermanent::Ref > _ref
Definition: timpi_init.h:108
void TIMPI_MPI_Handler(MPI_Comm *, int *,...)
Definition: timpi_init.C:30
bool i_initialized_mpi
Definition: timpi_init.h:111
MPI_Errhandler my_errhandler
Definition: timpi_init.h:113
std::unique_ptr< Communicator > _comm
Definition: timpi_init.h:105

◆ 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 122 of file timpi_init.C.

References _comm, and _ref.

125 {
126  this->_comm = std::make_unique<Communicator>(); // So comm() doesn't dereference null
127  this->_ref = std::make_unique<SemiPermanent::Ref>();
128 }
std::unique_ptr< SemiPermanent::Ref > _ref
Definition: timpi_init.h:108
std::unique_ptr< Communicator > _comm
Definition: timpi_init.h:105

◆ ~TIMPIInit()

TIMPI::TIMPIInit::~TIMPIInit ( )
virtual

Destructor.

Finalizes MPI if that was initialized by TIMPIInit.

Definition at line 133 of file timpi_init.C.

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

134 {
135  // Every processor had better be ready to exit at the same time.
136  // This would be a timpi_parallel_only() function, except that
137  // timpi_parallel_only() uses timpi_assert() which throws an
138  // exception which causes compilers to scream about exceptions
139  // inside destructors.
140 
141  // Even if we're not doing parallel_only debugging, we don't want
142  // one processor to try to exit until all others are done working.
143  this->comm().barrier();
144 
145  // Trigger any SemiPermanent cleanup before potentially finalizing MPI
146  _ref.reset();
147 
148 #ifdef TIMPI_HAVE_MPI
149  if (err_handler_set)
150  {
151  unsigned int error_code =
152  MPI_Errhandler_free(&my_errhandler);
153  if (error_code != MPI_SUCCESS)
154  {
155  std::cerr <<
156  "Failure when freeing MPI_Errhandler! Continuing..." <<
157  std::endl;
158  }
159  }
160 
161  this->_comm.reset();
162 
163  if (this->i_initialized_mpi)
164  {
165  // We can't just timpi_assert here because destructor,
166  // but we ought to report any errors
167  int error_code = MPI_Finalize();
168  if (error_code != MPI_SUCCESS)
169  {
170  char error_string[MPI_MAX_ERROR_STRING+1];
171  int error_string_len;
172  MPI_Error_string(error_code, error_string,
173  &error_string_len);
174  std::cerr << "Failure from MPI_Finalize():\n"
175  << error_string << std::endl;
176  }
177  }
178 #else
179  this->_comm.reset();
180 #endif
181 }
std::unique_ptr< SemiPermanent::Ref > _ref
Definition: timpi_init.h:108
void barrier() const
Pause execution until all processors reach a certain point.
Definition: communicator.C:225
bool i_initialized_mpi
Definition: timpi_init.h:111
MPI_Errhandler my_errhandler
Definition: timpi_init.h:113
std::unique_ptr< Communicator > _comm
Definition: timpi_init.h:105
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

Member Function Documentation

◆ comm() [1/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.

References _comm.

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

100 { return *_comm; }
std::unique_ptr< Communicator > _comm
Definition: timpi_init.h:105

◆ comm() [2/2]

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

Definition at line 102 of file timpi_init.h.

References _comm.

102 { return *_comm; }
std::unique_ptr< Communicator > _comm
Definition: timpi_init.h:105

Member Data Documentation

◆ _comm

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

Definition at line 105 of file timpi_init.h.

Referenced by comm(), 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(), 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: