MPIWrapper.hpp
Go to the documentation of this file.
1 /*
2  * STRUMPACK -- STRUctured Matrices PACKage, Copyright (c) 2014, The
3  * Regents of the University of California, through Lawrence Berkeley
4  * National Laboratory (subject to receipt of any required approvals
5  * from the U.S. Dept. of Energy). All rights reserved.
6  *
7  * If you have questions about your rights to use or distribute this
8  * software, please contact Berkeley Lab's Technology Transfer
9  * Department at TTD@lbl.gov.
10  *
11  * NOTICE. This software is owned by the U.S. Department of Energy. As
12  * such, the U.S. Government has been granted for itself and others
13  * acting on its behalf a paid-up, nonexclusive, irrevocable,
14  * worldwide license in the Software to reproduce, prepare derivative
15  * works, and perform publicly and display publicly. Beginning five
16  * (5) years after the date permission to assert copyright is obtained
17  * from the U.S. Department of Energy, and subject to any subsequent
18  * five (5) year renewals, the U.S. Government is granted for itself
19  * and others acting on its behalf a paid-up, nonexclusive,
20  * irrevocable, worldwide license in the Software to reproduce,
21  * prepare derivative works, distribute copies to the public, perform
22  * publicly and display publicly, and to permit others to do so.
23  *
24  * Developers: Pieter Ghysels, Francois-Henry Rouet, Xiaoye S. Li.
25  * (Lawrence Berkeley National Lab, Computational Research
26  * Division).
27  *
28  */
33 #ifndef STRUMPACK_MPI_WRAPPER_HPP
34 #define STRUMPACK_MPI_WRAPPER_HPP
35 
36 #include <vector>
37 #include <complex>
38 #include <cassert>
39 #include <numeric>
40 #include <limits>
41 #include <memory>
42 #include <utility>
43 
44 #define OMPI_SKIP_MPICXX 1
45 #include <mpi.h>
46 
47 #include "StrumpackParameters.hpp"
48 #include "Triplet.hpp"
49 
50 namespace strumpack {
51 
58  template<typename T> MPI_Datatype mpi_type() { return T::mpi_type(); }
60  template<> inline MPI_Datatype mpi_type<char>() { return MPI_CHAR; }
62  template<> inline MPI_Datatype mpi_type<bool>() { return MPI_CXX_BOOL; }
64  template<> inline MPI_Datatype mpi_type<int>() { return MPI_INT; }
66  template<> inline MPI_Datatype mpi_type<long>() { return MPI_LONG; }
68  template<> inline MPI_Datatype mpi_type<unsigned long>() { return MPI_UNSIGNED_LONG; }
70  template<> inline MPI_Datatype mpi_type<long long int>() { return MPI_LONG_LONG_INT; }
72  template<> inline MPI_Datatype mpi_type<float>() { return MPI_FLOAT; }
74  template<> inline MPI_Datatype mpi_type<double>() { return MPI_DOUBLE; }
76  template<> inline MPI_Datatype mpi_type<std::complex<float>>() { return MPI_CXX_FLOAT_COMPLEX; }
78  template<> inline MPI_Datatype mpi_type<std::complex<double>>() { return MPI_CXX_DOUBLE_COMPLEX; }
80  template<> inline MPI_Datatype mpi_type<std::pair<int,int>>() { return MPI_2INT; }
81 
83  template<> inline MPI_Datatype mpi_type<std::pair<long int,long int>>() {
84  static MPI_Datatype l_l_mpi_type = MPI_DATATYPE_NULL;
85  if (l_l_mpi_type == MPI_DATATYPE_NULL) {
86  MPI_Type_contiguous
87  (2, strumpack::mpi_type<long int>(), &l_l_mpi_type);
88  MPI_Type_commit(&l_l_mpi_type);
89  }
90  return l_l_mpi_type;
91  }
93  template<> inline MPI_Datatype mpi_type<std::pair<long long int,long long int>>() {
94  static MPI_Datatype ll_ll_mpi_type = MPI_DATATYPE_NULL;
95  if (ll_ll_mpi_type == MPI_DATATYPE_NULL) {
96  MPI_Type_contiguous
97  (2, strumpack::mpi_type<long long int>(), &ll_ll_mpi_type);
98  MPI_Type_commit(&ll_ll_mpi_type);
99  }
100  return ll_ll_mpi_type;
101  }
102 
119  class MPIRequest {
120  public:
125  req_ = std::unique_ptr<MPI_Request>(new MPI_Request());
126  }
127 
132  MPIRequest(const MPIRequest&) = delete;
133 
137  MPIRequest(MPIRequest&&) = default;
138 
142  MPIRequest& operator=(const MPIRequest&) = delete;
143 
147  MPIRequest& operator=(MPIRequest&&) = default;
148 
152  void wait() { MPI_Wait(req_.get(), MPI_STATUS_IGNORE); }
153 
154  private:
155  std::unique_ptr<MPI_Request> req_;
156  friend class MPIComm;
157  };
158 
168  inline void wait_all(std::vector<MPIRequest>& reqs) {
169  for (auto& r : reqs) r.wait();
170  reqs.clear();
171  }
172 
173  inline void wait_all(std::vector<MPI_Request>& reqs) {
174  MPI_Waitall(reqs.size(), reqs.data(), MPI_STATUSES_IGNORE);
175  }
176 
177 
190  class MPIComm {
191  public:
196  MPIComm() {}
197 
205  MPIComm(MPI_Comm c) { duplicate(c); }
206 
213  MPIComm(const MPIComm& c) { *this = c; }
214 
221  MPIComm(MPIComm&& c) noexcept { *this = std::move(c); }
222 
227  virtual ~MPIComm() {
228  if (comm_ != MPI_COMM_NULL && comm_ != MPI_COMM_WORLD)
229  MPI_Comm_free(&comm_);
230  }
231 
237  MPIComm& operator=(const MPIComm& c) {
238  if (this != &c) duplicate(c.comm());
239  return *this;
240  }
241 
248  MPIComm& operator=(MPIComm&& c) noexcept {
249  comm_ = c.comm_;
250  c.comm_ = MPI_COMM_NULL;
251  return *this;
252  }
253 
257  MPI_Comm comm() const { return comm_; }
258 
262  bool is_null() const { return comm_ == MPI_COMM_NULL; }
263 
267  int rank() const {
268  assert(comm_ != MPI_COMM_NULL);
269  int r;
270  MPI_Comm_rank(comm_, &r);
271  return r;
272  }
273 
278  int size() const {
279  assert(comm_ != MPI_COMM_NULL);
280  int nprocs;
281  MPI_Comm_size(comm_, &nprocs);
282  return nprocs;
283  }
284 
289  bool is_root() const { return rank() == 0; }
290 
295  void barrier() const { MPI_Barrier(comm_); }
296 
297  template<typename T> void
298  broadcast(std::vector<T>& sbuf) const {
299  MPI_Bcast(sbuf.data(), sbuf.size(), mpi_type<T>(), 0, comm_);
300  }
301  template<typename T> void
302  broadcast_from(std::vector<T>& sbuf, int src) const {
303  MPI_Bcast(sbuf.data(), sbuf.size(), mpi_type<T>(), src, comm_);
304  }
305 
306  template<typename T, std::size_t N> void
307  broadcast(std::array<T,N>& sbuf) const {
308  MPI_Bcast(sbuf.data(), sbuf.size(), mpi_type<T>(), 0, comm_);
309  }
310 
311  template<typename T> void
312  broadcast(T& data) const {
313  MPI_Bcast(&data, 1, mpi_type<T>(), 0, comm_);
314  }
315  template<typename T> void
316  broadcast_from(T& data, int src) const {
317  MPI_Bcast(&data, 1, mpi_type<T>(), src, comm_);
318  }
319  template<typename T> void
320  broadcast(T* sbuf, std::size_t ssize) const {
321  MPI_Bcast(sbuf, ssize, mpi_type<T>(), 0, comm_);
322  }
323  template<typename T> void
324  broadcast_from(T* sbuf, std::size_t ssize, int src) const {
325  MPI_Bcast(sbuf, ssize, mpi_type<T>(), src, comm_);
326  }
327 
328  template<typename T>
329  void all_gather(T* buf, std::size_t rsize) const {
330  MPI_Allgather
331  (MPI_IN_PLACE, 0, MPI_DATATYPE_NULL,
332  buf, rsize, mpi_type<T>(), comm_);
333  }
334 
335  template<typename T>
336  void all_gather_v(T* buf, const int* rcnts, const int* displs) const {
337  MPI_Allgatherv
338  (MPI_IN_PLACE, 0, MPI_DATATYPE_NULL, buf, rcnts, displs,
339  mpi_type<T>(), comm_);
340  }
341 
342 
356  template<typename T>
357  MPIRequest isend(const std::vector<T>& sbuf, int dest, int tag) const {
358  MPIRequest req;
359  // const_cast is necessary for ancient openmpi version used on Travis
360  MPI_Isend(const_cast<T*>(sbuf.data()), sbuf.size(), mpi_type<T>(),
361  dest, tag, comm_, req.req_.get());
362  return req;
363  }
364 
377  template<typename T>
378  void isend(const std::vector<T>& sbuf, int dest, int tag,
379  MPI_Request* req) const {
380  // const_cast is necessary for ancient openmpi version used on Travis
381  MPI_Isend(const_cast<T*>(sbuf.data()), sbuf.size(), mpi_type<T>(),
382  dest, tag, comm_, req);
383  }
384 
385  template<typename T>
386  void isend(const T* sbuf, std::size_t ssize, int dest,
387  int tag, MPI_Request* req) const {
388  // const_cast is necessary for ancient openmpi version used on Travis
389  MPI_Isend(const_cast<T*>(sbuf), ssize, mpi_type<T>(),
390  dest, tag, comm_, req);
391  }
392  template<typename T>
393  void send(const T* sbuf, std::size_t ssize, int dest, int tag) const {
394  // const_cast is necessary for ancient openmpi version used on Travis
395  MPI_Send(const_cast<T*>(sbuf), ssize, mpi_type<T>(), dest, tag, comm_);
396  }
397 
398  template<typename T>
399  void isend(const T& buf, int dest, int tag, MPI_Request* req) const {
400  // const_cast is necessary for ancient openmpi version used on Travis
401  MPI_Isend(const_cast<T*>(&buf), 1, mpi_type<T>(),
402  dest, tag, comm_, req);
403  }
404 
418  template<typename T>
419  void send(const std::vector<T>& sbuf, int dest, int tag) const {
420  // const_cast is necessary for ancient openmpi version used on Travis
421  MPI_Send(const_cast<T*>(sbuf.data()), sbuf.size(), mpi_type<T>(), dest, tag, comm_);
422  }
423 
436  template<typename T> std::vector<T> recv(int src, int tag) const {
437  MPI_Status stat;
438  MPI_Probe(src, tag, comm_, &stat);
439  int msgsize;
440  MPI_Get_count(&stat, mpi_type<T>(), &msgsize);
441  //std::vector<T,NoInit<T>> rbuf(msgsize);
442  std::vector<T> rbuf(msgsize);
443  MPI_Recv(rbuf.data(), msgsize, mpi_type<T>(), src, tag,
444  comm_, MPI_STATUS_IGNORE);
445  return rbuf;
446  }
447 
448  template<typename T>
449  std::pair<int,std::vector<T>> recv_any_src(int tag) const {
450  MPI_Status stat;
451  MPI_Probe(MPI_ANY_SOURCE, tag, comm_, &stat);
452  int msgsize;
453  MPI_Get_count(&stat, mpi_type<T>(), &msgsize);
454  std::vector<T> rbuf(msgsize);
455  MPI_Recv(rbuf.data(), msgsize, mpi_type<T>(), stat.MPI_SOURCE,
456  tag, comm_, MPI_STATUS_IGNORE);
457  return {stat.MPI_SOURCE, std::move(rbuf)};
458  }
459 
460  template<typename T> T recv_one(int src, int tag) const {
461  T t;
462  MPI_Recv(&t, 1, mpi_type<T>(), src, tag, comm_, MPI_STATUS_IGNORE);
463  return t;
464  }
465 
466  template<typename T>
467  void irecv(const T* rbuf, std::size_t rsize, int src,
468  int tag, MPI_Request* req) const {
469  // const_cast is necessary for ancient openmpi version used on Travis
470  MPI_Irecv(const_cast<T*>(rbuf), rsize, mpi_type<T>(),
471  src, tag, comm_, req);
472  }
473 
474  template<typename T>
475  void recv(const T* rbuf, std::size_t rsize, int src, int tag) const {
476  // const_cast is necessary for ancient openmpi version used on Travis
477  MPI_Status stat;
478  MPI_Recv(const_cast<T*>(rbuf), rsize, mpi_type<T>(),
479  src, tag, comm_, &stat);
480  }
481 
496  template<typename T> T all_reduce(T t, MPI_Op op) const {
497  MPI_Allreduce(MPI_IN_PLACE, &t, 1, mpi_type<T>(), op, comm_);
498  return t;
499  }
500 
515  template<typename T> T reduce(T t, MPI_Op op) const {
516  if (is_root())
517  MPI_Reduce(MPI_IN_PLACE, &t, 1, mpi_type<T>(), op, 0, comm_);
518  else MPI_Reduce(&t, &t, 1, mpi_type<T>(), op, 0, comm_);
519  return t;
520  }
521 
537  template<typename T> void all_reduce(T* t, int ssize, MPI_Op op) const {
538  MPI_Allreduce(MPI_IN_PLACE, t, ssize, mpi_type<T>(), op, comm_);
539  }
540 
541  template<typename T> void all_reduce(std::vector<T>& t, MPI_Op op) const {
542  all_reduce(t.data(), t.size(), op);
543  }
544 
561  template<typename T> void
562  reduce(T* t, int ssize, MPI_Op op, int dest=0) const {
563  if (rank() == dest)
564  MPI_Reduce(MPI_IN_PLACE, t, ssize, mpi_type<T>(), op, dest, comm_);
565  else MPI_Reduce(t, t, ssize, mpi_type<T>(), op, dest, comm_);
566  }
567 
568  template<typename T>
569  void all_to_all(const T* sbuf, int scnt, T* rbuf) const {
570  MPI_Alltoall
571  (sbuf, scnt, mpi_type<T>(), rbuf, scnt, mpi_type<T>(), comm_);
572  }
573 
574  template<typename T, typename A=std::allocator<T>> std::vector<T,A>
575  all_to_allv(const T* sbuf, int* scnts, int* sdispls,
576  int* rcnts, int* rdispls) const {
577  std::size_t rsize = 0;
578  for (int p=0; p<size(); p++)
579  rsize += rcnts[p];
580  std::vector<T,A> rbuf(rsize);
581  MPI_Alltoallv
582  (sbuf, scnts, sdispls, mpi_type<T>(),
583  rbuf.data(), rcnts, rdispls, mpi_type<T>(), comm_);
584  return rbuf;
585  }
586 
587  template<typename T> void
588  all_to_allv(const T* sbuf, int* scnts, int* sdispls,
589  T* rbuf, int* rcnts, int* rdispls) const {
590  MPI_Alltoallv
591  (sbuf, scnts, sdispls, mpi_type<T>(),
592  rbuf, rcnts, rdispls, mpi_type<T>(), comm_);
593  }
594 
612  template<typename T, typename A=std::allocator<T>> void
613  all_to_all_v(std::vector<std::vector<T>>& sbuf, std::vector<T,A>& rbuf,
614  std::vector<T*>& pbuf) const {
615  all_to_all_v(sbuf, rbuf, pbuf, mpi_type<T>());
616  }
617 
631  template<typename T, typename A=std::allocator<T>> std::vector<T,A>
632  all_to_all_v(std::vector<std::vector<T>>& sbuf) const {
633  std::vector<T,A> rbuf;
634  std::vector<T*> pbuf;
635  all_to_all_v(sbuf, rbuf, pbuf, mpi_type<T>());
636  return rbuf;
637  }
638 
656  template<typename T, typename A=std::allocator<T>> void
657  all_to_all_v(std::vector<std::vector<T>>& sbuf, std::vector<T,A>& rbuf,
658  std::vector<T*>& pbuf, const MPI_Datatype Ttype) const {
659  assert(sbuf.size() == std::size_t(size()));
660  auto P = size();
661  std::unique_ptr<int[]> iwork(new int[4*P]);
662  auto ssizes = iwork.get();
663  auto rsizes = ssizes + P;
664  auto sdispl = ssizes + 2*P;
665  auto rdispl = ssizes + 3*P;
666  for (int p=0; p<P; p++) {
667  if (sbuf[p].size() >
668  static_cast<std::size_t>(std::numeric_limits<int>::max())) {
669  std::cerr << "# ERROR: 32bit integer overflow in all_to_all_v!!"
670  << std::endl;
671  MPI_Abort(comm_, 1);
672  }
673  ssizes[p] = sbuf[p].size();
674  }
675  MPI_Alltoall
676  (ssizes, 1, mpi_type<int>(), rsizes, 1, mpi_type<int>(), comm_);
677  std::size_t totssize = std::accumulate(ssizes, ssizes+P, std::size_t(0)),
678  totrsize = std::accumulate(rsizes, rsizes+P, std::size_t(0));
679  if (totrsize >
680  static_cast<std::size_t>(std::numeric_limits<int>::max()) ||
681  totssize >
682  static_cast<std::size_t>(std::numeric_limits<int>::max())) {
683  // This case will probably cause an overflow in the
684  // rdispl/sdispl elements. Here we do the all_to_all_v
685  // manually by just using Isend/Irecv. This might be slower
686  // than splitting into multiple calls to MPI_Alltoallv
687  // (although it avoids a copy from the sbuf).
688  rbuf.resize(totrsize);
689  std::unique_ptr<MPI_Request[]> reqs(new MPI_Request[2*P]);
690  std::size_t displ = 0;
691  pbuf.resize(P);
692  for (int p=0; p<P; p++) {
693  pbuf[p] = rbuf.data() + displ;
694  MPI_Irecv(pbuf[p], rsizes[p], Ttype, p, 0, comm_, reqs.get()+p);
695  displ += rsizes[p];
696  }
697  for (int p=0; p<P; p++)
698  MPI_Isend
699  (sbuf[p].data(), ssizes[p], Ttype, p, 0, comm_, reqs.get()+P+p);
700  MPI_Waitall(2*P, reqs.get(), MPI_STATUSES_IGNORE);
701  std::vector<std::vector<T>>().swap(sbuf);
702  } else {
703  std::unique_ptr<T[]> sendbuf_(new T[totssize]);
704  auto sendbuf = sendbuf_.get();
705  sdispl[0] = rdispl[0] = 0;
706  for (int p=1; p<P; p++) {
707  sdispl[p] = sdispl[p-1] + ssizes[p-1];
708  rdispl[p] = rdispl[p-1] + rsizes[p-1];
709  }
710  for (int p=0; p<P; p++)
711  std::copy(sbuf[p].begin(), sbuf[p].end(), sendbuf+sdispl[p]);
712  std::vector<std::vector<T>>().swap(sbuf);
713  rbuf.resize(totrsize);
714  MPI_Alltoallv(sendbuf, ssizes, sdispl, Ttype,
715  rbuf.data(), rsizes, rdispl, Ttype, comm_);
716  pbuf.resize(P);
717  for (int p=0; p<P; p++)
718  pbuf[p] = rbuf.data() + rdispl[p];
719  }
720  }
721 
737  MPIComm sub(int P0, int P, int stride=1) const {
738  if (is_null()) return MPIComm(MPI_COMM_NULL);
739  assert(P0 + P <= size());
740  MPIComm sub_comm;
741  std::vector<int> sub_ranks(P);
742  for (int i=0; i<P; i++)
743  sub_ranks[i] = P0 + i*stride;
744  MPI_Group group, sub_group;
745  MPI_Comm_group(comm_, &group); // get group from comm
746  MPI_Group_incl(group, P, sub_ranks.data(), &sub_group); // group ranks [P0,P0+P) into sub_group
747  MPI_Comm_create(comm_, sub_group, &sub_comm.comm_); // create new sub_comm
748  MPI_Group_free(&group);
749  MPI_Group_free(&sub_group);
750  return sub_comm;
751  }
752 
762  // return MPI_COMM_SELF??? or MPI_COMM_NULL if not rank??
763  MPIComm sub_self(int p) const {
764  if (is_null()) return MPIComm(MPI_COMM_NULL);
765  MPIComm c0;
766  MPI_Group group, sub_group;
767  MPI_Comm_group(comm_, &group);
768  MPI_Group_incl(group, 1, &p, &sub_group);
769  MPI_Comm_create(comm_, sub_group, &c0.comm_);
770  MPI_Group_free(&group);
771  MPI_Group_free(&sub_group);
772  return c0;
773  }
774 
778  static void control_start(const std::string& name) {
779  MPI_Pcontrol(1, name.c_str());
780  }
784  static void control_stop(const std::string& name) {
785  MPI_Pcontrol(-1, name.c_str());
786  }
787 
788  static bool initialized() {
789  int flag;
790  MPI_Initialized(&flag);
791  return static_cast<bool>(flag);
792  }
793 
794  private:
795  MPI_Comm comm_ = MPI_COMM_WORLD;
796 
797  void duplicate(MPI_Comm c) {
798  if (c == MPI_COMM_NULL) comm_ = c;
799  else MPI_Comm_dup(c, &comm_);
800  }
801  };
802 
803 
811  inline int mpi_rank(MPI_Comm c=MPI_COMM_WORLD) {
812  assert(c != MPI_COMM_NULL);
813  int rank;
814  MPI_Comm_rank(c, &rank);
815  return rank;
816  }
817 
825  inline int mpi_nprocs(MPI_Comm c=MPI_COMM_WORLD) {
826  assert(c != MPI_COMM_NULL);
827  int nprocs;
828  MPI_Comm_size(c, &nprocs);
829  return nprocs;
830  }
831 
832 } // end namespace strumpack
833 
834 #endif // STRUMPACK_MPI_WRAPPER_HPP
strumpack::MPIComm::isend
void isend(const std::vector< T > &sbuf, int dest, int tag, MPI_Request *req) const
Definition: MPIWrapper.hpp:378
strumpack::MPIComm::operator=
MPIComm & operator=(const MPIComm &c)
Definition: MPIWrapper.hpp:237
strumpack::mpi_type< float >
MPI_Datatype mpi_type< float >()
Definition: MPIWrapper.hpp:72
strumpack::mpi_type< char >
MPI_Datatype mpi_type< char >()
Definition: MPIWrapper.hpp:60
strumpack::MPIComm
Wrapper class around an MPI_Comm object.
Definition: MPIWrapper.hpp:190
strumpack::MPIRequest::wait
void wait()
Definition: MPIWrapper.hpp:152
strumpack::mpi_type< double >
MPI_Datatype mpi_type< double >()
Definition: MPIWrapper.hpp:74
strumpack::MPIComm::reduce
void reduce(T *t, int ssize, MPI_Op op, int dest=0) const
Definition: MPIWrapper.hpp:562
strumpack::MPIComm::is_null
bool is_null() const
Definition: MPIWrapper.hpp:262
strumpack::copy
void copy(std::size_t m, std::size_t n, const DenseMatrix< scalar_from_t > &a, std::size_t ia, std::size_t ja, DenseMatrix< scalar_to_t > &b, std::size_t ib, std::size_t jb)
Definition: DenseMatrix.hpp:1207
strumpack::MPIComm::is_root
bool is_root() const
Definition: MPIWrapper.hpp:289
strumpack::mpi_type< int >
MPI_Datatype mpi_type< int >()
Definition: MPIWrapper.hpp:64
strumpack
Definition: StrumpackOptions.hpp:42
strumpack::MPIComm::isend
MPIRequest isend(const std::vector< T > &sbuf, int dest, int tag) const
Definition: MPIWrapper.hpp:357
strumpack::MPIRequest
Wrapper around an MPI_Request object.
Definition: MPIWrapper.hpp:119
strumpack::MPIComm::MPIComm
MPIComm()
Definition: MPIWrapper.hpp:196
strumpack::MPIComm::comm
MPI_Comm comm() const
Definition: MPIWrapper.hpp:257
strumpack::mpi_nprocs
int mpi_nprocs(MPI_Comm c=MPI_COMM_WORLD)
Definition: MPIWrapper.hpp:825
StrumpackParameters.hpp
Contains the definition of some useful (global) variables.
strumpack::MPIComm::all_reduce
T all_reduce(T t, MPI_Op op) const
Definition: MPIWrapper.hpp:496
strumpack::mpi_type
MPI_Datatype mpi_type()
Definition: MPIWrapper.hpp:58
strumpack::wait_all
void wait_all(std::vector< MPIRequest > &reqs)
Definition: MPIWrapper.hpp:168
strumpack::MPIComm::all_to_all_v
std::vector< T, A > all_to_all_v(std::vector< std::vector< T >> &sbuf) const
Definition: MPIWrapper.hpp:632
strumpack::MPIComm::reduce
T reduce(T t, MPI_Op op) const
Definition: MPIWrapper.hpp:515
strumpack::mpi_type< long long int >
MPI_Datatype mpi_type< long long int >()
Definition: MPIWrapper.hpp:70
strumpack::MPIComm::all_reduce
void all_reduce(T *t, int ssize, MPI_Op op) const
Definition: MPIWrapper.hpp:537
strumpack::MPIComm::sub
MPIComm sub(int P0, int P, int stride=1) const
Definition: MPIWrapper.hpp:737
strumpack::MPIComm::barrier
void barrier() const
Definition: MPIWrapper.hpp:295
strumpack::MPIComm::control_start
static void control_start(const std::string &name)
Definition: MPIWrapper.hpp:778
strumpack::mpi_type< bool >
MPI_Datatype mpi_type< bool >()
Definition: MPIWrapper.hpp:62
strumpack::MPIComm::sub_self
MPIComm sub_self(int p) const
Definition: MPIWrapper.hpp:763
strumpack::MPIComm::rank
int rank() const
Definition: MPIWrapper.hpp:267
strumpack::mpi_type< long >
MPI_Datatype mpi_type< long >()
Definition: MPIWrapper.hpp:66
strumpack::MPIComm::~MPIComm
virtual ~MPIComm()
Definition: MPIWrapper.hpp:227
strumpack::MPIComm::size
int size() const
Definition: MPIWrapper.hpp:278
strumpack::MPIComm::MPIComm
MPIComm(MPI_Comm c)
Definition: MPIWrapper.hpp:205
strumpack::MPIComm::MPIComm
MPIComm(MPIComm &&c) noexcept
Definition: MPIWrapper.hpp:221
strumpack::MPIComm::control_stop
static void control_stop(const std::string &name)
Definition: MPIWrapper.hpp:784
strumpack::MPIComm::send
void send(const std::vector< T > &sbuf, int dest, int tag) const
Definition: MPIWrapper.hpp:419
strumpack::MPIComm::MPIComm
MPIComm(const MPIComm &c)
Definition: MPIWrapper.hpp:213
strumpack::MPIComm::recv
std::vector< T > recv(int src, int tag) const
Definition: MPIWrapper.hpp:436
strumpack::MPIComm::all_to_all_v
void all_to_all_v(std::vector< std::vector< T >> &sbuf, std::vector< T, A > &rbuf, std::vector< T * > &pbuf, const MPI_Datatype Ttype) const
Definition: MPIWrapper.hpp:657
strumpack::MPIComm::operator=
MPIComm & operator=(MPIComm &&c) noexcept
Definition: MPIWrapper.hpp:248
strumpack::Trans::T
@ T
strumpack::mpi_type< unsigned long >
MPI_Datatype mpi_type< unsigned long >()
Definition: MPIWrapper.hpp:68
strumpack::MPIComm::all_to_all_v
void all_to_all_v(std::vector< std::vector< T >> &sbuf, std::vector< T, A > &rbuf, std::vector< T * > &pbuf) const
Definition: MPIWrapper.hpp:613
strumpack::mpi_rank
int mpi_rank(MPI_Comm c=MPI_COMM_WORLD)
Definition: MPIWrapper.hpp:811
strumpack::MPIRequest::MPIRequest
MPIRequest()
Definition: MPIWrapper.hpp:124
strumpack::MPIRequest::operator=
MPIRequest & operator=(const MPIRequest &)=delete