Rheolef  7.1
an efficient C++ finite element environment
scatter_message.icc
Go to the documentation of this file.
1 #ifndef _RHEOLEF_SCATTER_MESSAGE_ICC
2 #define _RHEOLEF_SCATTER_MESSAGE_ICC
23 //
24 // create distributed to sequential scatter context
25 // inspirated from petsc-2.0/vpscat.c: VecScatterCreate_PtoS(...)
26 //
27 #include "rheolef/compiler.h"
28 
29 #ifdef _RHEOLEF_HAVE_MPI
30 #include "rheolef/scatter_message.h"
31 #include "rheolef/msg_left_permutation_apply.h"
32 #include "rheolef/msg_right_permutation_apply.h"
33 
34 namespace rheolef {
35 
36 // =================================================================================
37 // part 1: init
38 // =================================================================================
39 // case of multi-valued data:
40 // called after the scatter_message<Container,false> scatter is finished:
41 // => the size of each object to transmit is known
42 template<class Container>
43 void
45 {
46  // ----------------------------------------------
47  // 1) count the total message size
48  // ----------------------------------------------
49  size_type n_data = base::n_data();
50  _ptr.resize (n_data+1);
51  _ptr [0] = 0;
52  for (size_type i = 0; i < n_data; i++) {
53  size_type size_i = base::_values [i];
54  _ptr [i+1] = _ptr[i] + size_i;
55  }
56  size_type n_multi_data = _ptr[n_data];
57 
58  // ----------------------------------------------
59  // 2) resize & fill multi_{values,indices} arrays
60  // ----------------------------------------------
61  _multi_values.resize (n_multi_data);
62 #ifdef TO_CLEAN
63  _multi_indices.resize (n_multi_data);
64  typename std::vector<size_type>::const_iterator p = base::_indices.begin();
65  std::vector<size_type> ip (n_data);
66  for (size_type i = 0; i < n_data; i++) {
67  ip[p[i]] = i;
68  }
69  // y[p[i]] == x[i] <==> x[ip[j]] == y[j]
70  // yptr[j]... yptr[j+1]-1 = range of multi-valued y[j]==x[i], j=p[i]
71  std::vector<size_type> yptr (n_data+1);
72  yptr [0] = 0;
73  for (size_type j = 0; j < n_data; j++) {
74  size_type size_j = base::_values [ip[j]];
75  yptr[j+1] = yptr[j] + size_j;
76  }
77  for (size_type i = 0; i < n_data; i++) {
78  size_type size_i = base::_values [i];
79  size_type j = _ptr[i];
80  for (size_type k = 0; k < size_i; j++) {
81  _multi_indices [yptr[j]+k] = _ptr[i] + k;
82  }
83  }
84 #endif // TO_CLEAN
85  // --------------------------------------------
86  // 3) eliminate zero-sized multi-messages
87  // --------------------------------------------
88  // some values could asked for send/receive could be empty set, so
89  // the multi_nproc of send/receive could be < nproc for sizes
90  // => check for empty messages, i.e. with zero-sized multi-valued containers(set,list,..)
91  // and MPI waits infinitely for empty messages to arrive...
92  size_type nproc = base::_procs.size();
93  std::vector<size_type> msg_size (nproc, 0);
94  size_type multi_nproc = 0;
95  for (size_type iproc = 0; iproc < nproc; iproc++) {
96  for (size_type i = base::_starts[iproc],
97  last_i = base::_starts[iproc+1]; i < last_i; i++) {
98  size_type size_i = base::_values [i];
99  msg_size[iproc] += size_i;
100  }
101  if (msg_size[iproc] != 0) {
102  multi_nproc++;
103  }
104  }
105  // --------------------------------------------
106  // 4) resize & fill multi_{procs,starts} arrays
107  // --------------------------------------------
108  _multi_procs.resize (multi_nproc);
109  _multi_starts.resize (multi_nproc+1);
110  _multi_irecv2base_irecv.resize (multi_nproc);
111  _multi_starts [0] = 0;
112  for (size_type iproc = 0, multi_iproc = 0; iproc < nproc; iproc++) {
113  if (msg_size[iproc] == 0) continue;
114  _multi_procs [multi_iproc] = base::_procs [iproc];
115  _multi_starts [multi_iproc+1] = _multi_starts [multi_iproc] + msg_size[iproc];
116  _multi_irecv2base_irecv [multi_iproc] = iproc;
117  multi_iproc++;
118  }
119 }
120 // =================================================================================
121 // part 2: load and store
122 // =================================================================================
123 // values[i] = x[indices[i]], i=[0..n_data[
124 template<class Container>
125 template<class InputIterator>
126 void
128 {
130  _indices.begin(),
131  _indices.end(),
132  x,
133  _values.begin());
134 }
135 // the same with multi-valued data:
136 template<class Container>
137 template<class InputIterator>
138 void
140 {
141  for (size_type i = 0, n_data = base::_indices.size(), z = 0; i < n_data; i++) {
142  size_type pi = base::_indices[i];
143  for (typename value_type::const_iterator first = x[pi].begin(), last = x[pi].end(); first != last; first++, z++) {
144  _multi_values [z] = *first;
145  }
146  }
147 }
148 // y[indices[i]] = value[i], i=[start(i_recv)..starts(i_recv+1)[
149 template<class Container>
150 template<class OutputIterator, class SetOp>
151 void
152 scatter_message<Container,false>::store_values (OutputIterator y, size_type i_recv, SetOp op) const
153 {
155  _values.begin() + _starts[i_recv],
156  op,
157  _indices.begin() + _starts[i_recv],
158  _indices.begin() + _starts[i_recv+1],
159  y);
160 }
161 // the same with multi-valued data:
162 template<class Container>
163 template<class OutputIterator, class SetOp>
164 void
165 scatter_message<Container,true>::store_values (OutputIterator y, size_type i_multi_recv, SetOp op) const
166 {
167  size_type i_recv = _multi_irecv2base_irecv [i_multi_recv];
168  for (size_type i = base::_starts[i_recv], n_data = base::_starts[i_recv+1]; i < n_data; i++) {
169  size_type pi = base::_indices[i];
170  for (size_type z = _ptr[i], last_z = _ptr[i+1]; z < last_z; z++) {
171  y[pi] += _multi_values [z];
172  }
173  }
174 }
175 
176 } // namespace rheolef
177 #endif // _RHEOLEF_HAVE_MPI
178 #endif // _RHEOLEF_SCATTER_MESSAGE_ICC
This file is part of Rheolef.
OutputIterator msg_right_permutation_apply(InputIterator perm, InputIterator last_perm, const InputRandomIterator &x, OutputIterator y, SetOp set_op)
void msg_left_permutation_apply(InputIterator1 x, SetOp op, InputIterator2 py, InputIterator2 last_py, OutputRandomIterator y)
Definition: sphere.icc:25