scatter_message.icc
Go to the documentation of this file.
#ifndef _RHEOLEF_SCATTER_MESSAGE_ICC
#define _RHEOLEF_SCATTER_MESSAGE_ICC
//
// create distributed to sequential scatter context
// inspirated from petsc-2.0/vpscat.c: VecScatterCreate_PtoS(...)
//
#include "rheolef/compiler.h"
#ifdef _RHEOLEF_HAVE_MPI
#include "rheolef/scatter_message.h"
#include "rheolef/msg_left_permutation_apply.h"
#include "rheolef/msg_right_permutation_apply.h"
namespace rheolef {
// =================================================================================
// part 1: init
// =================================================================================
// case of multi-valued data:
// called after the scatter_message<Container,false> scatter is finished:
// => the size of each object to transmit is known
template<class Container>
void
scatter_message<Container,true>::multi_init ()
{
// ----------------------------------------------
// 1) count the total message size
// ----------------------------------------------
size_type n_data = base::n_data();
_ptr.resize (n_data+1);
_ptr [0] = 0;
for (size_type i = 0; i < n_data; i++) {
size_type size_i = base::_values [i];
_ptr [i+1] = _ptr[i] + size_i;
}
size_type n_multi_data = _ptr[n_data];
// ----------------------------------------------
// 2) resize & fill multi_{values,indices} arrays
// ----------------------------------------------
_multi_values.resize (n_multi_data);
#ifdef TO_CLEAN
_multi_indices.resize (n_multi_data);
typename std::vector<size_type>::const_iterator p = base::_indices.begin();
std::vector<size_type> ip (n_data);
for (size_type i = 0; i < n_data; i++) {
ip[p[i]] = i;
}
// y[p[i]] == x[i] <==> x[ip[j]] == y[j]
// yptr[j]... yptr[j+1]-1 = range of multi-valued y[j]==x[i], j=p[i]
std::vector<size_type> yptr (n_data+1);
yptr [0] = 0;
for (size_type j = 0; j < n_data; j++) {
size_type size_j = base::_values [ip[j]];
yptr[j+1] = yptr[j] + size_j;
}
for (size_type i = 0; i < n_data; i++) {
size_type size_i = base::_values [i];
size_type j = _ptr[i];
for (size_type k = 0; k < size_i; j++) {
_multi_indices [yptr[j]+k] = _ptr[i] + k;
}
}
#endif // TO_CLEAN
// --------------------------------------------
// 3) eliminate zero-sized multi-messages
// --------------------------------------------
// some values could asked for send/receive could be empty set, so
// the multi_nproc of send/receive could be < nproc for sizes
// => check for empty messages, i.e. with zero-sized multi-valued containers(set,list,..)
// and MPI waits infinitely for empty messages to arrive...
size_type nproc = base::_procs.size();
std::vector<size_type> msg_size (nproc, 0);
size_type multi_nproc = 0;
for (size_type iproc = 0; iproc < nproc; iproc++) {
for (size_type i = base::_starts[iproc],
last_i = base::_starts[iproc+1]; i < last_i; i++) {
size_type size_i = base::_values [i];
msg_size[iproc] += size_i;
}
if (msg_size[iproc] != 0) {
multi_nproc++;
}
}
// --------------------------------------------
// 4) resize & fill multi_{procs,starts} arrays
// --------------------------------------------
_multi_procs.resize (multi_nproc);
_multi_starts.resize (multi_nproc+1);
_multi_irecv2base_irecv.resize (multi_nproc);
_multi_starts [0] = 0;
for (size_type iproc = 0, multi_iproc = 0; iproc < nproc; iproc++) {
if (msg_size[iproc] == 0) continue;
_multi_procs [multi_iproc] = base::_procs [iproc];
_multi_starts [multi_iproc+1] = _multi_starts [multi_iproc] + msg_size[iproc];
_multi_irecv2base_irecv [multi_iproc] = iproc;
multi_iproc++;
}
}
// =================================================================================
// part 2: load and store
// =================================================================================
// values[i] = x[indices[i]], i=[0..n_data[
template<class Container>
template<class InputIterator>
void
scatter_message<Container,false>::load_values (InputIterator x)
{
msg_right_permutation_apply (
_indices.begin(),
_indices.end(),
x,
_values.begin());
}
// the same with multi-valued data:
template<class Container>
template<class InputIterator>
void
scatter_message<Container,true>::load_values (InputIterator x)
{
for (size_type i = 0, n_data = base::_indices.size(), z = 0; i < n_data; i++) {
size_type pi = base::_indices[i];
for (typename value_type::const_iterator first = x[pi].begin(), last = x[pi].end(); first != last; first++, z++) {
_multi_values [z] = *first;
}
}
}
// y[indices[i]] = value[i], i=[start(i_recv)..starts(i_recv+1)[
template<class Container>
template<class OutputIterator, class SetOp>
void
scatter_message<Container,false>::store_values (OutputIterator y, size_type i_recv, SetOp op) const
{
msg_left_permutation_apply (
_values.begin() + _starts[i_recv],
op,
_indices.begin() + _starts[i_recv],
_indices.begin() + _starts[i_recv+1],
y);
}
// the same with multi-valued data:
template<class Container>
template<class OutputIterator, class SetOp>
void
scatter_message<Container,true>::store_values (OutputIterator y, size_type i_multi_recv, SetOp op) const
{
size_type i_recv = _multi_irecv2base_irecv [i_multi_recv];
for (size_type i = base::_starts[i_recv], n_data = base::_starts[i_recv+1]; i < n_data; i++) {
size_type pi = base::_indices[i];
for (size_type z = _ptr[i], last_z = _ptr[i+1]; z < last_z; z++) {
y[pi] += _multi_values [z];
}
}
}
} // namespace rheolef
#endif // _RHEOLEF_HAVE_MPI
#endif // _RHEOLEF_SCATTER_MESSAGE_ICC
rheolef::scatter_message< Container, false >::size_type
Container::size_type size_type
Definition: scatter_message.h:41
rheolef::scatter_message< Container, true >::size_type
base::size_type size_type
Definition: scatter_message.h:122
rheolef::scatter_message
Definition: scatter_message.h:33
rheolef
This file is part of Rheolef.
Definition: compiler_eigen.h:37
rheolef::msg_right_permutation_apply
OutputIterator msg_right_permutation_apply(InputIterator perm, InputIterator last_perm, const InputRandomIterator &x, OutputIterator y, SetOp set_op)
Definition: msg_right_permutation_apply.h:57
rheolef::msg_left_permutation_apply
void msg_left_permutation_apply(InputIterator1 x, SetOp op, InputIterator2 py, InputIterator2 last_py, OutputRandomIterator y)
Definition: msg_left_permutation_apply.h:57
p
Definition: sphere.icc:25