distributor.cc
Go to the documentation of this file.
# include "rheolef/distributor.h"
# include <algorithm> // std::lower_bound()
namespace rheolef {
using namespace std;
// ----------------------------------------------------------------------------
// class member functions
// ----------------------------------------------------------------------------
void
distributor::resize (
size_type dis_size1,
const communicator_type& comm1,
size_type loc_size1)
{
_comm = comm1;
size_type nproc = comm1.size();
size_type my_proc = comm1.rank();
Vector<size_type>::resize (nproc+1);
if (dis_size1 == decide) {
// example:
// disarray<T,sequential> x(n); => local size is n and dis_size is indefined
check_macro (loc_size1 != decide, "both dis_size and local size are indetermined");
#ifndef _RHEOLEF_HAVE_MPI
dis_size1 = loc_size1;
#else // _RHEOLEF_HAVE_MPI
dis_size1 = mpi::all_reduce (_comm, loc_size1, std::plus<size_type>());
#endif // _RHEOLEF_HAVE_MPI
}
// compute ownership:
at(0) = 0;
#ifndef _RHEOLEF_HAVE_MPI
at(1) = dis_size1;
#else // _RHEOLEF_HAVE_MPI
if (dis_size1 == 0) {
// zero dis_size, which is very frequent in iterative linear solvers, for tmp vectors
// => avoid all_gather(blocking communication): set all local sizes to zero
// BUG: when doing this, some tests blocks:
// mpirun -np 4 neumann line-dom-v2.geo
// mpirun -np 6 neumann line-dom-v2.geo
// HYP: the following mpi::all_gather force resynchronization before form c=a+m addition ?
std::fill(Vector<size_type>::begin(), Vector<size_type>::end(), 0);
return;
}
#ifdef TODO
#endif // TODO
// compute local size if not furnished by user:
if (loc_size1 == decide) {
// example:
// disarray<T,distributed> x(n); => dis_size is n and local size is indefined
check_macro (dis_size1 != decide, "both dis_size and local size are indetermined");
size_type N = dis_size1;
size_type n = nproc;
size_type i = my_proc;
loc_size1 = size_type(N/n + ((N % n) > i));
}
// ownership[j] := loc_size_ in the context of the j-th process
// mpi::all_gather: The block of data sent from the jth process is
// received by every process and placed in the jth block of the
// buffer.
mpi::all_gather (comm1, loc_size1, begin().operator->()+1);
// compute global last index from local sizes
for (size_type i = 2; i <= nproc; i++ ) {
at(i) += at(i-1);
}
#endif // _RHEOLEF_HAVE_MPI
}
distributor::distributor (
size_type dis_size1,
const communicator_type& comm1,
size_type loc_size1)
: Vector<size_type>(),
_comm(comm1)
{
resize(dis_size1, comm1, loc_size1);
}
distributor::distributor (const distributor& ownership)
: Vector<size_type>(ownership),
_comm(ownership.comm())
{
}
distributor::~distributor ()
{
}
distributor::size_type
distributor::find_owner (size_type dis_i) const
{
// check first on current iproc:
size_type iproc = comm().rank();
if (is_owned (dis_i, iproc)) return iproc;
// then lookup in sorted intervals table:
const_iterator iter = std::lower_bound (begin(), end(), dis_i);
check_macro (iter != end(), "index = " << dis_i <<" not found in index range[0:" << dis_size() << "[");
size_type iproc1 = distance (begin(), iter);
iproc = (operator[] (iproc1) == dis_i) ? iproc1 : iproc1 - 1;
if (dis_i >= first_index(iproc) && dis_i < last_index(iproc)) {
return iproc;
}
if (dis_i < first_index(iproc) || dis_i >= last_index(iproc)) {
// more complex distribution: some partitions are empty, e.g. [0:0[
for (size_type jproc = iproc+1, nproc = n_process(); jproc < nproc; jproc++) {
if (dis_i >= first_index(jproc) && dis_i < last_index(jproc)) {
return jproc;
}
}
}
error_macro ("owner not found for index="<<dis_i<<" in [0:"<<dis_size() << "[");
return 0;
}
#ifdef _RHEOLEF_HAVE_MPI
int
distributor::get_new_tag () {
static const int min_tag = 0;
static const int max_tag = mpi::environment::max_tag();
static int cur_tag = min_tag;
cur_tag;
if (cur_tag > max_tag) cur_tag = min_tag;
return cur_tag++;
}
#else // _RHEOLEF_HAVE_MPI
int
distributor::get_new_tag () {
return 0;
}
#endif // _RHEOLEF_HAVE_MPI
} // namespace rheolef
rheolef::distributor
see the distributor page for the full documentation
Definition: distributor.h:62
rheolef::distributor::last_index
size_type last_index() const
Definition: distributor.h:195
rheolef::distributor::n_process
size_type n_process() const
number of processes
Definition: distributor.h:169
rheolef::distributor::find_owner
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
rheolef::distributor::resize
void resize(size_type dis_size=0, const communicator_type &c=communicator_type(), size_type loc_size=decide)
Definition: distributor.cc:30
rheolef::distributor::~distributor
~distributor()
Definition: distributor.cc:102
rheolef::distributor::dis_size
size_type dis_size() const
global and local sizes
Definition: distributor.h:207
rheolef::distributor::communicator_type
communicator communicator_type
Definition: distributor.h:72
rheolef::distributor::get_new_tag
static tag_type get_new_tag()
returns a new tag
Definition: distributor.cc:133
rheolef::distributor::first_index
size_type first_index() const
global index range and local size owned by current process
Definition: distributor.h:189
rheolef::distributor::const_iterator
_base::const_iterator const_iterator
Definition: distributor.h:70
rheolef::distributor::is_owned
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
rheolef::distributor::distributor
distributor(size_type dis_size=0, const communicator_type &c=communicator_type(), size_type loc_size=decide)
Definition: distributor.cc:88
rheolef::distributor::size_type
std::allocator< int >::size_type size_type
Definition: distributor.h:67
rheolef::distributor::comm
const communicator_type & comm() const
Definition: distributor.h:145
rheolef::size_type
size_t size_type
Definition: basis_get.cc:76
error_macro
#define error_macro(message)
Definition: dis_macros.h:49
check_macro
check_macro(expr1.have_homogeneous_space(Xh1), "dual(expr1,expr2); expr1 should have homogeneous space. HINT: use dual(interpolate(Xh, expr1),expr2)")
mkgeo_ball.n
int n
Definition: mkgeo_ball.sh:150
rheolef
This file is part of Rheolef.
Definition: compiler_eigen.h:37
N
size_t N
Definition: neumann-laplace-check.cc:24
rheolef::Vector
Definition: Vector.h:176
rheolef::Vector< std::allocator< int >::size_type >::operator[]
const_reference operator[](size_type n) const
Definition: Vector.h:274
rheolef::Vector::resize
void resize(size_type sz, T v=T())
Definition: Vector.h:266
rheolef::Vector< std::allocator< int >::size_type >::end
iterator end()
Definition: Vector.h:225
rheolef::Vector< std::allocator< int >::size_type >::begin
iterator begin()
Definition: Vector.h:217