Rheolef  7.1
an efficient C++ finite element environment
distributor.cc
Go to the documentation of this file.
1 
22 # include "rheolef/distributor.h"
23 # include <algorithm> // std::lower_bound()
24 namespace rheolef {
25 using namespace std;
26 // ----------------------------------------------------------------------------
27 // class member functions
28 // ----------------------------------------------------------------------------
29 void
31  size_type dis_size1,
32  const communicator_type& comm1,
33  size_type loc_size1)
34 {
35  _comm = comm1;
36  size_type nproc = comm1.size();
37  size_type my_proc = comm1.rank();
38  Vector<size_type>::resize (nproc+1);
39  if (dis_size1 == decide) {
40  // example:
41  // disarray<T,sequential> x(n); => local size is n and dis_size is indefined
42  check_macro (loc_size1 != decide, "both dis_size and local size are indetermined");
43 #ifndef _RHEOLEF_HAVE_MPI
44  dis_size1 = loc_size1;
45 #else // _RHEOLEF_HAVE_MPI
46  dis_size1 = mpi::all_reduce (_comm, loc_size1, std::plus<size_type>());
47 #endif // _RHEOLEF_HAVE_MPI
48  }
49  // compute ownership:
50  at(0) = 0;
51 #ifndef _RHEOLEF_HAVE_MPI
52  at(1) = dis_size1;
53 #else // _RHEOLEF_HAVE_MPI
54 
55  if (dis_size1 == 0) {
56  // zero dis_size, which is very frequent in iterative linear solvers, for tmp vectors
57  // => avoid all_gather(blocking communication): set all local sizes to zero
58  // BUG: when doing this, some tests blocks:
59  // mpirun -np 4 neumann line-dom-v2.geo
60  // mpirun -np 6 neumann line-dom-v2.geo
61  // HYP: the following mpi::all_gather force resynchronization before form c=a+m addition ?
63  return;
64  }
65 #ifdef TODO
66 #endif // TODO
67  // compute local size if not furnished by user:
68  if (loc_size1 == decide) {
69  // example:
70  // disarray<T,distributed> x(n); => dis_size is n and local size is indefined
71  check_macro (dis_size1 != decide, "both dis_size and local size are indetermined");
72  size_type N = dis_size1;
73  size_type n = nproc;
74  size_type i = my_proc;
75  loc_size1 = size_type(N/n + ((N % n) > i));
76  }
77  // ownership[j] := loc_size_ in the context of the j-th process
78  // mpi::all_gather: The block of data sent from the jth process is
79  // received by every process and placed in the jth block of the
80  // buffer.
81  mpi::all_gather (comm1, loc_size1, begin().operator->()+1);
82  // compute global last index from local sizes
83  for (size_type i = 2; i <= nproc; i++ ) {
84  at(i) += at(i-1);
85  }
86 #endif // _RHEOLEF_HAVE_MPI
87 }
89  size_type dis_size1,
90  const communicator_type& comm1,
91  size_type loc_size1)
92  : Vector<size_type>(),
93  _comm(comm1)
94 {
95  resize(dis_size1, comm1, loc_size1);
96 }
98  : Vector<size_type>(ownership),
99  _comm(ownership.comm())
100 {
101 }
103 {
104 }
107 {
108  // check first on current iproc:
109  size_type iproc = comm().rank();
110  if (is_owned (dis_i, iproc)) return iproc;
111 
112  // then lookup in sorted intervals table:
113  const_iterator iter = std::lower_bound (begin(), end(), dis_i);
114  check_macro (iter != end(), "index = " << dis_i <<" not found in index range[0:" << dis_size() << "[");
115  size_type iproc1 = distance (begin(), iter);
116  iproc = (operator[] (iproc1) == dis_i) ? iproc1 : iproc1 - 1;
117  if (dis_i >= first_index(iproc) && dis_i < last_index(iproc)) {
118  return iproc;
119  }
120  if (dis_i < first_index(iproc) || dis_i >= last_index(iproc)) {
121  // more complex distribution: some partitions are empty, e.g. [0:0[
122  for (size_type jproc = iproc+1, nproc = n_process(); jproc < nproc; jproc++) {
123  if (dis_i >= first_index(jproc) && dis_i < last_index(jproc)) {
124  return jproc;
125  }
126  }
127  }
128  error_macro ("owner not found for index="<<dis_i<<" in [0:"<<dis_size() << "[");
129  return 0;
130 }
131 #ifdef _RHEOLEF_HAVE_MPI
132 int
134  static const int min_tag = 0;
135  static const int max_tag = mpi::environment::max_tag();
136  static int cur_tag = min_tag;
137  cur_tag;
138  if (cur_tag > max_tag) cur_tag = min_tag;
139  return cur_tag++;
140 }
141 #else // _RHEOLEF_HAVE_MPI
142 int
144  return 0;
145 }
146 #endif // _RHEOLEF_HAVE_MPI
147 
148 } // namespace rheolef
see the distributor page for the full documentation
Definition: distributor.h:62
size_type last_index() const
Definition: distributor.h:195
size_type n_process() const
number of processes
Definition: distributor.h:169
size_type find_owner(size_type dis_i) const
find iproc associated to a global index dis_i: CPU=log(nproc)
Definition: distributor.cc:106
void resize(size_type dis_size=0, const communicator_type &c=communicator_type(), size_type loc_size=decide)
Definition: distributor.cc:30
size_type dis_size() const
global and local sizes
Definition: distributor.h:207
communicator communicator_type
Definition: distributor.h:72
static tag_type get_new_tag()
returns a new tag
Definition: distributor.cc:133
size_type first_index() const
global index range and local size owned by current process
Definition: distributor.h:189
_base::const_iterator const_iterator
Definition: distributor.h:70
bool is_owned(size_type dis_i, size_type iproc) const
true when dis_i in [first_index(iproc):last_index(iproc)[
Definition: distributor.h:213
distributor(size_type dis_size=0, const communicator_type &c=communicator_type(), size_type loc_size=decide)
Definition: distributor.cc:88
std::allocator< int >::size_type size_type
Definition: distributor.h:67
const communicator_type & comm() const
Definition: distributor.h:145
size_t size_type
Definition: basis_get.cc:76
#define error_macro(message)
Definition: dis_macros.h:49
check_macro(expr1.have_homogeneous_space(Xh1), "dual(expr1,expr2); expr1 should have homogeneous space. HINT: use dual(interpolate(Xh, expr1),expr2)")
This file is part of Rheolef.
size_t N
const_reference operator[](size_type n) const
Definition: Vector.h:274
void resize(size_type sz, T v=T())
Definition: Vector.h:266