DASH Use Cases
Containers
Array
Fully specified type
// element type (double), index type (dash::default_index_t), pattern type
dash::Array<
double, dash::default_index_t,
dash::BlockPattern<1, ROW_MAJOR, dash::default_index_t>
> array(
size,
dash::DistributionSpec<1>(BLOCKED(blocksize)),
dash::Team::All()
);
Algorithms
Transform
// Add local values to global container elements (corresponds to MPI_Accumulate)
dash::Array<int> array;
std::vector<int> local_values;
// Blocking acculumate.
// Add local elements to global container elements starting from global index 100:
dash::transform(
// Range of left-hand side values to add (lhs)
local_values.begin(), local_values.end(),
// Range of right-hand side values to add (rhs)
array[100],
// Start of result range (out)
array[100],
// Binary operation to perform (op | out[i] = op(lhs[i], rhs[i])
dash::plus<int>());
Pattern Traits
Deduction and verification of optimal distribution schemes.
Compile-Time Constraints Checking
Scenario
A concrete implementation of an operation verifies that it complies with a given distribution pattern.
Example
using namespace dash;
static_assert(
dash::pattern_contraints<
pattern_blocking_properties< pattern_blocking_tag::balanced >,
pattern_topology_properties< pattern_topology_tag::diagonal >,
pattern_indexing_properties< pattern_indexing_tag::local_strided >
>::satisfied::value
);
Run-Time Constraints Checking
Scenario
An implementation makes a decision at run-time depending on properties implemented by a distribution pattern.
Example
using namespace dash;
if (dash::check_pattern_contraints<
pattern_blocking_properties< pattern_blocking_tag::balanced >,
pattern_topology_properties< pattern_topology_tag::diagonal >,
pattern_indexing_properties< pattern_indexing_tag::local_strided >
>(pattern))
{
// Object 'pattern' satisfies constraints
}
Automatically Deduction of Pattern from Set of Properties
Scenario
Desired properties on data distribution are known, automatically resolve a pattern that implements them.
Example
static const dash::dim_t NumDimensions = 2;
// Topology of processes, here: 16x8 process grid, may have any number of dimensions <= NumDimensions
TeamSpec<2> teamspec(16, 8);
// Cartesian extents of container:
SizeSpec<NumDimensions> sizespec(extent_x, extent_y);
// Create instance of pattern type deduced from given constraints at compile time:
auto pattern = dash::make_pattern<
// How elements are mapped to blocks
pattern_blocking_properties<
pattern_blocking_tag::balanced // same number of elements in every block
>,
// How blocks are mapped to processes
pattern_topology_properties<
pattern_topology_tag::balanced, // same amount of blocks for every process
pattern_topology_tag::diagonal // every process mapped in every row/column
>,
// How local elements are indexed
pattern_indexing_properties<
pattern_indexing_tag::in_block // elements contiguous within block
>
>(sizespec, teamspec);
Automatic Deduction of Algorithm Variant from Pattern Instance
Scenario
Data distribution is fixed, automatically resolve optimal algorithm.
Example
typedef dash::TilePattern<2, int> TiledPattern;
typedef dash::Matrix<2, int, TiledPattern> TiledMatrix;
typedef dash::StridePattern<2, int> StridedPattern;
typedef dash::Matrix<2, int, StridedPattern> StridedMatrix;
TiledPattern tpattern(global_extent_x, global_extent_y,
TILE(tilesize_x), TILE(tilesize_y));
StridedPattern spattern(global_extent_x, global_extent_y,
TILE(tilesize_x), TILE(tilesize_y));
TiledMatrix At(pattern);
TiledMatrix Bt(pattern);
TiledMatrix Ct(pattern);
StridedMatrix As(pattern);
StridedMatrix Bs(pattern);
StridedMatrix Cs(pattern);
// Initialize values in matrix_a and matrix_b ...
// Automatically resolves xDGEMM-algorithm that is optimized for
// properties guaranteed by matrix pattern types:
dash::multiply(At, Bt, Ct); // --> dash::summa(At, Bt, Ct);
dash::multiply(As, Bs, Cs); // --> dash::cannon(As, Bs, Cs);