Intel® oneAPI DPC++/C++ Compiler Developer Guide and Reference

ID 767253
Date 3/22/2024
Public

A newer version of this document is available. Customers should click here to go to the newest version.

Document Table of Contents

Number Representation

When specifying extents, positions inside of, or bounds of a container, numeric values can be represented three different ways: fixed, aligned, and int. Fixed is most precise and int is least precise. It is advised to use as precise specification as possible. The compiler may optimize better with more information.

Fixed

Represent a numerical constant whose value specified at compile time.

template <int NumberT> class fixed;

If offsets applied to index values inside a SIMD loop are known at compile time, then the compiler can use that information. For example, to maintain aligned access, if boundary is fixed and known to be aligned when accessing underlying data layout. When multiple accesses are happening near each other, the compiler will have the opportunity to detect which accesses occur in the same cache lines and potentially avoid prefetching the same cache line repeatedly. Additionally, if the start of an iteration space is known at compile time, if it's a multiple of the SIMD lane count, the compiler could skip generating a peel loop. Whenever possible, fixed values should be used over aligned or arbitrary integer values.

Although std::integral_constant<int> provides the same functionality, the library defines own type to provide overloaded operators and avoid collisions with any other code's interactions with std::integral_constant<int>.

The following table provides information about the template arguments for fixed.

Template Argument Description

int Number T

The numerical value the fixed will represent.

The following table provides information about the members of fixed.

Member Description
static constexpr int value = NumberT 
The numerical value known at compile-time.
constexpr operator value_type() const

Returns: The numerical value

constexpr value_type operator()() const;

Returns: The numerical value

Constant expression arithmetic operators +,- (both unary and binary), * and / are defined for type sdlt::fixed<> and will be evaluated at compile-time.

The suffix _fixed is a C++11 user-defined equivalent literal. For example, 1080_fixed is equivalent to fixed<1080>. Consider the readability of the two samples below.

foo3d(fixed<1080>(), fixed<1920>());

versus

foo3d(1080_fixed, 1920_fixed);

NOTE:
This note does not apply to SYCL. The sdlt::fixed<NumberT> type supersedes the deprecated sdlt::fixed_offset<OffsetT> type found in SDLT v1. It is strongly advised to use sdlt::fixed<NumberT>. However, in this release, a template alias is provided mapping sdlt::fixed_offset<OffsetT> onto sdlt::fixed<NumberT>.

Aligned

Represent integer value known at compile time to be a multiple of an IndexAlignment.

template <int IndexAlignmentT> class aligned;

If you can tell the compiler that you know that an integer will be a multiple of known value, then, when combined with a loop index inside a SIMD loop, the compiler can use that information to maintain aligned access when accessing underlying data layout.

Internally, the integer value is converted to a block count, where:

block_count = value/IndexAlignmentT;

Overloaded math operations can then use that aligned block count as needed. The value() is represented by AlignmentT*block_count allowing the compiler to prove that the value() is a multiple of AlignmentT, which can utilize alignment optimizations.

The following table provides information about the template arguments for aligned.

Template Argument Description

int IndexAlignmentT

The alignment the user is stating that the number is a multiple of. IndexAlignmentT must be a power of two.

The following table provides information about the types defined as members of aligned.

Member Type Description

typedef int value_type

The type of the numerical value.

typedef int block_type

The type of the block_count.

The following table provides information about the members of aligned.

Member Description
static const int index_alignment  

The IndexAlignmentT value.

aligned()

Constructs empty (uninitialized) object

explicit aligned(value_type)

Constructs computing block_count=a_value/IndexAlignmentT.

aligned(const aligned& a_other)

Constructs copying block_count from a_other. a_other must have same IndexAlignmentT.

template<int OtherAlignment>
explicit aligned(const aligned& other)

Constructs computing block_count optimized by avoiding computing other.value(). Must have IndexAlignmentT of a_other < IndexAlignmentT and other.value() be multiple of IndexAlignmentT.

template<int OtherAlignment>
aligned(const aligned& other)

