SIMD library
The SIMD library provides portable types for explicitly stating data-parallelism and structuring data for more efficient SIMD access.
An object of type simd<T> behaves analogue to objects of type T
. But while T
stores and manipulates one value, simd<T>
stores and manipulates multiple values (called width but identified as size for consistency with the rest of the standard library; cf. simd_size).
Every operator and operation on simd<T>
acts element-wise (except for horizontal operations, which are clearly marked as such). This simple rule expresses data-parallelism and will be used by the compiler to generate SIMD instructions and/or independent execution streams.
The width of the types simd<T>
and native_simd<T> is determined by the implementation at compile-time. In contrast, the width of the type fixed_size_simd<T, N> is fixed by the developer to a certain size.
A recommended pattern for using a mix of different SIMD types with high efficiency uses native_simd and rebind_simd:
#include <experimental/simd> namespace stdx = std::experimental; using floatv = stdx::native_simd<float>; using doublev = stdx::rebind_simd_t<double, floatv>; using intv = stdx::rebind_simd_t<int, floatv>;
This ensures that the set of types all have the same width and thus can be interconverted. A conversion with mismatching width is not defined because it would either drop values or have to invent values. For resizing operations, the SIMD library provides the split and concat functions.
<experimental/simd>
Contents
[edit] Main classes
[edit]
std::experimental::simd_abi
(constant) [edit]
(class template) [edit]
[edit]
(class) [edit]
(class) [edit]
(class template) [edit]
[edit] Where expression
(class template)
[edit] Casts
[edit] Algorithms
[edit] Reduction
[edit] Mask reduction
(function template) [edit]
[edit] Traits
(class template) [edit]
(class template) [edit]
[edit] Math functions
All functions in <cmath>, except for the special math functions, are overloaded for simd
.
[edit] Example
#include <experimental/simd> #include <iostream> #include <string_view> namespace stdx = std::experimental; void println(std::string_view name, auto const& a) { std::cout << name << ": "; for (std::size_t i{}; i != std::size (a); ++i) std::cout << a[i] << ' '; std::cout << '\n'; } template<class A> stdx::simd<int, A> my_abs(stdx::simd<int, A> x) { where(x < 0, x) = -x; return x; } int main() { const stdx::native_simd<int> a = 1; println("a", a); const stdx::native_simd<int> b([](int i) { return i - 2; }); println("b", b); const auto c = a + b; println("c", c); const auto d = my_abs(c); println("d", d); const auto e = d * d; println("e", e); const auto inner_product = stdx::reduce(e); std::cout << "inner product: " << inner_product << '\n'; const stdx::fixed_size_simd<long double, 16> x([](int i) { return i; }); println("x", x); println("cos2(x) + sin2(x)", stdx::pow(stdx::cos(x), 2) + stdx::pow(stdx::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 cos2(x) + sin2(x): 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
[edit] See also
[edit] External links
std::experimental::simd
is shipping with GCC-11) — gcc.gnu.org