MADNESS  version 0.9
safempi.h
Go to the documentation of this file.
1 /*
2  This file is part of MADNESS.
3 
4  Copyright (C) 2007,2010 Oak Ridge National Laboratory
5 
6  This program is free software; you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation; either version 2 of the License, or
9  (at your option) any later version.
10 
11  This program is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with this program; if not, write to the Free Software
18  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 
20  For more information please contact:
21 
22  Robert J. Harrison
23  Oak Ridge National Laboratory
24  One Bethel Valley Road
25  P.O. Box 2008, MS-6367
26 
27  email: harrisonrj@ornl.gov
28  tel: 865-241-3937
29  fax: 865-572-0680
30 
31  $Id$
32 */
33 #ifndef MADNESS_WORLD_SAFEMPI_H__INCLUDED
34 #define MADNESS_WORLD_SAFEMPI_H__INCLUDED
35 
38 
39 #include <madness/madness_config.h>
40 
41 // Jeff's original comments:
42 // It is not safe to undefine this because the MPI mutex protects static variables.
43 // One needs thread-local storage or something similar if MPI_THREAD_MULTIPLE is to be used.
44 // Jeff's new comments:
45 // I can't remember where the static stuff is that scared me but it must be found and properly
46 // protected. We really need to be able to use MPI_THREAD_MULTIPLE on BGQ.
47 #if MADNESS_MPI_THREAD_LEVEL == MPI_THREAD_SERIALIZED
48 # define MADNESS_SERIALIZES_MPI
49 #endif
50 
51 #ifdef STUBOUTMPI
52 #include <madness/world/stubmpi.h>
53 #else
54 
55 //#ifdef SEEK_SET
56 //#undef SEEK_SET
57 //#endif
58 //#ifdef SEEK_CUR
59 //#undef SEEK_CUR
60 //#endif
61 //#ifdef SEEK_END
62 //#undef SEEK_END
63 //#endif
64 
65 #include <mpi.h>
66 #endif
67 
72 #include <iostream>
73 #include <cstring>
74 
75 #define MADNESS_MPI_TEST(condition) \
76  { \
77  int mpi_error_code = condition; \
78  if(mpi_error_code != MPI_SUCCESS) throw ::SafeMPI::Exception(mpi_error_code); \
79  }
80 
81 namespace SafeMPI {
82 
83 #ifdef MADNESS_SERIALIZES_MPI
84  extern madness::SCALABLE_MUTEX_TYPE charon; // Inside safempi.cc
85 #define SAFE_MPI_GLOBAL_MUTEX madness::ScopedMutex<madness::SCALABLE_MUTEX_TYPE> obolus(SafeMPI::charon)
86 #else
87 #define SAFE_MPI_GLOBAL_MUTEX
88 #endif
89 
97 
98  static const int RMI_TAG = 1023;
99  static const int RMI_HUGE_ACK_TAG = 1022;
100  static const int RMI_HUGE_DAT_TAG = 1021;
101  static const int MPIAR_TAG = 1001;
102  static const int DEFAULT_SEND_RECV_TAG = 1000;
103 
104  // Forward declarations
105  class Intracomm;
106  extern Intracomm COMM_WORLD;
107  inline int Finalize();
108 
110 
112  inline bool Is_initialized() {
113  int initialized = 0;
114  MPI_Initialized(&initialized);
115  return (initialized != 0);
116  }
117 
119 
121  inline bool Is_finalized() {
122  int flag = 0;
123  MPI_Finalized(&flag);
124  return flag != 0;
125  }
126 
127  namespace detail {
129  inline void init_comm_world();
130 
131  inline void print_mpi_error(const int rc, const char* function,
132  const int line, const char* file)
133  {
134  int len = 0;
135  char error_string[MPI_MAX_ERROR_STRING];
136  MPI_Error_string(rc, error_string, &len);
137  std::cerr << "!!! MPI ERROR (" << rc << ") in " << function <<
138  " at " << file << "(" << line << "): " << error_string << "\n";
139  }
140 
141  } // namespace detail
142 
144 
146  class Exception : public std::exception {
147  private:
148  char mpi_error_string_[MPI_MAX_ERROR_STRING];
149 
150  public:
151 
152  Exception(const int mpi_error) throw() {
153  int len = 0;
154  if(MPI_Error_string(mpi_error, mpi_error_string_, &len) != MPI_SUCCESS)
155  std::strncpy(mpi_error_string_, "UNKNOWN MPI ERROR!", MPI_MAX_ERROR_STRING);
156  }
157 
158  Exception(const Exception& other) throw() {
159  std::strncpy(mpi_error_string_, other.mpi_error_string_, MPI_MAX_ERROR_STRING);
160  }
161 
162  Exception& operator=(const Exception& other) {
163  std::strncpy(mpi_error_string_, other.mpi_error_string_, MPI_MAX_ERROR_STRING);
164  return *this;
165  }
166 
167  virtual ~Exception() throw() { }
168 
169  virtual const char* what() const throw() { return mpi_error_string_; }
170 
171  friend std::ostream& operator<<(std::ostream& os, const Exception& e) {
172  os << e.what();
173  return os;
174  }
175  }; // class Exception
176 
177 
178  class Status {
179  private:
180  MPI_Status status_;
181 
182  public:
183  // Constructors
184  Status(void) : status_() { }
185  Status(const Status &other) : status_(other.status_) { }
186  Status(MPI_Status other) : status_(other) { }
187 
188  // Assignment operators
189  Status& operator=(const Status &other) {
190  status_ = other.status_;
191  return *this;
192  }
193 
194  Status& operator=(const MPI_Status other) {
195  status_ = other;
196  return *this;
197  }
198 
199  // C/C++ cast and assignment
200  operator MPI_Status*() { return &status_; }
201 
202  operator MPI_Status() const { return status_; }
203 
204 // bool Is_cancelled() const {
205 // int flag = 0;
206 // MADNESS_MPI_TEST(MPI_Test_cancelled(const_cast<MPI_Status*>(&status_), &flag));
207 // return flag != 0;
208 // }
209 //
210 // int Get_elements(const MPI_Datatype datatype) const {
211 // int elements = 0;
212 // MADNESS_MPI_TEST(MPI_Get_elements(const_cast<MPI_Status*>(&status_), datatype, &elements));
213 // return elements;
214 // }
215 
216  int Get_count(const MPI_Datatype datatype) const {
217  int count = 0;
218  MADNESS_MPI_TEST(MPI_Get_count(const_cast<MPI_Status*>(&status_), datatype, &count));
219  return count;
220  }
221 
222 // void Set_cancelled(bool flag) {
223 // MADNESS_MPI_TEST(MPI_Status_set_cancelled(&status_, flag));
224 // }
225 //
226 // void Set_elements( const MPI_Datatype &v2, int v3 ) {
227 // MADNESS_MPI_TEST(MPI_Status_set_elements(&status_, v2, v3 ));
228 // }
229 
230  int Get_source() const { return status_.MPI_SOURCE; }
231 
232  int Get_tag() const { return status_.MPI_TAG; }
233 
234  int Get_error() const { return status_.MPI_ERROR; }
235 
236  void Set_source(int source) { status_.MPI_SOURCE = source; }
237 
238  void Set_tag(int tag) { status_.MPI_TAG = tag; }
239 
240  void Set_error(int error) { status_.MPI_ERROR = error; }
241  }; // class Status
242 
243  class Request {
244  // Note: This class was previously derived from MPI::Request, but this
245  // was changed with the removal of the MPI C++ bindings. Now this class
246  // only implements the minumum functionality required by MADNESS. Feel
247  // free to add more functionality as needed.
248 
249  private:
250  MPI_Request request_;
251 
252  public:
253 
254  // Constructors
255  Request() : request_(MPI_REQUEST_NULL) { }
256  Request(MPI_Request other) : request_(other) { }
257  Request(const Request& other) : request_(other.request_) { }
258 
259  // Assignment operators
260  Request& operator=(const Request &other) {
261  request_ = other.request_;
262  return *this;
263  }
264 
265  Request& operator=(const MPI_Request& other) {
266  request_ = other;
267  return *this;
268  }
269 
270  // logical
271  bool operator==(const Request &other) { return (request_ == other.request_); }
272  bool operator!=(const Request &other) { return (request_ != other.request_); }
273 
274  // C/C++ cast and assignment
275  operator MPI_Request*() { return &request_; }
276  operator MPI_Request() const { return request_; }
277 
278  static bool Testany(int count, Request* requests, int& index, Status& status) {
279  MADNESS_ASSERT(requests != NULL);
280  int flag;
281  madness::ScopedArray<MPI_Request> mpi_requests(new MPI_Request[count]);
282 
283  // Copy requests to an array that can be used by MPI
284  for(int i = 0; i < count; ++i)
285  mpi_requests[i] = requests[i].request_;
286  {
288  MADNESS_MPI_TEST(MPI_Testany(count, mpi_requests.get(), &index, &flag, status));
289  }
290  // Copy results from MPI back to the original array
291  for(int i = 0; i < count; ++i)
292  requests[i].request_ = mpi_requests[i];
293  return flag != 0;
294  }
295 
296  static bool Testany(int count, Request* requests, int& index) {
297  MADNESS_ASSERT(requests != NULL);
298  int flag;
299  madness::ScopedArray<MPI_Request> mpi_requests(new MPI_Request[count]);
300 
301  // Copy requests to an array that can be used by MPI
302  for(int i = 0; i < count; ++i)
303  mpi_requests[i] = requests[i].request_;
304  {
306  MADNESS_MPI_TEST(MPI_Testany(count, mpi_requests.get(), &index, &flag, MPI_STATUS_IGNORE));
307  }
308  // Copy results from MPI back to the original array
309  for(int i = 0; i < count; ++i)
310  requests[i] = mpi_requests[i];
311  return flag != 0;
312  }
313 
314  static int Testsome(int incount, Request* requests, int* indices, Status* statuses) {
315  MADNESS_ASSERT(requests != NULL);
316  MADNESS_ASSERT(indices != NULL);
317  MADNESS_ASSERT(statuses != NULL);
318 
319  int outcount = 0;
320  madness::ScopedArray<MPI_Request> mpi_requests(new MPI_Request[incount]);
321  madness::ScopedArray<MPI_Status> mpi_statuses(new MPI_Status[incount]);
322  for(int i = 0; i < incount; ++i)
323  mpi_requests[i] = requests[i].request_;
324  {
326  MADNESS_MPI_TEST( MPI_Testsome( incount, mpi_requests.get(), &outcount, indices, mpi_statuses.get()));
327  }
328  for(int i = 0; i < incount; ++i) {
329  requests[i] = mpi_requests[i];
330  statuses[i] = mpi_statuses[i];
331  }
332  return outcount;
333  }
334 
335  static int Testsome(int incount, Request* requests, int* indices) {
336  int outcount = 0;
337  madness::ScopedArray<MPI_Request> mpi_requests(new MPI_Request[incount]);
338  for(int i = 0; i < incount; ++i)
339  mpi_requests[i] = requests[i].request_;
340  {
342  MADNESS_MPI_TEST( MPI_Testsome( incount, mpi_requests.get(), &outcount, indices, MPI_STATUSES_IGNORE));
343  }
344  for(int i = 0; i < incount; ++i)
345  requests[i] = mpi_requests[i];
346  return outcount;
347  }
348 
349 
351  int flag;
352  MADNESS_MPI_TEST(MPI_Test(&request_, &flag, &status));
353  return flag != 0;
354  }
355 
356  bool Test(MPI_Status& status) {
358  return Test_got_lock_already(status);
359  }
360 
362  int flag;
363  MADNESS_MPI_TEST(MPI_Test(&request_, &flag, MPI_STATUS_IGNORE));
364  return flag != 0;
365  }
366 
367  bool Test() {
369  return Test_got_lock_already();
370  }
371  }; // class Request
372 
375  class Group {
376  public:
377  Group Incl(int n, const int* ranks) const {
378  // MPI <3 interface lacks explicit const sanitation
379  Group result(std::shared_ptr<Impl>(new Impl(*pimpl, n, const_cast<int*>(ranks))));
380  return result;
381  }
382 
383  void Translate_ranks(int nproc, const int* ranks1, const Group& grp2, int* ranks2) const {
384  // MPI <3 interface lacks explicit const sanitation
385  MADNESS_ASSERT(pimpl);
386  MADNESS_MPI_TEST(MPI_Group_translate_ranks(pimpl->group, nproc,
387  const_cast<int*>(ranks1), grp2.pimpl->group, ranks2));
388  }
389 
390  MPI_Group group() const {
391  MADNESS_ASSERT(pimpl);
392  return pimpl->group;
393  }
394 
395  Group(const Group& other) : pimpl(other.pimpl) { }
396 
397  private:
398 
399  struct Impl {
401 
402  Impl(MPI_Comm comm) {
403  MADNESS_MPI_TEST(MPI_Comm_group(comm, &group));
404  }
405 
406  Impl(const Impl& other, int n, const int* ranks) {
407  // MPI <3 interface lacks explicit const sanitation
408  MADNESS_MPI_TEST(MPI_Group_incl(other.group, n,
409  const_cast<int*>(ranks), & group));
410  }
411 
412  ~Impl() {
413  if(Is_initialized()) {
414  const int mpi_error_code = MPI_Group_free(&group);
415  if(mpi_error_code != MPI_SUCCESS)
416  ::SafeMPI::detail::print_mpi_error(mpi_error_code,
417  "SafeMPI::Group::Impl::~Impl()", __LINE__, __FILE__);
418  }
419  }
420 
421  }; // struct Impl
422 
423  friend class Intracomm;
424 
425  Group() : pimpl() { }
426 
427  // only Intracomm will use this
428  Group(MPI_Comm comm) : pimpl(new Impl(comm)) { }
429 
430  // only myself will use this
431  Group(const std::shared_ptr<Impl>& p) : pimpl(p) { }
432 
433  std::shared_ptr<Impl> pimpl;
434  }; // class Group
435 
437  class Intracomm {
438 
439  static bool Comm_compare(const MPI_Comm& comm1, const MPI_Comm& comm2) {
440  int compare_result;
441  const int result = MPI_Comm_compare(comm1, comm2, &compare_result);
442  return ((result == MPI_SUCCESS) && (compare_result == MPI_IDENT));
443  }
444 
445  struct Impl {
446  MPI_Comm comm;
447  int me;
448  int numproc;
449  bool owner;
450 
451  volatile int utag;
452  volatile int urtag;
453 
454  Impl(const MPI_Comm& c, int m, int n, bool o) :
455  comm(c), me(m), numproc(n), owner(o), utag(1024), urtag(1)
456  { }
457 
458  ~Impl() {
459  if(owner && Is_initialized() && !Is_finalized() && !Comm_compare(comm, MPI_COMM_WORLD)) {
460  MPI_Comm_free(&comm);
461  }
462  }
463 
465 
473  int unique_tag() {
475  int result = utag++;
476  if (utag >= 4095) utag = 1024;
477  return result;
478  }
479 
481 
485  int unique_reserved_tag() {
487  int result = urtag++;
488  if (result >= 1000) MADNESS_EXCEPTION( "too many reserved tags in use" , result );
489  return result;
490  }
491 
492  };
493  std::shared_ptr<Impl> pimpl;
494 
495  friend void SafeMPI::detail::init_comm_world();
496  friend int Finalize();
497 
498  // For internal use only. Do not try to call this constructor. It is
499  // only used to construct Intarcomm in Create().
500  Intracomm(const std::shared_ptr<Impl>& i) : pimpl(i) { }
501 
502  // Not allowed
503  Intracomm& operator=(const Intracomm& other);
504 
505  public:
506  struct WorldInitObject;
507 
508  // For internal use only. Do not try to call this constructor. It is
509  // only used to construct COMM_WORLD.
510  Intracomm(const WorldInitObject&);
511 
512  explicit Intracomm(const MPI_Comm& comm, bool take_ownership_of_comm = true) :
513  pimpl()
514  {
515  MADNESS_ASSERT(Is_initialized());
516  int rank = -1, size = -1;
517  MADNESS_MPI_TEST(MPI_Comm_rank(comm, &rank));
518  MADNESS_MPI_TEST(MPI_Comm_size(comm, &size));
519  take_ownership_of_comm =
520  take_ownership_of_comm && (! Comm_compare(comm, MPI_COMM_WORLD));
521  pimpl.reset(new Impl(comm, rank, size, take_ownership_of_comm));
522  }
523 
524  Intracomm(const Intracomm& other) : pimpl(other.pimpl) { }
525 
527 
539  Intracomm Create(Group group) const {
540  MADNESS_ASSERT(pimpl);
542  MPI_Comm group_comm;
543  MADNESS_MPI_TEST(MPI_Comm_create(pimpl->comm, group.group(), &group_comm));
544  int me; MADNESS_MPI_TEST(MPI_Comm_rank(group_comm, &me));
545  int nproc; MADNESS_MPI_TEST(MPI_Comm_size(group_comm, &nproc));
546  return Intracomm(std::shared_ptr<Impl>(new Impl(group_comm, me, nproc, true)));
547  }
548 
549  bool operator==(const Intracomm& other) const {
550  return (pimpl == other.pimpl) || ((pimpl && other.pimpl) &&
551  Comm_compare(pimpl->comm, other.pimpl->comm));
552  }
553 
558  Group Get_group() const {
559  MADNESS_ASSERT(pimpl);
561  Group group(pimpl->comm);
562  return group;
563  }
564 
566  MADNESS_ASSERT(pimpl);
567  return pimpl->comm;
568  }
569 
570  int Get_rank() const {
571  MADNESS_ASSERT(pimpl);
572  return pimpl->me;
573  }
574 
575  int Get_size() const {
576  MADNESS_ASSERT(pimpl);
577  return pimpl->numproc;
578  }
579 
580  Request Isend(const void* buf, const int count, const MPI_Datatype datatype, const int dest, const int tag) const {
581  MADNESS_ASSERT(pimpl);
583  Request request;
584  MADNESS_MPI_TEST(MPI_Isend(const_cast<void*>(buf), count, datatype, dest,tag, pimpl->comm, request));
585  return request;
586  }
587 
588  Request Irecv(void* buf, const int count, const MPI_Datatype datatype, const int src, const int tag) const {
589  MADNESS_ASSERT(pimpl);
591  Request request;
592  MADNESS_MPI_TEST(MPI_Irecv(buf, count, datatype, src, tag, pimpl->comm, request));
593  return request;
594  }
595 
596  void Send(const void* buf, const int count, const MPI_Datatype datatype, int dest, int tag) const {
597  MADNESS_ASSERT(pimpl);
599  MADNESS_MPI_TEST(MPI_Send(const_cast<void*>(buf), count, datatype, dest, tag, pimpl->comm));
600  }
601 
602 #ifdef MADNESS_USE_BSEND_ACKS
603  void Bsend(const void* buf, size_t count, const MPI_Datatype datatype, int dest, int tag) const {
604  MADNESS_ASSERT(pimpl);
606  if (count>10 || datatype!=MPI_BYTE) MADNESS_EXCEPTION("Bsend: this protocol is only for 1-byte acks", count );
607  MADNESS_MPI_TEST(MPI_Bsend(const_cast<void*>(buf), count, datatype, dest, tag, pimpl->comm));
608  }
609 #endif // MADNESS_USE_BSEND_ACKS
610 
611  void Recv(void* buf, const int count, const MPI_Datatype datatype, const int source, const int tag, MPI_Status& status) const {
612  MADNESS_ASSERT(pimpl);
614  MADNESS_MPI_TEST(MPI_Recv(buf, count, datatype, source, tag, pimpl->comm, &status));
615  }
616 
617  void Recv(void* buf, const int count, const MPI_Datatype datatype, const int source, const int tag) const {
618  MADNESS_ASSERT(pimpl);
620  MADNESS_MPI_TEST(MPI_Recv(buf, count, datatype, source, tag, pimpl->comm, MPI_STATUS_IGNORE));
621  }
622 
623  void Bcast(void* buf, size_t count, const MPI_Datatype datatype, const int root) const {
624  MADNESS_ASSERT(pimpl);
626  MADNESS_MPI_TEST(MPI_Bcast(buf, count, datatype, root, pimpl->comm));
627  }
628 
629  void Reduce(const void* sendbuf, void* recvbuf, const int count, const MPI_Datatype datatype, const MPI_Op op, const int root) const {
630  MADNESS_ASSERT(pimpl);
632  MADNESS_MPI_TEST(MPI_Reduce(const_cast<void*>(sendbuf), recvbuf, count, datatype, op, root, pimpl->comm));
633  }
634 
635  void Allreduce(const void* sendbuf, void* recvbuf, const int count, const MPI_Datatype datatype, const MPI_Op op) const {
636  MADNESS_ASSERT(pimpl);
638  MADNESS_MPI_TEST(MPI_Allreduce(const_cast<void*>(sendbuf), recvbuf, count, datatype, op, pimpl->comm));
639  }
640  bool Get_attr(int key, void* value) const {
641  MADNESS_ASSERT(pimpl);
642  int flag = 0;
644  MADNESS_MPI_TEST(MPI_Comm_get_attr(pimpl->comm, key, value, &flag));
645  return flag != 0;
646  }
647 
648  void Abort(int code=1) const {
649  MPI_Abort(pimpl->comm, code);
650  }
651 
652  void Barrier() const {
653  MADNESS_ASSERT(pimpl);
655  MADNESS_MPI_TEST(MPI_Barrier(pimpl->comm));
656  }
657 
659 
667  int unique_tag() {
668  MADNESS_ASSERT(pimpl);
669  return pimpl->unique_tag();
670  }
671 
673 
678  MADNESS_ASSERT(pimpl);
679  return pimpl->unique_reserved_tag();
680  }
681 
683 
688  void binary_tree_info(int root, int& parent, int& child0, int& child1);
689 
690  }; // class Intracomm
691 
692  namespace detail {
693 
695  inline void init_comm_world() {
696  MADNESS_MPI_TEST(MPI_Comm_rank(COMM_WORLD.pimpl->comm, & COMM_WORLD.pimpl->me));
697  MADNESS_MPI_TEST(MPI_Comm_size(COMM_WORLD.pimpl->comm, & COMM_WORLD.pimpl->numproc));
698  }
699 
700  } // namespace detail
701 
702 
704 
709  inline int Init_thread(int & argc, char **& argv, int requested) {
710  int provided = 0;
711  MADNESS_MPI_TEST(MPI_Init_thread(&argc, &argv, requested, &provided));
713  return provided;
714  }
715 
717 
720  inline int Init_thread(int requested) {
721  int argc = 0;
722  char** argv = NULL;
723  return SafeMPI::Init_thread(argc, argv, requested);
724  }
725 
727 
730  inline void Init(int &argc, char **&argv) {
731  MADNESS_MPI_TEST(MPI_Init(&argc, &argv));
733  }
734 
736  inline void Init() {
737  int argc = 0;
738  char** argv = NULL;
739  SafeMPI::Init(argc,argv);
740  }
741 
743 
749  inline int Finalize() {
750  SafeMPI::COMM_WORLD.pimpl.reset();
751  const int result = MPI_Finalize();
752  return result;
753  }
754 
756 
758  inline int Query_thread() {
759  int provided;
761  return provided;
762  }
763 
765 
767  inline double Wtime() { return MPI_Wtime(); }
768 
770 
773  inline void Attach_buffer(void* buffer, int size) {
774  MADNESS_MPI_TEST(MPI_Buffer_attach(buffer, size));
775  }
776 
778 
780  inline int Detach_buffer(void *&buffer) {
781  int size = 0;
782  MPI_Buffer_detach(&buffer, &size);
783  return size;
784  }
785 } // namespace SafeMPI
786 
787 #endif // MADNESS_WORLD_SAFEMPI_H__INCLUDED
void Attach_buffer(void *buffer, int size)
Set buffer for Bsend .
Definition: safempi.h:773
Mutex using pthread mutex operations.
Definition: worldmutex.h:94
Request Isend(const void *buf, const int count, const MPI_Datatype datatype, const int dest, const int tag) const
Definition: safempi.h:580
void Barrier() const
Definition: safempi.h:652
int MPI_Irecv(void *, int, MPI_Datatype, int, int, MPI_Comm, MPI_Request *)
Definition: stubmpi.h:156
void Recv(void *buf, const int count, const MPI_Datatype datatype, const int source, const int tag, MPI_Status &status) const
Definition: safempi.h:611
int MPI_Recv(void *, int, MPI_Datatype, int, int, MPI_Comm, MPI_Status *)
Definition: stubmpi.h:157
int unique_reserved_tag()
Returns a unique tag reserved for long-term use (0
Definition: safempi.h:677
Status(const Status &other)
Definition: safempi.h:185
int MPI_Query_thread(int *provided)
Definition: stubmpi.h:121
Wrapper around MPI_Comm. Has a shallow copy constructor; use Create(Get_group()) for deep copy...
Definition: safempi.h:437
bool Is_initialized()
Check MPI initialization status.
Definition: safempi.h:112
Request & operator=(const Request &other)
Definition: safempi.h:260
int MPI_Comm_get_attr(MPI_Comm, int, void *, int *)
Definition: stubmpi.h:172
int MPI_Comm_group(MPI_Comm, MPI_Group *group)
Definition: stubmpi.h:183
int MPI_Bcast(void *, int, MPI_Datatype, int, MPI_Comm)
Definition: stubmpi.h:160
Status(MPI_Status other)
Definition: safempi.h:186
int MPI_Comm_rank(MPI_Comm, int *rank)
Definition: stubmpi.h:149
Group Get_group() const
Definition: safempi.h:558
int MPI_Comm_compare(MPI_Comm comm1, MPI_Comm comm2, int *result)
Definition: stubmpi.h:193
int Finalize()
Analogous to MPI_Finalize.
Definition: safempi.h:749
int MPI_Buffer_attach(void *, int)
Definition: stubmpi.h:124
char * strncpy()
void Reduce(const void *sendbuf, void *recvbuf, const int count, const MPI_Datatype datatype, const MPI_Op op, const int root) const
Definition: safempi.h:629
Intracomm(const MPI_Comm &comm, bool take_ownership_of_comm=true)
Definition: safempi.h:512
Definition: safempi.h:375
Grossly simplified Boost-like type traits and templates.
int MPI_Testsome(int, MPI_Request *, int *outcount, int *, MPI_Status *)
Definition: stubmpi.h:138
#define MPI_STATUSES_IGNORE
Definition: stubmpi.h:20
int MPI_Group
Definition: stubmpi.h:9
void Set_tag(int tag)
Definition: safempi.h:238
void init_comm_world()
Initialize SafeMPI::COMM_WORLD.
Definition: safempi.h:695
int Get_tag() const
Definition: safempi.h:232
virtual ~Exception()
Definition: safempi.h:167
static bool Testany(int count, Request *requests, int &index, Status &status)
Definition: safempi.h:278
void Translate_ranks(int nproc, const int *ranks1, const Group &grp2, int *ranks2) const
Definition: safempi.h:383
Exception(const int mpi_error)
Definition: safempi.h:152
void Set_source(int source)
Definition: safempi.h:236
int Get_size() const
Definition: safempi.h:575
int MPI_Finalized(int *flag)
Definition: stubmpi.h:120
POD holding excitation energy and response vector for a single excitation.
Definition: tdhf_CIS.h:134
Group(const Group &other)
Definition: safempi.h:395
int Get_count(const MPI_Datatype datatype) const
Definition: safempi.h:216
void Allreduce(const void *sendbuf, void *recvbuf, const int count, const MPI_Datatype datatype, const MPI_Op op) const
Definition: safempi.h:635
#define MPI_COMM_WORLD
Definition: stubmpi.h:23
void Abort(int code=1) const
Definition: safempi.h:648
int MPI_Error_string(int errorcode, char *string, int *resultlen)
Definition: stubmpi.h:203
bool Test(MPI_Status &status)
Definition: safempi.h:356
int Detach_buffer(void *&buffer)
Unset the Bsend buffer.
Definition: safempi.h:780
#define MADNESS_MPI_TEST(condition)
Definition: safempi.h:75
#define MPI_BYTE
Definition: stubmpi.h:66
int MPI_Bsend(void *, int, MPI_Datatype, int, int, MPI_Comm)
Definition: stubmpi.h:155
int MPI_Group_incl(MPI_Group group, int n, const int ranks[], MPI_Group *newgroup)
Definition: stubmpi.h:106
int MPI_Init_thread(int *, char ***, int, int *provided)
Definition: stubmpi.h:117
int MPI_Comm_free(MPI_Comm *comm)
Definition: stubmpi.h:188
int MPI_Test(MPI_Request *, int *flag, MPI_Status *)
Definition: stubmpi.h:127
int MPI_Comm_create(MPI_Comm, MPI_Group, MPI_Comm *newcomm)
Definition: stubmpi.h:178
Exception & operator=(const Exception &other)
Definition: safempi.h:162
int MPI_Reduce(void *sendbuf, void *recvbuf, int count, MPI_Datatype, MPI_Op, int, MPI_Comm)
Definition: stubmpi.h:163
virtual const char * what() const
Definition: safempi.h:169
Intracomm(const Intracomm &other)
Definition: safempi.h:524
int unique_tag()
Returns a unique tag for temporary use (1023
Definition: safempi.h:667
int MPI_Isend(void *, int, MPI_Datatype, int, int, MPI_Comm, MPI_Request *)
Definition: stubmpi.h:153
int MPI_Get_count(MPI_Status *, MPI_Datatype, int *count)
Definition: stubmpi.h:143
Status(void)
Definition: safempi.h:184
double Wtime()
Wall time.
Definition: safempi.h:767
void Recv(void *buf, const int count, const MPI_Datatype datatype, const int source, const int tag) const
Definition: safempi.h:617
bool operator==(const Request &other)
Definition: safempi.h:271
int MPI_Testany(int, MPI_Request[], int *index, int *flag, MPI_Status *)
Definition: stubmpi.h:132
#define MPI_IDENT
Definition: stubmpi.h:34
Status & operator=(const Status &other)
Definition: safempi.h:189
Exception(const Exception &other)
Definition: safempi.h:158
int Init_thread(int &argc, char **&argv, int requested)
Analogous to MPI_Init_thread.
Definition: safempi.h:709
friend std::ostream & operator<<(std::ostream &os, const Exception &e)
Definition: safempi.h:171
int MPI_Comm
Definition: stubmpi.h:22
Intracomm Create(Group group) const
Definition: safempi.h:539
MPI_Comm & Get_mpi_comm() const
Definition: safempi.h:565
int MPI_Group_translate_ranks(const MPI_Group &, int n, const int *, const MPI_Group &, int *ranks2)
Definition: stubmpi.h:100
Request()
Definition: safempi.h:255
int Get_source() const
Definition: safempi.h:230
#define MPI_STATUS_IGNORE
Definition: stubmpi.h:19
MPI_Group group() const
Definition: safempi.h:390
int MPI_Group_free(MPI_Group *group)
Definition: stubmpi.h:111
SafeMPI exception object.
Definition: safempi.h:146
double MPI_Wtime()
Definition: stubmpi.h:225
int MPI_Init(int *, char ***)
Definition: stubmpi.h:116
int MPI_Buffer_detach(void *buffer, int *size)
Definition: stubmpi.h:125
#define SAFE_MPI_GLOBAL_MUTEX
Definition: safempi.h:85
Implements Mutex, MutexFair, Spinlock, ConditionVariable.
int Query_thread()
Analogous to MPI_Query_thread.
Definition: safempi.h:758
int MPI_Initialized(int *flag)
Definition: stubmpi.h:118
bool initialized()
Definition: world.cc:70
int MPI_Op
Definition: stubmpi.h:83
void Init(int &argc, char **&argv)
Analogous to MPI_Init.
Definition: safempi.h:730
int Get_rank() const
Definition: safempi.h:570
void error(const char *msg, int code)
Definition: oldtest.cc:57
static int Testsome(int incount, Request *requests, int *indices)
Definition: safempi.h:335
Group Incl(int n, const int *ranks) const
Definition: safempi.h:377
Request(const Request &other)
Definition: safempi.h:257
void binary_tree_info(int root, int &parent, int &child0, int &child1)
Construct info about a binary tree with given root.
Definition: safempi.cc:42
static bool Testany(int count, Request *requests, int &index)
Definition: safempi.h:296
int MPI_Send(void *, int, MPI_Datatype, int, int, MPI_Comm)
Definition: stubmpi.h:154
Request(MPI_Request other)
Definition: safempi.h:256
int Get_error() const
Definition: safempi.h:234
Scoped array.
Definition: scopedptr.h:85
bool Test_got_lock_already()
Definition: safempi.h:361
int MPI_TAG
Definition: stubmpi.h:15
#define MPI_REQUEST_NULL
Definition: stubmpi.h:44
const double m
Definition: gfit.cc:199
Definition: safempi.h:243
void reset()
Definition: shared_ptr_bits.h:459
int MPI_SOURCE
Definition: stubmpi.h:14
bool Is_finalized()
Check MPI finalization status.
Definition: safempi.h:121
Definition: stubmpi.h:11
#define MPI_MAX_ERROR_STRING
Definition: stubmpi.h:31
bool operator==(const Intracomm &other) const
Definition: safempi.h:549
bool Test_got_lock_already(MPI_Status &status)
Definition: safempi.h:350
ptrT * get() const
Pointer accessor.
Definition: scopedptr.h:266
Intracomm COMM_WORLD
Definition: safempi.cc:70
Definition: safempi.cc:36
int MPI_Comm_size(MPI_Comm, int *size)
Definition: stubmpi.h:150
void Bcast(void *buf, size_t count, const MPI_Datatype datatype, const int root) const
Definition: safempi.h:623
madness::SCALABLE_MUTEX_TYPE charon
bool operator!=(const Request &other)
Definition: safempi.h:272
Tensor< double > op(const Tensor< double > &x)
Definition: kain.cc:508
void Set_error(int error)
Definition: safempi.h:240
Request Irecv(void *buf, const int count, const MPI_Datatype datatype, const int src, const int tag) const
Definition: safempi.h:588
#define MADNESS_EXCEPTION(msg, value)
Definition: worldexc.h:88
void print_mpi_error(const int rc, const char *function, const int line, const char *file)
Definition: safempi.h:131
Request & operator=(const MPI_Request &other)
Definition: safempi.h:265
friend int Finalize()
Analogous to MPI_Finalize.
Definition: safempi.h:749
bool Test()
Definition: safempi.h:367
int MPI_Allreduce(void *sendbuf, void *recvbuf, int count, MPI_Datatype, MPI_Op, MPI_Comm)
Definition: stubmpi.h:167
struct MPI_Status MPI_Status
int MPI_Datatype
Definition: stubmpi.h:62
int MPI_Barrier(MPI_Comm)
Definition: stubmpi.h:176
Status & operator=(const MPI_Status other)
Definition: safempi.h:194
void Send(const void *buf, const int count, const MPI_Datatype datatype, int dest, int tag) const
Definition: safempi.h:596
~Intracomm()
Definition: safempi.h:526
const double c
Definition: gfit.cc:200
static int Testsome(int incount, Request *requests, int *indices, Status *statuses)
Definition: safempi.h:314
bool Get_attr(int key, void *value) const
Definition: safempi.h:640
Definition: safempi.h:178
int MPI_Request
Definition: stubmpi.h:10
int MPI_Finalize()
Definition: stubmpi.h:119
#define MPI_SUCCESS
Definition: stubmpi.h:28
int MPI_ERROR
Definition: stubmpi.h:16
int MPI_Abort(MPI_Comm, int code)
Definition: stubmpi.h:174