NAME
disarray - container in distributed environment (rheolef-7.0)
SYNOPSIS
STL-like vector container for a distributed memory machine model.
EXAMPLE
A sample usage of the class is:
int main(int
argc, char**argv) {
environment distributed(argc, argv);
disarray<double> x(distributor(100), 3.14);
dout << x << endl;
}
The disarray<T> interface is similar to those of the std::vector<T> with the addition of some communication features in the distributed case: write accesses with entry/assembly and read access with dis_at.
DISTRIBUTED WRITE ACCESS
Loop on any dis_i that is not managed by the current processor:
x.dis_entry (dis_i) = value;
and then, after loop, perform all communication:
x.dis_entry_assembly();
After this command, each value is stored in the disarray, available the processor associated to dis_i.
DISTRIBUTED READ ACCESS
First, define the set of indexes:
std::set<size_t> ext_idx_set;
Then, loop on dis_i indexes that are not managed by the current processor:
ext_idx_set.insert (dis_i);
After the loop, performs the communications:
x.set_dis_indexes (ext_idx_set);
After this command, each values associated to the dis_i index, and that belongs to the index set, is now available also on the current processor as:
value = x.dis_at (dis_i);
For convenience, if dis_i is managed by the current processor, this function returns also the value.
NOTE
The class takes two template parameters: one for the type T and the second for the memory model M, that could be either M=distributed or M=sequential. The two cases are associated to two different implementations, but proposes exactly the same interface. The sequential interface propose also a supplementary constructor:
disarray<double,sequential> x(local_size, init_val);
This constructor is a STL-like one but could be consufused in the distributed case, since there are two sizes: a local one and a global one. In that case, the use of the distributor, as a generalization of the size concept, clarify the situation (see distributor(2)).
IMPLEMENTATION NOTE
"scatter" via "get_dis_entry".
"gather" via "dis_entry(dis_i) = value" or "dis_entry(dis_i) += value". Note that += applies when T=idx_set where idx_set is a wrapper class of std::set<size_t> ; the += operator represents the union of a set. The operator= is used when T=double or others simple T types without algebra. If there is a conflict, i.e. several processes set the dis_i index, then the result of operator+= depends upon the order of the process at each run and is not deterministic. Such ambiguous behavior is not detected yet at run time.
IMPLEMENTATION
template
<class T, class A>
class disarray<T,sequential,A> : public
smart_pointer<disarray_rep<T,sequential,A> > {
public:
// typedefs:
typedef
disarray_rep<T,sequential,A> rep;
typedef smart_pointer<rep> base;
typedef
sequential memory_type;
typedef typename rep::size_type size_type;
typedef typename rep::difference_type difference_type;
typedef typename rep::value_type value_type;
typedef typename rep::reference reference;
typedef typename rep::dis_reference dis_reference;
typedef typename rep::iterator iterator;
typedef typename rep::const_reference const_reference;
typedef typename rep::const_iterator const_iterator;
// allocators:
disarray
(size_type loc_size = 0, const T& init_val = T(), const
A& alloc = A());
void resize (size_type loc_size = 0, const T& init_val =
T());
disarray (const distributor& ownership, const T&
init_val = T(), const A& alloc = A());
void resize (const distributor& ownership, const T&
init_val = T());
// local accessors & modifiers:
A
get_allocator() const { return base::data().get_allocator();
}
size_type size () const { return base::data().size(); }
size_type dis_size () const { return
base::data().dis_size(); }
const distributor& ownership() const { return
base::data().ownership(); }
const communicator& comm() const { return
ownership().comm(); }
reference
operator[] (size_type i) { return base::data().operator[]
(i); }
const_reference operator[] (size_type i) const { return
base::data().operator[] (i); }
reference operator() (size_type i) { return
base::data().operator[] (i); }
const_reference operator() (size_type i) const { return
base::data().operator[] (i); }
const_reference dis_at (size_type dis_i) const { return
operator[] (dis_i); }
iterator
begin() { return base::data().begin(); }
const_iterator begin() const { return base::data().begin();
}
iterator end() { return base::data().end(); }
const_iterator end() const { return base::data().end();
}
// global modifiers (for compatibility with distributed interface):
dis_reference
dis_entry (size_type dis_i) { return
base::data().dis_entry(dis_i); }
template<class SetOp = typename
default_set_op<T>::type>
void dis_entry_assembly (SetOp my_set_op = SetOp()) {}
template<class SetOp = typename
default_set_op<T>::type>
void dis_entry_assembly_begin (SetOp my_set_op = SetOp()) {}
template<class SetOp = typename
default_set_op<T>::type>
void dis_entry_assembly_end (SetOp my_set_op = SetOp())
{}
void
dis_entry_assembly_begin() {}
void dis_entry_assembly_end() {}
void dis_entry_assembly() {}
void
reset_dis_indexes() const {}
template<class Set> void set_dis_indexes (const
Set& ext_idx_set) const {}
template<class Set> void append_dis_indexes (const
Set& ext_idx_set) const {}
template<class Set, class Map> void append_dis_entry
(const Set& ext_idx_set, Map& ext_idx_map) const {}
template<class Set, class Map> void get_dis_entry
(const Set& ext_idx_set, Map& ext_idx_map) const
{}
// apply a partition:
template<class
RepSize>
void repartition ( // old_numbering for *this
const RepSize& partition, // old_ownership
disarray<T,sequential,A>& new_disarray, //
new_ownership (created)
RepSize& old_numbering, // new_ownership
RepSize& new_numbering) const // old_ownership
{ return base::data().repartition (partition, new_disarray,
old_numbering, new_numbering); }
template<class
RepSize>
void permutation_apply ( // old_numbering for *this
const RepSize& new_numbering, // old_ownership
disarray<T,sequential,A>& new_disarray) const //
new_ownership (already allocated)
{ return base::data().permutation_apply (new_numbering,
new_disarray); }
void
reverse_permutation ( // old_ownership for
*this=iold2dis_inew
disarray<size_type,sequential,A>& inew2dis_iold)
const // new_ownership
{ base::data().reverse_permutation (inew2dis_iold.data());
}
// i/o:
odiststream&
put_values (odiststream& ops) const { return
base::data().put_values(ops); }
idiststream& get_values (idiststream& ips) { return
base::data().get_values(ips); }
template <class GetFunction>
idiststream& get_values (idiststream& ips,
GetFunction get_element) { return
base::data().get_values(ips, get_element); }
template <class PutFunction>
odiststream& put_values (odiststream& ops,
PutFunction put_element) const { return
base::data().put_values(ops, put_element); }
void dump (std::string name) const { return
base::data().dump(name); }
};
IMPLEMENTATION
template
<class T, class A>
class disarray<T,distributed,A> : public
smart_pointer<disarray_rep<T,distributed,A> > {
public:
// typedefs:
typedef
disarray_rep<T,distributed,A> rep;
typedef smart_pointer<rep> base;
typedef
distributed memory_type;
typedef typename rep::size_type size_type;
typedef typename rep::difference_type difference_type;
typedef typename rep::value_type value_type;
typedef typename rep::reference reference;
typedef typename rep::dis_reference dis_reference;
typedef typename rep::iterator iterator;
typedef typename rep::const_reference const_reference;
typedef typename rep::const_iterator const_iterator;
typedef typename rep::scatter_map_type scatter_map_type;
// allocators:
disarray (const
distributor& ownership = distributor(), const T&
init_val = T(), const A& alloc = A());
void resize (const distributor& ownership =
distributor(), const T& init_val = T());
// local accessors & modifiers:
A
get_allocator() const { return base::data().get_allocator();
}
size_type size () const { return base::data().size(); }
size_type dis_size () const { return
base::data().dis_size(); }
const distributor& ownership() const { return
base::data().ownership(); }
const communicator& comm() const { return
base::data().comm(); }
reference
operator[] (size_type i) { return base::data().operator[]
(i); }
const_reference operator[] (size_type i) const { return
base::data().operator[] (i); }
reference operator() (size_type i) { return
base::data().operator[] (i); }
const_reference operator() (size_type i) const { return
base::data().operator[] (i); }
iterator
begin() { return base::data().begin(); }
const_iterator begin() const { return base::data().begin();
}
iterator end() { return base::data().end(); }
const_iterator end() const { return base::data().end();
}
// global accessor:
template<class
Set, class Map>
void append_dis_entry (const Set& ext_idx_set, Map&
ext_idx_map) const { base::data().append_dis_entry
(ext_idx_set, ext_idx_map); }
template<class
Set, class Map>
void get_dis_entry (const Set& ext_idx_set, Map&
ext_idx_map) const { base::data().get_dis_entry
(ext_idx_set, ext_idx_map); }
template<class
Set>
void append_dis_indexes (const Set& ext_idx_set) const {
base::data().append_dis_indexes (ext_idx_set); }
void reset_dis_indexes() const {
base::data().reset_dis_indexes(); }
template<class
Set>
void set_dis_indexes (const Set& ext_idx_set) const {
base::data().set_dis_indexes (ext_idx_set); }
const T& dis_at (size_type dis_i) const { return base::data().dis_at (dis_i); }
// get all
external pairs (dis_i, values):
const scatter_map_type& get_dis_map_entries() const {
return base::data().get_dis_map_entries(); }
// global modifiers (for compatibility with distributed interface):
dis_reference dis_entry (size_type dis_i) { return base::data().dis_entry(dis_i); }
template<class
SetOp = typename default_set_op<T>::type>
void dis_entry_assembly_begin (SetOp my_set_op = SetOp()) {
base::data().dis_entry_assembly_begin (my_set_op); }
template<class SetOp = typename
default_set_op<T>::type>
void dis_entry_assembly_end (SetOp my_set_op = SetOp()) {
base::data().dis_entry_assembly_end (my_set_op); }
template<class SetOp = typename
default_set_op<T>::type>
void dis_entry_assembly (SetOp my_set_op = SetOp()) {
base::data().dis_entry_assembly (my_set_op); }
void
dis_entry_assembly_begin() { base::data().template
dis_entry_assembly_begin<typename
default_set_op<T>::type>(); }
void dis_entry_assembly_end() { base::data().template
dis_entry_assembly_end<typename
default_set_op<T>::type>(); }
void dis_entry_assembly() { dis_entry_assembly_begin();
dis_entry_assembly_end(); }
// apply a partition:
template<class
RepSize>
void repartition ( // old_numbering for *this
const RepSize& partition, // old_ownership
disarray<T,distributed>& new_disarray, //
new_ownership (created)
RepSize& old_numbering, // new_ownership
RepSize& new_numbering) const // old_ownership
{ return base::data().repartition (partition.data(),
new_disarray.data(), old_numbering.data(),
new_numbering.data()); }
template<class
RepSize>
void permutation_apply ( // old_numbering for *this
const RepSize& new_numbering, // old_ownership
disarray<T,distributed,A>& new_disarray) const //
new_ownership (already allocated)
{ base::data().permutation_apply (new_numbering.data(),
new_disarray.data()); }
void
reverse_permutation ( // old_ownership for
*this=iold2dis_inew
disarray<size_type,distributed,A>& inew2dis_iold)
const // new_ownership
{ base::data().reverse_permutation (inew2dis_iold.data());
}
// i/o:
odiststream&
put_values (odiststream& ops) const { return
base::data().put_values(ops); }
idiststream& get_values (idiststream& ips) { return
base::data().get_values(ips); }
void dump (std::string name) const { return
base::data().dump(name); }
template
<class GetFunction>
idiststream& get_values (idiststream& ips,
GetFunction get_element) { return
base::data().get_values(ips, get_element); }
template <class PutFunction>
odiststream& put_values (odiststream& ops,
PutFunction put_element) const { return
base::data().put_values(ops, put_element); }
template <class PutFunction, class A2>
odiststream& permuted_put_values (
odiststream& ops, const
disarray<size_type,distributed,A2>& perm,
PutFunction put_element) const
{ return base::data().permuted_put_values (ops, perm.data(),
put_element); }
};
SEE ALSO
COPYRIGHT
Copyright (C) 2000-2018 Pierre Saramito <Pierre.Saramito [AT] imag.fr> GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>. This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law.