Developer Guide and Reference

Contents

Accessor Concept

Accessor and const_accessor objects obtained via
n_container::access()
and
n_container::const_access()
provide access to read from or write to cells inside an
n_container
.

Syntax

The following methods return objects meeting the requirements of the accessor concept.
auto n_container::access(); auto n_container::const_access(); auto accessor_concept::section(n_bounds_t<…>); auto accessor_concept::translated_to(n_index_t<…>); auto accessor_concept::translated_to_zero();
Description
Accessor objects provide read/write access to individual cells of an n-dimensional container. Index values passed to a sequence of array subscript operator calls will produce a proxy concept that can import to or export the primitive data the corresponding cell inside the container.
auto image = make_n_container<MyStruct, layout::soa>(n_extent[128][256]); auto acc = image.access(); MyStruct in_value(100.0f, 200.0f, 300.0f); acc[64][128] = in_value; MyStruct out_value = acc[64][128]; assert(out_value == in_value);
Accessors also know their valid iteration space, which can queried using the template function bound_d<int DimensionT>(accessor).
assert(bounds_d<0>(acc) == bounds(0_fixed,128)); assert(bounds_d<1>(acc) == bounds(0_fixed,256));
An accessor may have a non-zero index space if it has a translation embedded into it,
bounds_d
will reflect any such translation.
auto shifted_acc = acc.translated_to(n_index[1000][2000]); assert(bounds_d<0>(shifted_acc) == bounds(1000,1128)); assert(bounds_d<1>(shifted_acc) == bounds(2000,2256));
This is useful to have a smaller sized container participate in a calculation over a portion of a larger index space, simplifying programming as the same index variable can be used, and the accessor takes care of applying the necessary translation. An accessor may represent a subsection over the original extents, bounds_d will identify the valid iteration space for that accessor.
auto subsection_acc = a.section(n_bounds[bounds(64,96)][bounds(128,160)]); assert(bounds_d<0>(subsection_acc) == bounds(64, 96)); assert(bounds_d<1>(subsection_acc) == bounds(128, 160);
It can also be useful to have subsections be translated back to start their iteration space at 0. For efficiency, the translated_to_zero() method is provided to create an accessor shifted back to zero.
auto zb_sub_acc = a.section( n_bounds[bounds(64, 96)][bounds(128, 160)] ).translated_to_zero(); assert(bounds_d<0>(zb_sub_acc) == bounds(0, 32)); assert(bounds_d<1>(zb_sub_acc) == bounds(0, 32));
If fewer array subscript calls applied to an accessor than its rank, the result is another accessor of a lower rank. This can be useful to obtain accessors suitable to pass to code expecting lower rank accessors. Such as a obtaining a 3d accessor from a 4d container by specifying only a single index via array subscript. This has the effect of embedding the index value of the dimension inside accessor. When the final dimension is sliced, the result is a proxy object to the cell inside the container corresponding to the embedded index values inside the sliced accessors
auto image4d = make_n_container<MyStruct, layout::soa>(n_extent[10][20][128][256]); MyStruct in_value(100.0f, 200.0f, 300.0f); auto acc4d = image4d.access(); auto acc3d = acc4d[5]; auto acc2d = acc3d[10]; auto acc1d = acc2d[64]; acc1d[128] = in_value; MyStruct out_value = acc4d[5][10][64][128]; assert(out_value == in_value);
The following table provides information on the requirements of the accessor concept.
Pseudo-Signature
Description
typedef PrimitiveT primitive_type;
Data type inside the cells of the container.
static constexpr int rank;
Number of free dimensions of accessor
accessor_concept(const accessor_concept &a_other)
Effects: constructs a copy of another accessor of the exact same type
template<typename IndexT> element_concept operator[] (const IndexT a_index) const
Requirements:
rank == 1 and IndexT is one of: int, aligned<AlignmentT>, fixed<NumberT>, linear_index, or simd_index<LaneCountT>
Effects:
When only 1 free dimension is left, the operator[] will construct an element_concept which is the proxy to the cell inside the container. If this accessor was obtained with const_access(), then the proxy will provide read only interface to the cell’s data.
Returns:
The proxy object to cell inside the container corresponding to the position identified by the a_index along with any embedded index values for other dimensions
template<typename IndexT> accessor_concept operator[] (const IndexT a_index) const
Requirements:
rank > 1 and IndexT is one of: int, aligned<AlignmentT>, fixed<NumberT>, linear_index, or simd_index<LaneCountT>
Effects:
When 2 or more free dimensions are left, the operator[] will construct another accessor_concept of lower rank embeding a_index inside of it, effectively fixing that dimension’s index value for any accesses made through the returned accessor_concept.
Returns:
The accessor_concept of lower rank ( one less free dimension).
template<int DimensionT> auto bounds_d() const
Requirements:
DimensionT >=0 and DimensionT < rank
Effects:
Determine the bounds of a free dimension using DimensionT as a 0 based index starting at the leftmost dimension.
Returns:
bounds_t of the DimensionT
auto bounds_dXX() const where XX is 0-19
Requirements:
XX >=0 and XX < rank and XX < 20
Effects:
Non templated methods to determine the bounds of a free dimension using XX as a 0 based index starting at the leftmost dimension.
Returns:
bounds_t of the XX dimension
template<int DimensionT> auto extent_d() const
Requirements:
DimensionT >=0 and DimensionT < rank
Effects:
Determine the extent of a free dimension using DimensionT as a 0 based index starting at the leftmost dimension.
Returns: extent of the DimensionT
auto extent_dXX() const where XX is 0-19
Requirements:
XX >=0 and XX < rank and XX < 20
Effects:
Non templated methods to determine the extent of a free dimension using XX as a 0 based index starting at the leftmost dimension.
Returns: extent of the XX dimension
template<typename ...IndexListT> accessor_concept translated_to( n_index_t<IndexListT...> a_n_index) const
Requirements:
a_n_index has same rank as the accessor
Effects:
construct an accessor_concept with an embedded translation such that accessing a_n_index will corresponds back to the current lower bounds. Easy way to think of it is that current iteration space is translated to a_n_index space.
Returns:
accessor_concept whose bounds have the same extents, but whose lower bounds start at the supplied a_n_index
template<typename ...IndexListT> accessor_concept translated_to_zero() const
Effects:
construct an accessor_concept with an embedded translation such that accessing [0] index for all dimensions will corresponds back to the current lower bounds. Easy way to think of it is that current iteration space is translated to [0] for all free dimensions.
Returns:
accessor_concept whose bounds have the same extents, but whose lower bounds start [0]…[0]
template<typename ...BoundsTypeListT> auto section(const n_bounds_t<BoundsTypeListT...> &a_n_bounds) const
Requirements:
a_n_bounds has same rank as the accessor and a_n_bounds is contained by the accessors current bounds.
Effects:
construct an accessor_concept with using the supplied a_n_bounds to represent its valid iteration space. Because a_n_bounds must be contained within the existing bounds, we are effictively creating an accessor over a section of the container. Easy way to think of it is that current bounds are being restricted to a_n_bounds. Note: can be useful to chain a call
translated_to_zero()
on to the return value.
Returns:
accessor_concept
whose bounds are set to the supplied a_n_bounds

Product and Performance Information

1

Performance varies by use, configuration and other factors. Learn more at www.Intel.com/PerformanceIndex.