The library provides data-parallel types and operations on these types: portable types for explicitly stating data-parallelism and structuring data through data-parallel execution resources where available, such as SIMD registers and instructions or execution units that are driven by a common instruction decoder.
The set of vectorizable types comprises:
T
is a vectorizable floating-point type.A data-parallel type consists of one or more elements of an underlying vectorizable type, called the element type . The number of elements, called the width , is constant for each data-parallel type.
The data-parallel type refers to all enabled specializations of the class templates basic_simd
and basic_simd_mask
.
A data-parallel object of data-parallel type behaves analogously to objects of type T
. But while T
stores and manipulates a single value, the data-parallel type with the element type T
stores and manipulates multiple values.
Every operation on a data-parallel object acts element-wise (except for horizontal operations, such as reductions, which are clearly marked as such) applying to each element of the object or to corresponding elements of two objects. Each such application is unsequenced with respect to the others. This simple rule expresses data-parallelism and will be used by the compiler to generate SIMD instructions and/or independent execution streams.
All operations (except non-constexpr math function overloads) on data-parallel objects are constexpr: it is possible to create and use data-parallel objects in the evaluation of a constant expression.
Alias templates simd
and simd_mask
are defined to allow users to specify the width to a certain size. The default width is determined by the implementation at compile-time.
All functions in <cmath> and <complex> are overloaded for basic_simd
.
All bit manipulation functions in <bit> are overloaded for basic_simd
.
The data-parallel types basic_simd
and basic_simd_mask
are associated with ABI tags . These tags are types that specify the size and binary representation of data-parallel objects. The design intends the size and binary representation to vary based on target architecture and compiler flags. The ABI tag, together with the element type, determines the width.
The ABI tag remains independent of machine instruction set selection. The chosen machine instruction set limits the usable ABI tag types. The ABI tags enable users to safely pass objects of data-parallel type across translation unit boundaries.
[edit] Exposition-only entitiesusing /*simd-size-type*/ = /* see description */;
(1) (exposition only*) template< std::size_t Bytes >template< class T, class Abi >
constexpr /*simd-size-type*/ /*simd-size-v*/ = /* see description */;
template< class T >
concept /*constexpr-wrapper-like*/ = /* see description */;
template< class T >
using /*deduced-simd-t*/ = /* see description */;
template< class V, class T >
using /*make-compatible-simd-t*/ = /* see description */;
1) /*simd-size-type*/ is an alias for for a signed integer type. The implementation is free to choose any signed integer type.
2) /*integer-from*/<Bytes> is an alias for a signed integer type T
such that sizeof(T) equals Bytes.
3) /*simd-size-v*/<T, Abi> denotes the width of the enabled specialization basic_simd<T, Abi>
, or â0â otherwise.
4) If T
denotes std::datapar::basic_simd_mask<Bytes, Abi>, /*mask-element-size*/<T> equals Bytes.
The concept
/*constexpr-wrapper-like*/is defined as:
6)Let
xbe an lvalue of type
const T.
/*deduced-simd-t*/<T>is an alias equivalent to:
basic_simd
; otherwiseLet
xbe an lvalue of type
const T.
/*make-compatible-simd-t*/<V, T>is an alias equivalent to:
Math functions requirements
template< class V >
concept /*simd-floating-point*/ = /* see description */;
template< class... Ts >
concept /*math-floating-point*/ = /* see description */;
requires /*math-floating-point*/<Ts...>
template< class BinaryOp, class T >
concept /*reduction-binary-operation*/ = /* see description */;
The concept
/*simd-floating-point*/is defined as:
9)The concept
/*math-floating-point*/is defined as:
template< class... Ts > concept /*math-floating-point*/ = (/*simd-floating-point*/</*deduced-simd-t*/<Ts>> || ...);10)
Let
T0
denote
Ts...[0],
T1
denote
Ts...[1], and
TRest
denote a pack such that
T0, T1, TRest...is equivalent to
Ts.... Then,
/*math-common-simd-t*/<Ts...>is an alias equivalent to:
The concept
/*reduction-binary-operation*/is defined as:
template< class BinaryOp, class T > concept /*reduction-binary-operation*/ = requires (const BinaryOp binary_op, const std::datapar::simd<T, 1> v) { { binary_op(v, v) } -> std::same_as<std::datapar::simd<T, 1>>; };
/*reduction-binary-operation*/<BinaryOp, T> is modeled only if:
BinaryOp
is a binary element-wise operation that is commutative, andBinaryOp
is invocable with two arguments of type std::datapar::basic_simd<T, Abi> for unspecified ABI tag Abi
that returns a std::datapar::basic_simd<T, Abi>.SIMD ABI tags
template< class T >
using /*native-abi*/ = /* see description */;
template< class T, /*simd-size-type*/ N >
using /*deduce-abi-t*/ = /* see description */;
12) /*native-abi*/<T> is an implementation-defined alias for an ABI tag. This is the primary ABI tag to use for efficient explicit vectorization. As a result, basic_simd<T, /*native-abi*/<T>> is an enabled specialization.
13) /*deduce-abi-t*/<T, N>is an alias that names an ABI tag type such that:
It is defined only if
T
is a vectorizable type, and
N > 0 && N <= Mis
true, where
Mis an implementation-defined maximum that is at least
64and can differ depending on
T
.
Load and store flags
struct /*convert-flag*/;
(14) (exposition only*)struct /*aligned-flag*/;
(15) (exposition only*) (16) (exposition only*) 14-16)These tag types are used as a template argument of
std::datapar::flags
. See
load and store flagsfor their corresponding uses.
[edit] Notes [edit] Example#include <iostream> #include <simd> #include <string_view> void println(std::string_view name, auto const& a) { std::cout << name << ": "; for (std::size_t i{}; i != a.size(); ++i) std::cout << a[i] << ' '; std::cout << '\n'; } template<class A> constexpr std::datapar::basic_simd<int, A> my_abs(std::datapar::basic_simd<int, A> x) { return std::datapar::select(x < 0, -x, x); } int main() { constexpr std::datapar::simd<int> a = 1; println("a", a); constexpr std::datapar::simd<int> b([](int i) { return i - 2; }); println("b", b); constexpr auto c = a + b; println("c", c); constexpr auto d = my_abs(c); println("d", d); constexpr auto e = d * d; println("e", e); constexpr auto inner_product = std::datapar::reduce(e); std::cout << "inner product: " << inner_product << '\n'; constexpr std::datapar::simd<double, 16> x([](int i) { return i; }); println("x", x); // overloaded math functions are defined in <simd> println("cos²(x) + sin²(x)", std::pow(std::cos(x), 2) + std::pow(std::sin(x), 2)); }
Output:
a: 1 1 1 1 b: -2 -1 0 1 c: -1 0 1 2 d: 1 0 1 2 e: 1 0 1 4 inner product: 6 x: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 cos²(x) + sin²(x): 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1[edit] See also numeric arrays, array masks and array slices
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4