|
| 1 | +<cxx-clause id="parallel.simd"> |
| 2 | + <h1><ins>Data-Parallel Types</ins></h1> |
| 3 | + |
| 4 | + <cxx-section id="parallel.simd.general"> |
| 5 | + <h1><ins>General</ins></h1> |
| 6 | + |
| 7 | + <p> |
| 8 | + <ins> |
| 9 | + The data-parallel library consists of data-parallel types and operations on these types. A data-parallel type consists of elements of an underlying arithmetic type, called the <em>element type</em>. The number of elements is a constant for each data-parallel type and called the <em>width</em> of that type. |
| 10 | + </ins> |
| 11 | + </p> |
| 12 | + |
| 13 | + <p> |
| 14 | + <ins> |
| 15 | + Throughout this Clause, the term <em>data-parallel type</em> refers to all <em>supported</em> <cxx-ref to="parallel.simd.overview"></cxx-ref> specializations of the <code>simd</code> and <code>simd_mask</code> class templates. A <em>data-parallel object</em> is an object of <em>data-parallel type</em>. |
| 16 | + </ins> |
| 17 | + <p> |
| 18 | + |
| 19 | + <p> |
| 20 | + <ins> |
| 21 | + An <em>element-wise operation</em> applies a specified operation to the elements of one or more data-parallel objects. Each such application is unsequenced with respect to the others. A <em>unary element-wise operation</em> is an element-wise operation that applies a unary operation to each element of a data-parallel object. A <em>binary element-wise operation</em> is an element-wise operation that applies a binary operation to corresponding elements of two data-parallel objects. |
| 22 | + </ins> |
| 23 | + </p> |
| 24 | + |
| 25 | + <p> |
| 26 | + <ins> |
| 27 | + Throughout this Clause, the set of <em>vectorizable types</em> for a data-parallel type comprises all cv-unqualified arithmetic types other than <code>bool</code>. |
| 28 | + </ins> |
| 29 | + </p> |
| 30 | + |
| 31 | + <p> |
| 32 | + <ins> |
| 33 | + <cxx-note>The intent is to support acceleration through data-parallel execution resources, such as SIMD registers and instructions or execution units driven by a common instruction decoder. If such execution resources are unavailable, the interfaces support a transparent fallback to sequential execution.</cxx-note> |
| 34 | + </ins> |
| 35 | + </p> |
| 36 | + |
| 37 | + </cxx-section> |
| 38 | + |
| 39 | + <cxx-section id="parallel.simd.synopsis"> |
| 40 | + <h1><ins>Header <code><experimental/simd></code> synopsis</ins></h1> |
| 41 | + |
| 42 | + <ins> |
| 43 | + <pre> |
| 44 | + |
| 45 | +namespace std::experimental { |
| 46 | +inline namespace parallelism_v2 { |
| 47 | +namespace simd_abi { |
| 48 | + |
| 49 | + struct scalar {}; |
| 50 | + template<int N> struct fixed_size {}; |
| 51 | + template<class T> inline constexpr int max_fixed_size = <em>implementation-defined</em>; |
| 52 | + template<class T> using compatible = <em>implementation-defined</em>; |
| 53 | + template<class T> using native = <em>implementation-defined</em>; |
| 54 | + |
| 55 | + template<class T, size_t N> struct deduce { using type = <em>see-below</em>; }; |
| 56 | + template<class T, size_t N> using deduce_t = typename deduce<T, N>::type; |
| 57 | + |
| 58 | + struct element_aligned_tag {}; |
| 59 | + struct vector_aligned_tag {}; |
| 60 | + template<size_t> struct overaligned_tag {}; |
| 61 | + inline constexpr element_aligned_tag element_aligned{}; |
| 62 | + inline constexpr vector_aligned_tag vector_aligned{}; |
| 63 | + template<size_t N> inline constexpr overaligned_tag<N> overaligned{}; |
| 64 | + |
| 65 | + <cxx-ref insynopsis="" to="parallel.simd.traits"></cxx-ref> traits |
| 66 | + template<class T> struct is_abi_tag; |
| 67 | + template<class T> inline constexpr bool is_abi_tag_v = is_abi_tag<T>::value; |
| 68 | + |
| 69 | + template<class T> struct is_simd; |
| 70 | + template<class T> inline constexpr bool is_simd_v = is_simd<T>::value; |
| 71 | + |
| 72 | + template<class T> struct is_simd_mask; |
| 73 | + template<class T> inline constexpr bool is_simd_mask_v = is_simd_mask<T>::value; |
| 74 | + |
| 75 | + template<class T> struct is_simd_flag_type; |
| 76 | + template<class T> inline constexpr bool is_simd_flag_type_v = is_simd_flag_type<T>::value; |
| 77 | + |
| 78 | + template<class T, class Abi = simd_abi::compatible<T>> struct simd_size; |
| 79 | + template<class T, class Abi = simd_abi::compatible<T>> |
| 80 | + inline constexpr size_t simd_size_v = simd_size<T,Abi>::value; |
| 81 | + |
| 82 | + template<class T, class U = typename T::value_type> struct memory_alignment; |
| 83 | + template<class T, class U = typename T::value_type> |
| 84 | + inline constexpr size_t memory_alignment_v = memory_alignment<T,U>::value; |
| 85 | + |
| 86 | + <cxx-ref insynopsis="" to="parallel.simd.class"></cxx-ref> class template simd |
| 87 | + template<class T, class Abi = simd_abi::compatible<T>> class simd; |
| 88 | + template<class T> using native_simd<T, simd_abi::native<T>>; |
| 89 | + template<class T, int N> using fixed_size_simd = simd<T, simd_abi::fixed_size<N>>; |
| 90 | + |
| 91 | + <cxx-ref insynopsis="" to="parallel.simd.mask.class"></cxx-ref> class template simd_mask |
| 92 | + template<class T, class Abi = simd_abi::compatible<T>> class simd_mask; |
| 93 | + template<class T> using native_simd_mask<T, simd_abi::native<T>>; |
| 94 | + template<class T, int N> using fixed_size_simd_mask = simd_mask<T, simd_abi::fixed_size<N>>; |
| 95 | + |
| 96 | + <cxx-ref insynopsis="" to="parallel.simd.casts"></cxx-ref> casts |
| 97 | + template<class T, class U, class Abi> <em>see-below</em> simd_cast(const simd<U, Abi>&); |
| 98 | + template<class T, class U, class Abi> <em>see-below</em> static_simd_cast(const simd<U, Abi>&); |
| 99 | + |
| 100 | + template<class T, class Abi> |
| 101 | + fixed_size_simd<T, simd_size_v<T, Abi>> to_fixed_size(const simd<T, Abi>&) noexcept; |
| 102 | + template<class T, class Abi> |
| 103 | + fixed_size_simd_mask<T, simd_size_v<T, Abi>> to_fixed_size(const simd_mask<T, Abi>&) noexcept; |
| 104 | + template<class T, int N> native_simd<T> to_native(const fixed_size_simd<T, N>&) noexcept; |
| 105 | + template<class T, int N> native_simd_mask<T> to_native(const fixed_size_simd_mask<T, N>&) noexcept; |
| 106 | + template<class T, int N> simd<T> to_compatible(const fixed_size_simd<T, N>&) noexcept; |
| 107 | + template<class T, int N> simd_mask<T> to_compatible(const fixed_size_simd_mask<T, N>&) noexcept; |
| 108 | + |
| 109 | + template<size_t... Sizes, class T, class Abi> |
| 110 | + tuple<simd<T, simd_abi::deduce_t<T, Sizes>>...> split(const simd<T, Abi>&); |
| 111 | + template<size_t... Sizes, class T, class Abi> |
| 112 | + tuple<simd_mask<T, simd_mask_abi::deduce_t<T, Sizes>>...> split(const simd_mask<T, Abi>&); |
| 113 | + template<class V, class Abi> |
| 114 | + array<V, simd_size_v<typename V::value_type, Abi> / V::size()> split(const simd<typename V::value_type, Abi>&); |
| 115 | + template<class V, class Abi> |
| 116 | + array<V, simd_size_v<typename V::value_type, Abi> / V::size()> split(const simd_mask<typename V::value_type, Abi>&); |
| 117 | + |
| 118 | + template<class T, class... Abis> |
| 119 | + simd<T, simd_abi::deduce_t>T, (simd_size_v<T, Abis> + ...)>> concat(const simd<T, Abis>&...); |
| 120 | + template<class T, class... Abis> |
| 121 | + simd_mask<T, simd_abi::deduce_t>T, (simd_size_v<T, Abis> + ...)>> concat(const simd_mask<T, Abis>&...); |
| 122 | + |
| 123 | + <cxx-ref insynopsys="" to="parallel.simd.mask.reductions"></cxx-ref> reductions |
| 124 | + template<class T, class Abi> bool all_of(const simd_mask<T, Abi>&) noexcept; |
| 125 | + template<class T, class Abi> bool any_of(const simd_mask<T, Abi>&) noexcept; |
| 126 | + template<class T, class Abi> bool none_of(const simd_mask<T, Abi>&) noexcept; |
| 127 | + template<class T, class Abi> bool some_of(const simd_mask<T, Abi>&) noexcept; |
| 128 | + template<class T, class Abi> int popcount(const simd_mask<T, Abi>&) noexcept; |
| 129 | + template<class T, class Abi> int find_first_set(const simd_mask<T, Abi>&); |
| 130 | + template<class T, class Abi> int find_last_set(const simd_mask<T, Abi>&); |
| 131 | + |
| 132 | + bool all_of(<em>see-below</em>) noexcept; |
| 133 | + bool any_of(<em>see-below</em>) noexcept; |
| 134 | + bool none_of(<em>see-below</em>) noexcept; |
| 135 | + bool some_of(<em>see-below</em>) noexcept; |
| 136 | + int popcount(<em>see-below</em>) noexcept; |
| 137 | + int find_first_set(<em>see-below</em>) noexcept; |
| 138 | + int find_last_set(<em>see-below</em>) noexcept; |
| 139 | + |
| 140 | + <cxx-ref insynopsis="" to="parallel.simd.whereexpr"></cxx-ref> where expressions |
| 141 | + template<class M, class T> class const_where_expression; |
| 142 | + template<class M, class T> class where_expression; |
| 143 | + |
| 144 | + <cxx-ref insynopsis="" to="parallel.simd.mask.where"></cxx-ref> masked assignment |
| 145 | + template<class T> struct nodeduce { using type = T; }; // exposition only |
| 146 | + template<class T> using nodeduce_t = typename nodeduce<T>::type; // exposition only |
| 147 | + |
| 148 | + template<class T, class Abi> |
| 149 | + where_expression<simd_mask<T, Abi>, simd<T, Abi>> where(const typename simd<T, Abi>::mask_type&, simd<T, Abi>&) noexcept; |
| 150 | + |
| 151 | + template<class T, class Abi> |
| 152 | + const_where_expression<simd_mask<T, Abi>, simd<T, Abi>> where(const typename simd<T, Abi>::mask_type&, const simd<T, Abi>&) noexcept; |
| 153 | + |
| 154 | + template<class T, class Abi> |
| 155 | + where_expression<simd_mask<T, Abi>, simd_mask<T, Abi>> where(const nodeduce_t<simd_mask<T, Abit>>&, simd_mask<T, Abi>&) noexcept; |
| 156 | + |
| 157 | + template<class T, class Abi> |
| 158 | + const_where_expression<simd_mask<T, Abi>, simd_mask<T, Abi>> where(const nodeduce_t<simd_mask<T, Abit>>&, const simd_mask<T, Abi>&) noexcept; |
| 159 | + |
| 160 | + template<class T> |
| 161 | + const_where_expression<bool, T> where(<em>see-below</em> k, const T& d) noexcept; |
| 162 | + |
| 163 | + <cxx-ref insynopsis="" to="parallel.simd.reductions"></cxx-ref> reductions |
| 164 | + template<class T, class Abi, class BinaryOperation = plus<>> |
| 165 | + T reduce(const simd<T, Abi>&, BinaryOperation = {}); |
| 166 | + |
| 167 | + template<class M, class V, class BinaryOperation> |
| 168 | + typename V::value_type reduce(const const_where_expression<M, V>& x, |
| 169 | + typename V::value_type identity_element, BinaryOperation binary_op); |
| 170 | + template<class M, class V> |
| 171 | + typename V::value_type reduce(const const_where_expression<M, V> x, plus<> binary_op = {}); |
| 172 | + template<class M, class V> |
| 173 | + typename V::value_type reduce(const const_where_expression<M, V> x, multiplies<> binary_op = {}); |
| 174 | + template<class M, class V> |
| 175 | + typename V::value_type reduce(const const_where_expression<M, V> x, bit_and<> binary_op = {}); |
| 176 | + template<class M, class V> |
| 177 | + typename V::value_type reduce(const const_where_expression<M, V> x, bit_or<> binary_op = {}); |
| 178 | + template<class M, class V> |
| 179 | + typename V::value_type reduce(const const_where_expression<M, V> x, bit_xor<> binary_op = {}); |
| 180 | + |
| 181 | + template<class T, class Abi> T hmin(const simd<T, abi>&); |
| 182 | + template<class T, class Abi> typename V::value_type hmin(const const_where_expression<M, V>&); |
| 183 | + template<class T, class Abi> T hmax(const simd<T, abi>&); |
| 184 | + template<class T, class Abi> typename V::value_type hmax(const const_where_expression<M, V>&); |
| 185 | + |
| 186 | + <cxx-ref insynopsis="" to="parallel.simd.alg"></cxx-ref> algorithms |
| 187 | + template<class T, class Abi> simd<T, Abi> min(const simd<T, Abi>& a, const simd<T, Abi>& b) noexcept; |
| 188 | + template<class T, class Abi> simd<T, Abi> max(const simd<T, Abi>& a, const simd<T, Abi>& b) noexcept; |
| 189 | + template<class T, class Abi> simd<T, Abi> minmax(const simd<T, Abi>& a, const simd<T, Abi>& b) noexcept; |
| 190 | + template<class T, class Abi> simd<T, Abi> clamp(const simd<T, Abi>& v, const simd<T, Abi>& lo, const simd<T, Abi>& hi) noexcept; |
| 191 | +} |
| 192 | +} |
| 193 | +} |
| 194 | + </pre> |
| 195 | + </ins> |
| 196 | + |
| 197 | + <p> |
| 198 | + <ins> |
| 199 | + The header <code><experimental/simd></code> defines class templates, tag types, trait types, and function templates for element-wise operations on data-parallel objects. |
| 200 | + </ins> |
| 201 | + </p> |
| 202 | + </cxx-section> |
| 203 | + |
| 204 | + <cxx-section id="parallel.simd.overview"> |
| 205 | + </cxx-section> |
| 206 | +</cxx-clause> |
| 207 | + |
0 commit comments