Rheolef  7.2
an efficient C++ finite element environment
 
Loading...
Searching...
No Matches
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
34namespace 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
42template<class Container>
43void
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[
124template<class Container>
125template<class InputIterator>
126void
128{
130 _indices.begin(),
131 _indices.end(),
132 x,
133 _values.begin());
134}
135// the same with multi-valued data:
136template<class Container>
137template<class InputIterator>
138void
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)[
149template<class Container>
150template<class OutputIterator, class SetOp>
151void
152scatter_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:
162template<class Container>
163template<class OutputIterator, class SetOp>
164void
165scatter_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.
void msg_left_permutation_apply(InputIterator1 x, SetOp op, InputIterator2 py, InputIterator2 last_py, OutputRandomIterator y)
OutputIterator msg_right_permutation_apply(InputIterator perm, InputIterator last_perm, const InputRandomIterator &x, OutputIterator y, SetOp set_op)
Definition sphere.icc:25