Rheolef  7.2
an efficient C++ finite element environment
 
Loading...
Searching...
No Matches
distributor.cc
Go to the documentation of this file.
1
21
22# include "rheolef/distributor.h"
23# include <algorithm> // std::lower_bound()
24namespace rheolef {
25using namespace std;
26// ----------------------------------------------------------------------------
27// class member functions
28// ----------------------------------------------------------------------------
29void
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();
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}
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
132int
134 // see petsc/src/sys/objects/tagm.c for a more elaborate implementation
135 static const int min_tag = 0;
136 static const int max_tag = mpi::environment::max_tag();
137 static int cur_tag = min_tag;
138 cur_tag;
139 if (cur_tag > max_tag) cur_tag = min_tag;
140 return cur_tag++;
141}
142#else // _RHEOLEF_HAVE_MPI
143int
145 return 0;
146}
147#endif // _RHEOLEF_HAVE_MPI
148
149} // namespace rheolef
see the distributor page for the full documentation
Definition distributor.h:69
size_type last_index() const
size_type n_process() const
number of processes
size_type find_owner(size_type dis_i) const
find iproc associated to a global index dis_i: CPU=log(nproc)
void resize(size_type dis_size=0, const communicator_type &c=communicator_type(), size_type loc_size=decide)
size_type dis_size() const
global and local sizes
communicator communicator_type
Definition distributor.h:79
static tag_type get_new_tag()
returns a new tag
size_type first_index() const
global index range and local size owned by current process
_base::const_iterator const_iterator
Definition distributor.h:77
communicator_type _comm
bool is_owned(size_type dis_i, size_type iproc) const
true when dis_i in [first_index(iproc):last_index(iproc)[
static const size_type decide
Definition distributor.h:83
distributor(size_type dis_size=0, const communicator_type &c=communicator_type(), size_type loc_size=decide)
std::allocator< int >::size_type size_type
Definition distributor.h:74
const communicator_type & comm() const
#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.
STL namespace.
size_t N
const_reference at(size_type n) const
Definition Vector.h:283
const_reference operator[](size_type n) const
Definition Vector.h:274
void resize(size_type sz, T v=T())
Definition Vector.h:266