Constructs computing block_count with a multiply instead of divide. Must have IndexAlignmentT of a_other > IndexAlignmentT

static aligned from_block_count(block_type block_count)

Creates an instance of aligned avoiding any math by directly using supplied block_count

value_type value() const 

Computes the value represented by the aligned.

Returns: aligned_block_count()*IndexAlignmentT

operator value_type()

Conversion to int.

Returns: value()

block_type aligned_block_count() const

Conversion to int.

Returns: The block count

The following operations are supported for the aligned type.

Operation Description
operator *(int), commutative
Scale value.

Returns: aligned<IndexAlignmentT >

operator *(fixed<V>), commutative

Scales IndexAlignment by 2^M and value by K. Must have V=2^M*K (V is a multiple of a power of 2).

Returns: aligned<IndexAlignmentT*(2^M)>

operator *(aligned<OtherAl>)

Scales IndexAlignment by OtherAl and block_count by argument.

Returns: aligned<IndexAlignmentT*OtherAl>

int operator/(fixed<IndexAlignmentT>)

Returns: aligned_block_count()

int operator/(fixed<-IndexAlignmentT>)

Returns: -aligned_block_count();

int operator/(fixed<V>)

Must have abs(V)>IndexAlignmentT && IndexAlignmentT%V==0.

Returns: aligned_block_count()/(V/IndexAlignmentT)

int operator/(fixed<V>)

Must have abs(V) < IndexAlignmentT && V%IndexAlignmentT==0

Returns: aligned_block_count()*(IndexAlignmentT/V)

aligned operator -()

Returns: Same type aligned for negated value.

aligned operator -(const aligned &)
                const 

Returns: Same type aligned for value of difference.

template<int OtherAl> 
aligned<?> operator -(const aligned<OtherAl>&) const 

Difference with other alignment. Behavior and returned alignment type depend on relation between alignments of operands.

Returns: Value for difference as lower of incoming alignments

template<int V>
aligned<?> operator -(const fixed<V> &) const 

Difference with fixed value. Behavior and returned alignment type depend on relation between alignments of aligned<> operand and the value of V.

Returns: Adjusted aligned value of a difference

aligned operator +(const aligned &)const

Returns: Same type aligned for value of sum

template<int OtherAl>
aligned<?> operator +(const aligned<OtherAl>&) const 

Sum with other alignment. Behavior and returned alignment type depend on relation between alignments of operands.

Returns: Value for sum as lower of incoming alignments

template<int V>
aligned<?> operator +(const fixed<V> &) const

Sum with fixed value. Behavior and returned alignment type depend on relation between alignments of aligned<> operand and the value of V.

Returns: Adjusted aligned value of a sum.

template<int OtherAl>
aligned operator +=(const aligned<OtherAl> &) const

Increments value for the aligned object if IndexAlignmentT is compatible with OtherAl

Returns: Aligned with incremented value.

template<int OtherAl>
aligned operator -=(const aligned<OtherAl> &) const

Decrements value for the aligned object if IndexAlignmentT is compatible with OtherAl

Returns: Same type aligned with decremented value.

template<int OtherAl>
aligned operator *=(const aligned<OtherAl> &) const

Multiplies value for the aligned object if IndexAlignmentT is compatible with OtherAl.

Returns: Same type aligned with multiplied value.

template<int OtherAl>
aligned operator /=(const aligned<OtherAl> &) const

Divides value for the aligned object if IndexAlignmentT is compatible with OtherAl

Returns: Same type aligned with divided value.

NOTE:
This note does not apply to SYCL. The sdlt::aligned<> type supersedes the deprecated sdlt::aligned_offset<> type found in SDLT v1. It is strongly advised to use sdlt::aligned<>, however in this release a template alias is provided mapping sdlt::aligned_offset<> onto sdlt::aligned<>.

int

Represents an arbitrary integer value. In interfaces where fixed<> and aligned<> values supported you may also use plain old integer value. It provides least information among these three and so least facilitates compiler optimizations.