.\" .de Id .. .de Sp .if n .sp .if t .sp 0.4 .. .TH disarray 2rheolef "rheolef-6.7" "rheolef-6.7" "rheolef-6.7" .\" label: /*Class:disarray .SH NAME \fBdisarray\fP - container in distributed environment (rheolef-6.7) .SH SYNOPSYS STL-like vector container for a distributed memory machine model. .SH EXAMPLE A sample usage of the class is: .\" begin_example .Sp .nf int main(int argc, char**argv) { environment distributed(argc, argv); disarray x(distributor(100), 3.14); dout << x << endl; } .Sp .fi .\" end_example The disarray interface is similar to those of the std::vector with the addition of some communication features in the distributed case: write accesses with entry/assembly and read access with dis_at. .PP .SH DISTRIBUTED WRITE ACCESS Loop on any \fBdis_i\fP that is not managed by the current processor: .\" begin_example .Sp .nf x.dis_entry (dis_i) = value; .Sp .fi .\" end_example and then, after loop, perform all communication: .\" begin_example .Sp .nf x.dis_entry_assembly(); .Sp .fi .\" end_example After this command, each value is stored in the disarray, available the processor associated to \fBdis_i\fP. .SH DISTRIBUTED READ ACCESS First, define the set of indexes: .\" begin_example .Sp .nf std::set ext_idx_set; .Sp .fi .\" end_example Then, loop on \fBdis_i\fP indexes that are not managed by the current processor: .\" begin_example .Sp .nf ext_idx_set.insert (dis_i); .Sp .fi .\" end_example After the loop, performs the communications: .\" begin_example .Sp .nf x.set_dis_indexes (ext_idx_set); .Sp .fi .\" end_example After this command, each values associated to the \fBdis_i\fP index, and that belongs to the index set, is now available also on the current processor as: .\" begin_example .Sp .nf value = x.dis_at (dis_i); .Sp .fi .\" end_example For convenience, if \fBdis_i\fP is managed by the current processor, this function returns also the value. .SH 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 diferent implementations, but proposes exactly the same interface. The sequential interface propose also a supplementary constructor: .\" begin_example .Sp .nf disarray x(local_size, init_val); .Sp .fi .\" end_example 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)). .PP .SH IMPLEMENTATION NOTE "scatter" via "get_dis_entry". .PP "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 ; 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. .PP .\" skip start:AUTHOR: .\" END .SH IMPLEMENTATION .\" begin_example .Sp .nf template class disarray : public smart_pointer > { public: // typedefs: typedef disarray_rep rep; typedef smart_pointer 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::type> void dis_entry_assembly (SetOp my_set_op = SetOp()) {} template::type> void dis_entry_assembly_begin (SetOp my_set_op = SetOp()) {} template::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 void set_dis_indexes (const Set& ext_idx_set) const {} template void append_dis_indexes (const Set& ext_idx_set) const {} template void append_dis_entry (const Set& ext_idx_set, Map& ext_idx_map) const {} template void get_dis_entry (const Set& ext_idx_set, Map& ext_idx_map) const {} // apply a partition: template void repartition ( // old_numbering for *this const RepSize& partition, // old_ownership disarray& 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 void permutation_apply ( // old_numbering for *this const RepSize& new_numbering, // old_ownership disarray& 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& 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 idiststream& get_values (idiststream& ips, GetFunction get_element) { return base::data().get_values(ips, get_element); } template 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); } }; .Sp .fi .\" end_example .SH IMPLEMENTATION .\" begin_example .Sp .nf template class disarray : public smart_pointer > { public: // typedefs: typedef disarray_rep rep; typedef smart_pointer 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 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 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 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 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::type> void dis_entry_assembly_begin (SetOp my_set_op = SetOp()) { base::data().dis_entry_assembly_begin (my_set_op); } template::type> void dis_entry_assembly_end (SetOp my_set_op = SetOp()) { base::data().dis_entry_assembly_end (my_set_op); } template::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::type>(); } void dis_entry_assembly_end() { base::data().template dis_entry_assembly_end::type>(); } void dis_entry_assembly() { dis_entry_assembly_begin(); dis_entry_assembly_end(); } // apply a partition: template void repartition ( // old_numbering for *this const RepSize& partition, // old_ownership disarray& 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 void permutation_apply ( // old_numbering for *this const RepSize& new_numbering, // old_ownership disarray& 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& 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 idiststream& get_values (idiststream& ips, GetFunction get_element) { return base::data().get_values(ips, get_element); } template odiststream& put_values (odiststream& ops, PutFunction put_element) const { return base::data().put_values(ops, put_element); } template odiststream& permuted_put_values ( odiststream& ops, const disarray& perm, PutFunction put_element) const { return base::data().permuted_put_values (ops, perm.data(), put_element); } }; .Sp .fi .\" end_example .\" LENGTH = 1 .SH SEE ALSO distributor(2)