Fundamental Vector Reduction/Transformation Operator (RTOp) Interfaces
Version of the Day
|
Templated interface to vector reduction/transformation operators {abstract}. More...
#include <RTOpPack_RTOpT_decl.hpp>
public types | |
typedef PrimitiveTypeTraits < Scalar, Scalar > ::primitiveType | primitive_value_type |
Reduction object functions (NVI) | |
void | get_reduct_type_num_entries (const Ptr< int > &num_values, const Ptr< int > &num_indexes, const Ptr< int > &num_chars) const |
Get the number of entries of each basic data type in the externalized state for a reduction object for this operator. More... | |
Teuchos::RCP< ReductTarget > | reduct_obj_create () const |
Creates a new reduction target object initialized and ready to be used in a reduction. More... | |
void | reduce_reduct_objs (const ReductTarget &in_reduct_obj, const Ptr< ReductTarget > &inout_reduct_obj) const |
Reduce intermediate reduction target objects. More... | |
void | reduct_obj_reinit (const Ptr< ReductTarget > &reduct_obj) const |
Reinitialize an already created reduction object. More... | |
void | extract_reduct_obj_state (const ReductTarget &reduct_obj, const ArrayView< primitive_value_type > &value_data, const ArrayView< index_type > &index_data, const ArrayView< char_type > &char_data) const |
Extract the state of an already created reduction object. More... | |
void | load_reduct_obj_state (const ArrayView< const primitive_value_type > &value_data, const ArrayView< const index_type > &index_data, const ArrayView< const char_type > &char_data, const Ptr< ReductTarget > &reduct_obj) const |
Load the state of an already created reduction object given arrays of primitive objects. More... | |
Operator functions (NIV) | |
std::string | op_name () const |
Return the name (as a null-terminated C-style string) of the operator. More... | |
bool | coord_invariant () const |
Returns true if this operator is coordinate invariant. More... | |
Range1D | range () const |
Returns the continuous range of elements that this operator is defined over. More... | |
void | apply_op (const ArrayView< const ConstSubVectorView< Scalar > > &sub_vecs, const ArrayView< const SubVectorView< Scalar > > &targ_sub_vecs, const Ptr< ReductTarget > &reduct_obj) const |
Apply the reduction/transformation operator to a set of sub-vectors. More... | |
Protected virtual functions to be overridden by subclasses. | |
virtual void | get_reduct_type_num_entries_impl (const Ptr< int > &num_values, const Ptr< int > &num_indexes, const Ptr< int > &num_chars) const |
virtual Teuchos::RCP < ReductTarget > | reduct_obj_create_impl () const |
virtual void | reduce_reduct_objs_impl (const ReductTarget &in_reduct_obj, const Ptr< ReductTarget > &inout_reduct_obj) const |
virtual void | reduct_obj_reinit_impl (const Ptr< ReductTarget > &reduct_obj) const |
virtual void | extract_reduct_obj_state_impl (const ReductTarget &reduct_obj, const ArrayView< primitive_value_type > &value_data, const ArrayView< index_type > &index_data, const ArrayView< char_type > &char_data) const |
virtual void | load_reduct_obj_state_impl (const ArrayView< const primitive_value_type > &value_data, const ArrayView< const index_type > &index_data, const ArrayView< const char_type > &char_data, const Ptr< ReductTarget > &reduct_obj) const |
virtual std::string | op_name_impl () const |
virtual bool | coord_invariant_impl () const |
virtual Range1D | range_impl () const |
virtual void | apply_op_impl (const ArrayView< const ConstSubVectorView< Scalar > > &sub_vecs, const ArrayView< const SubVectorView< Scalar > > &targ_sub_vecs, const Ptr< ReductTarget > &reduct_obj) const =0 |
Nonvirtual protected functions. | |
RTOpT (const std::string &op_name_base="") | |
Constructor that creates an operator name appended with the type. More... | |
void | setOpNameBase (const std::string &op_name_base) |
Just set the operator name. More... | |
Templated interface to vector reduction/transformation operators {abstract}.
The purpose of this base class is to allow users to specify arbitrary reduction/transformation operations on vectors without requiring the vectors to reveal their implementation details. The design is motivated partly by the "Visitor" patter (Gamma, 1995).
This interface is designed to allow implementation of a distributed parallel abstract numerical algorithm without the explicit knowledge of the algorithm.
In the following discussion, v[k]
, x
, y
and z
are some abstract vector objects of dimension n
. Users can define operators to perform reduction and/or transformation operations. Reduction operations applied over all of the elements of a vector require communication between nodes in a parallel environment but do not change any of the vectors involved. Transformation operations don't require communication between nodes in a parallel environment. The targets of a transformation operation is a set of one or more vectors which are changed in some way.
The idea is that the user may want to perform reduction operations of the form:
op(v[0]...v[*],z[0]...z[*]) -> reduct_obj
where reduct_obj
is a single object based on a reduction over all the elements of the vector arguments, or transformation operations of the form:
op(v[0](i)...v[*](i),z[0](i)...z[*](i)) -> z[0](i)...z[*](i), for i = 0...n-1
Operators can also be defined that perform reduction and transformation operations on the same vectors that that should only be done for efficiency reasons.
The tricky part though, is that the reduct_obj
object of the reduction operation may be more complex than a single scalar value. For instance, it could be a double
and an int
pair such as in the reduction operation:
min{ |x(i)|, i = 0...n-1 } -> [ x(j_min), j_min ]
or it could perform several reductions at once and store several scalar values such as in:
min_max_sum{ x(i), i = 0...n-1 } -> [ x(j_min), j_min, x(j_max), j_max, x_sum ]
Transformation operations are much simpler to think about and to deal with. Some off-the-wall examples of transformation operations that this design will support are:
max{ |x(i)|, |y(i)| } + |z(i)| -> z(i), for i = 0...n-1 alpha * |z(i)| / x(i) -> z(i), for i = 0...n-1 alpha * x(i) * y(i) + beta * z(i) -> z(i), for i = 0...n-1
Reduction operations present the more difficult technical challenge since they require information gathered from all of the elements to arrive at the final result. This design allows operator classes to be defined that can simultaneously perform reduction and transformation operations:
op(v[0](i)...v[*](i),z[0](i)...z[*](i)) -> z[0](i)...z[*](i),reduct_obj, for i = 0...n-1
This design is based on a few assumptions about the reduction and transformation operations and vector implementations themselves. First, we will assume that vectors are stored and manipulated as chunks of sub-vectors (of dimension subDim
) where each sub-vector is sufficiently large to overcome the inherent overhead of this design. This design supports dense strided sub-vectors (see ConstSubVectorView
and SubVectorView
) but is relatively flexible.
It is strictly the responsibility of the vector implementations to determine how these operators are applied. For instance, if we are performing a transformation operation of the form:
op( x(i), y(i), z(i) ) -> z(i), for i = 0...n-1
where x
, y
, and z
are distributed parallel vectors, then we would assume that the elements would be partitioned onto the various processors with the same local elements stored on each processor so as not to require any communication between processors.
Definition at line 137 of file RTOpPack_RTOpT_decl.hpp.
typedef PrimitiveTypeTraits<Scalar,Scalar>::primitiveType RTOpPack::RTOpT< Scalar >::primitive_value_type |
Definition at line 145 of file RTOpPack_RTOpT_decl.hpp.
|
protected |
Constructor that creates an operator name appended with the type.
Definition at line 113 of file RTOpPack_RTOpT_def.hpp.
|
inline |
Get the number of entries of each basic data type in the externalized state for a reduction object for this operator.
Note that a specific reduction object is not passed in as an argument. This is because the structure of a reduction object is completely determined by its associated operator object and this structure can not change as a result of a reduction operation (this is needed to simplify global communication code when used * with MPI).
The default implementation returns zeros for *num_values
, *num_indexes
and *num_chars
(i.e. by default there is no reduction operation performed).
Definition at line 167 of file RTOpPack_RTOpT_decl.hpp.
|
inline |
Creates a new reduction target object initialized and ready to be used in a reduction.
The default implementation returns returnVal.get()==NULL
(i.e. by default there is no reduction operation performed).
Definition at line 182 of file RTOpPack_RTOpT_decl.hpp.
|
inline |
Reduce intermediate reduction target objects.
The default implementation does not do anything (i.e. by default there is no reduction operation performed).
Definition at line 192 of file RTOpPack_RTOpT_decl.hpp.
|
inline |
Reinitialize an already created reduction object.
The default implementation does nothing (i.e. by default there is no reduction operation performed).
reduct_obj | [in/out] Reduction object is reinitialized on output. |
Definition at line 206 of file RTOpPack_RTOpT_decl.hpp.
|
inline |
Extract the state of an already created reduction object.
This method allows the state of a reduction target object to be externalized so that it can be passed over a heterogeneous network of computers.
The default implementation does nothing (i.e. by default there is no reduction operation performed).
Definition at line 220 of file RTOpPack_RTOpT_decl.hpp.
|
inline |
Load the state of an already created reduction object given arrays of primitive objects.
The default implementation does nothing.
Definition at line 236 of file RTOpPack_RTOpT_decl.hpp.
|
inline |
Return the name (as a null-terminated C-style string) of the operator.
This name is used to differentiate an operator subclass from all other operator subclasses. This is an important property needed for a client/server or master/slave runtime configuration.
The default implementation uses the value created in the constructor RTOpT()
.
Definition at line 260 of file RTOpPack_RTOpT_decl.hpp.
|
inline |
Returns true
if this operator is coordinate invariant.
The default implementation returns true
as most vector operators are coordinate invariant.
Definition at line 274 of file RTOpPack_RTOpT_decl.hpp.
|
inline |
Returns the continuous range of elements that this operator is defined over.
Vector client implementations are free to ignore this but they can use this information to optimize rare operators that only interact with a subset of elements.
The default implementation return Range1D()
which means all of the elements.
Definition at line 289 of file RTOpPack_RTOpT_decl.hpp.
|
inline |
Apply the reduction/transformation operator to a set of sub-vectors.
op(sub_vecs[], targ_sub_vecs[], reduct_obj) -> targ_sub_vecs[], reduct_obj
.
This is the bread and butter of the whole design. Through this method, a vector implementation applies a reduction/transformation operator to a set of sub-vectors.
sub_vecs | [in] Array (length num_vecs ) of non-mutable vectors to apply the operator over. The ordering of these sub-vectors sub_vecs[k], for k = 0...num_vecs-1 , is significant to the this operator object. If num_vecs==0 then sub_vecs can be NULL . |
targ_sub_vecs | [in/out] Array (length num_targ_vecs ) of mutable vectors to apply the operator over and be mutated. The ordering of these sub-vectors targ_sub_vecs[k], for k = 0...num_targ_vecs-1 , is significant to this operator object. If num_targ_vecs==0 then targ_sub_vecs can be NULL . |
reduct_obj | [in/out] This reduction object must have been created by a this->reduct_obj_create() call and it may have * already passed through one or more other reduction operations (accumulating the reductions along the way). If this->get_reduct_type_num_entries() returns num_values==0 , num_indexes==0 and num_chars==0 , then reduct_obj should be set to NULL as no reduction will be performed. |
Preconditions:
globalOffset==sub_vecs[k].globalOffset
, for k = 0,...,sub_vecs.subDim()-1
globalOffset==targ_sub_vecs[k].globalOffset
, for k = 0,...,targ_vecs.subDim()-1
subDim==sub_vecs[k].subDim()
, for k = 0,...,sub_vecs.subDim()-1
subDim==targ_sub_vecs[k].subDim()
, for k = 0,...,targ_vecs.subDim()-1
If nonnull(reduct_obj)==true
then the reduction operation will be accumulated as:
op(sub_vecs[], targ_sub_vecs[], reduct_obj) -> reduct_obj
By allowing an in/out reduct_obj
and an accumulation of the reduction, the maximum reuse of memory is achieved. If this->reduct_obj_create()
or this->reduct_obj_reinit()
(passing in reduct_obj
) was called immediately before this function, then on return, reduct_obj
will contain only the reduction from this function call.
If the sizes of sub_vecs
and targ_sub_vecs
is incompatible with the underlying operator object then InvalidNumVecs
is thrown. If the sub-vectors are not compatible (i.e. globalOffset
and/or subDim
not the same) then IncompatibleVecs
is thrown.
Definition at line 362 of file RTOpPack_RTOpT_decl.hpp.
|
protectedvirtual |
Definition at line 27 of file RTOpPack_RTOpT_def.hpp.
|
protectedvirtual |
Definition at line 41 of file RTOpPack_RTOpT_def.hpp.
|
protectedvirtual |
Definition at line 48 of file RTOpPack_RTOpT_def.hpp.
|
protectedvirtual |
Definition at line 57 of file RTOpPack_RTOpT_def.hpp.
|
protectedvirtual |
Definition at line 65 of file RTOpPack_RTOpT_def.hpp.
|
protectedvirtual |
Definition at line 77 of file RTOpPack_RTOpT_def.hpp.
|
protectedvirtual |
Definition at line 89 of file RTOpPack_RTOpT_def.hpp.
|
protectedvirtual |
Definition at line 96 of file RTOpPack_RTOpT_def.hpp.
|
protectedvirtual |
Definition at line 103 of file RTOpPack_RTOpT_def.hpp.
|
protectedpure virtual |
|
protected |
Just set the operator name.
Definition at line 120 of file RTOpPack_RTOpT_def.hpp.