G+Smo  24.08.0
Geometry + Simulation Modules
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
gsMpi.h
Go to the documentation of this file.
1 
14 #pragma once
15 
17 
18 #ifdef GISMO_WITH_MPI
19 #include <string.h>
20 #include <mpi.h>
21 // #if MPI_VERSION < 2
22 // # ifdef _MSC_VER
23 // # pragma message ("The MPI version is older than MPI-2.")
24 // # else
25 // # warning "The MPI version is older than MPI-2."
26 // # endif
27 //#endif
28 #include <gsParallel/gsMpiTraits.h>
30 #endif
31 
32 #include <gsParallel/gsMpiComm.h>
33 
34 namespace gismo
35 {
36 
37 class gsMpi;
38 
40 GISMO_EXPORT gsMpi & gsMpiSingleton(const int& argc, char** argv);
41 
58 class gsMpi
59 {
60 
61 public:
62 
63  friend GISMO_EXPORT gsMpi & gsMpiSingleton(const int& argc, char** argv);
64 
65 # ifdef GISMO_WITH_MPI
66 
69  typedef MPI_Comm Communicator;
70 # else
71  typedef gsSerialComm Communicator;
72 # endif
73 
80  static Communicator worldComm()
81  {
82 # ifdef GISMO_WITH_MPI
83  return MPI_COMM_WORLD;
84 # else
85  return localComm();
86 # endif
87  }
88 
95  static Communicator localComm()
96  {
97  return gsSerialComm();
98  }
99 
115  static gsMpi& init(const int& argc = 0, char** argv = NULL)
116  {
117  GISMO_ASSERT( 0 == argc || NULL!=argv, "Need both argc and argv (or none)");
118  return gsMpiSingleton(argc,argv);
119  }
120 
124  static int worldRank () { return gsMpiComm(worldComm()).rank(); }
128  static int worldSize () { return gsMpiComm(worldComm()).size(); }
129 
130  static inline double wallTime()
131  {
132 # ifdef GISMO_WITH_MPI
133  return MPI_Wtime();
134 # else
135  return 0;
136 # endif
137  }
138 
139  static inline std::string getProcessorName()
140  {
141 # ifdef GISMO_WITH_MPI
142  char processor_name[MPI_MAX_PROCESSOR_NAME];
143  int name_len;
144  MPI_Get_processor_name(processor_name, &name_len);
145  return std::string(processor_name, name_len);
146 # else
147 
148  //linux: gethostname(processor_name, HOST_NAME_MAX);
149  //mswin: GetComputerName(processor_name, &name_len)
150  return "SingleCPU";
151 # endif
152  }
153 
154  bool initialized() const
155  {
156 # ifdef GISMO_WITH_MPI
157  int init = -1;
158  MPI_Initialized( &init );
159  return (0 != init);
160 # endif
161  return false;
162  }
163 
164 private:
165 
166  gsMpi();
167 
169  gsMpi(const int& argc, char** argv)
170  {
171  initMpi(const_cast<int*>(&argc), argv);
172  }
173 
174  void initMpi(int * argc = NULL, char** argv = NULL) const
175  {
176 # ifdef GISMO_WITH_MPI
177  if( !initialized() )
178  {
179 #ifdef _OPENMP
180  // Initialize MPI with multi-threading support
181  char* thread_level = getenv("GISMO_MPI_THREAD_LEVEL");
182  const int req_level = ( NULL != thread_level ? atoi(getenv("GISMO_MPI_THREAD_LEVEL")) : 0);
183  int MPI_thread_required = MPI_THREAD_SINGLE, MPI_thread_provided;
184  switch(req_level)
185  {
186  case 0:
187  MPI_thread_required = MPI_THREAD_SINGLE;
188  break;
189  case 1:
190  MPI_thread_required = MPI_THREAD_FUNNELED;
191  break;
192  case 2:
193  MPI_thread_required = MPI_THREAD_SERIALIZED;
194  break;
195  case 3:
196  MPI_thread_required = MPI_THREAD_MULTIPLE;
197  break;
198  default:
199  GISMO_ERROR("Invalid value for environment variable GISMO_MPI_THREAD_LEVEL");
200  };
201 
202  const int init = MPI_Init_thread(argc, &argv, MPI_thread_required, &MPI_thread_provided);
203  GISMO_ENSURE(MPI_SUCCESS==init &&
204  MPI_thread_required <= MPI_thread_provided, "MPI failed to initialize");
205 #else
206  //Note: valgrind false positive here, see
207  // https://www.open-mpi.org/faq/?category=debugging#valgrind_clean
208  const int init = MPI_Init(argc, &argv);
209  GISMO_ENSURE(MPI_SUCCESS==init, "MPI failed to initialize");
210 #endif
211  }
212 # ifndef NDEBUG
213  MPI_Comm_create_errhandler(gsMpiComm::ErrCallBack, &gsMpiComm::ErrHandler);
214  MPI_Comm_set_errhandler(worldComm(), gsMpiComm::ErrHandler);
215 # endif
216 # else
217  GISMO_UNUSED(argc);
218  GISMO_UNUSED(argv);
219 # endif
220  //gsDebug << "Called MPI_Init on p=" << rank_ << "!" << std::endl;
221  }
222 
225  {
226 # ifdef GISMO_WITH_MPI
227  int wasFinalized = -1;
228  MPI_Finalized( &wasFinalized );
229  if( 0 == wasFinalized)
230  {
231  MPI_Finalize();
232  }
233 # endif
234  //gsDebug << "Called MPI_Finalize on p=" << rank_ << "!" <<std::endl;
235  }
236 
237  gsMpi(const gsMpi&);
238  gsMpi& operator=(const gsMpi&);
239 
240 };
241 
242 }
int rank() const
return rank of process, i.e. zero
Definition: gsMpiComm.h:297
#define GISMO_ENSURE(cond, message)
Definition: gsDebug.h:102
#define GISMO_ASSERT(cond, message)
Definition: gsDebug.h:89
Various helper classes derived from from std::binary_function for stl-style functional programming...
~gsMpi()
calls MPI_Finalize
Definition: gsMpi.h:224
A wrapper for MPI communicators.
gsMpi & gsMpiSingleton(const int &argc, char **argv)
Singleton function returning the gsMpi helper object.
Definition: gsMpi.cpp:9
Provides forward declarations of types and structs.
static int size()
return rank of process, i.e. one
Definition: gsMpiComm.h:302
Traits classes for mapping types onto MPI_Datatype.
#define GISMO_UNUSED(x)
Definition: gsDebug.h:112
#define GISMO_ERROR(message)
Definition: gsDebug.h:118