batmat develop
Batched linear algebra routines
Loading...
Searching...
No Matches
simd.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <batmat/config.hpp>
4#include <batmat/unroll.h>
5
6#if BATMAT_WITH_GSI_HPC_SIMD
7
8#include <cstddef>
9#include <simd>
10
11namespace batmat::datapar {
12
13template <class Tp, class Abi>
14using simd = std::datapar::basic_simd<Tp, Abi>;
15template <class Tp, std::size_t Np>
16using deduced_simd = std::datapar::simd<Tp, Np>;
17template <class Tp, std::size_t Np>
19template <class Tp>
21
22template <class V>
23V unaligned_load(const typename V::value_type *p) {
24 std::span<typename V::value_type, V::size()> sp{const_cast<V::value_type *>(p), V::size()};
25 return std::datapar::unchecked_load<V>(sp);
26}
27
28template <class V>
29V aligned_load(const typename V::value_type *p) {
30 std::span<typename V::value_type, V::size()> sp{const_cast<V::value_type *>(p), V::size()};
31 return std::datapar::unchecked_load<V>(sp, std::datapar::flag_aligned);
32}
33
34template <class V>
35void unaligned_store(V v, typename V::value_type *p) {
36 std::datapar::unchecked_store(v, p, V::size());
37}
38
39template <class V>
40void aligned_store(V v, typename V::value_type *p) {
41 std::span<typename V::value_type, V::size()> sp{p, V::size()};
42 std::datapar::unchecked_store(v, sp, std::datapar::flag_aligned);
43}
44
45template <class V>
46void masked_aligned_store(V v, typename V::mask_type m, typename V::value_type *p) {
47 std::span<typename V::value_type, V::size()> sp{p, V::size()};
48 if constexpr (V::size() == 1) {
49 if (m[0])
50 std::datapar::unchecked_store(v, sp, std::datapar::flag_aligned);
51 } else {
52 std::datapar::unchecked_store(v, sp, m, std::datapar::flag_aligned);
53 }
54}
55
56#if defined(__x86_64__) || defined(_M_X64)
57template <class V>
58auto to_intrin(V v) {
59 return std::__detail::__to_x86_intrin(v);
60}
61#define BATMAT_HAVE_SIMD_TO_INTRIN 1
62#endif
63
64template <class Tp, class Abi>
65using simd_size = std::remove_cvref_t<decltype(simd<Tp, Abi>::size)>;
66template <class Tp, class Abi>
67using simd_align = std::datapar::alignment<simd<Tp, Abi>>;
68template <class T, class V>
69using rebind_simd_t = deduced_simd<T, V::size()>;
70
71template <class V>
72auto hmax(V v) { // TODO
73 using value_type = V::value_type;
74 value_type m = v[0];
75 BATMAT_FULLY_UNROLLED_FOR (int i = 1; i < v.size(); ++i)
76 m = std::max(v[i], m);
77 return m;
78}
79template <class V>
80auto hmin(V v) { // TODO
81 using value_type = V::value_type;
82 value_type m = v[0];
83 BATMAT_FULLY_UNROLLED_FOR (int i = 1; i < v.size(); ++i)
84 m = std::min(v[i], m);
85 return m;
86}
87
88using std::datapar::reduce_count;
89using std::datapar::select;
90
91} // namespace batmat::datapar
92
93#else
94
95#include <experimental/simd>
96#include <cstddef>
97
98namespace batmat::datapar {
99namespace stdx = std::experimental;
100
101template <class Tp, class Abi>
102using simd = stdx::simd<Tp, Abi>;
103template <class Tp, std::size_t Np>
104using deduced_abi = stdx::simd_abi::deduce_t<Tp, Np>;
105template <class Tp, std::size_t Np>
107
108template <class V>
109V unaligned_load(const typename V::value_type *p) {
110 return V{p, stdx::element_aligned};
111}
112
113template <class V>
114V aligned_load(const typename V::value_type *p) {
115 return V{p, stdx::vector_aligned};
116}
117
118template <class V>
119void unaligned_store(V v, typename V::value_type *p) {
120 v.copy_to(p, stdx::element_aligned);
121}
122
123template <class V>
124void aligned_store(V v, typename V::value_type *p) {
125 v.copy_to(p, stdx::vector_aligned);
126}
127
128template <class V>
129void masked_aligned_store(V v, typename V::mask_type m, typename V::value_type *p) {
130 where(m, v).copy_to(p, stdx::vector_aligned);
131}
132
133template <class V>
134auto to_intrin(V v) {
135 return static_cast<stdx::__intrinsic_type_t<V, v.size()>>(v);
136}
137#define BATMAT_HAVE_SIMD_TO_INTRIN 1
138
139template <class Tp, class Abi>
140using simd_size = stdx::simd_size<Tp, Abi>;
141template <class Tp, class Abi>
142using simd_align = stdx::memory_alignment<simd<Tp, Abi>>;
143template <class T, class V>
144using rebind_simd_t = stdx::rebind_simd_t<T, V>;
145template <class Tp>
147
148using stdx::hmax;
149using stdx::hmin;
150
151auto reduce_count(auto v) { return popcount(v); }
152auto select(auto cond, auto t, auto f) {
153 where(cond, f) = t;
154 return f;
155}
156
157} // namespace batmat::datapar
158
159#endif
160
161namespace batmat::datapar {
162
163template <class V>
164constexpr V from_values(auto... values) {
166 const typename V::value_type data[]{values...};
167 return aligned_load<V>(data);
168}
169
170} // namespace batmat::datapar
V unaligned_load(const typename V::value_type *p)
Definition simd.hpp:109
void aligned_store(V v, typename V::value_type *p)
Definition simd.hpp:124
stdx::memory_alignment< simd< Tp, Abi > > simd_align
Definition simd.hpp:142
stdx::simd_size< Tp, Abi > simd_size
Definition simd.hpp:140
auto to_intrin(V v)
Definition simd.hpp:134
deduced_abi< Tp, 1 > scalar_abi
Definition simd.hpp:146
auto reduce_count(auto v)
Definition simd.hpp:151
stdx::rebind_simd_t< T, V > rebind_simd_t
Definition simd.hpp:144
V aligned_load(const typename V::value_type *p)
Definition simd.hpp:114
stdx::simd_abi::deduce_t< Tp, Np > deduced_abi
Definition simd.hpp:104
void unaligned_store(V v, typename V::value_type *p)
Definition simd.hpp:119
simd< Tp, deduced_abi< Tp, Np > > deduced_simd
Definition simd.hpp:106
void masked_aligned_store(V v, typename V::mask_type m, typename V::value_type *p)
Definition simd.hpp:129
auto select(auto cond, auto t, auto f)
Definition simd.hpp:152
constexpr V from_values(auto... values)
Definition simd.hpp:164
stdx::simd< Tp, Abi > simd
Definition simd.hpp:102
#define BATMAT_FULLY_UNROLLED_FOR(...)
Definition unroll.h:27