alpaka
Abstraction Library for Parallel Kernel Acceleration
Loading...
Searching...
No Matches
SimdPtr.hpp
Go to the documentation of this file.
1/* Copyright 2025 René Widera
2 * SPDX-License-Identifier: MPL-2.0
3 */
4
5#pragma once
6
7#include "alpaka/Simd.hpp"
8#include "alpaka/Vec.hpp"
13#include "alpaka/trait.hpp"
14
15#include <concepts>
16#include <cstdint>
17#include <type_traits>
18
19namespace alpaka
20{
21 namespace trait
22 {
23 template<typename T>
24 struct IsSimdPtr : std::false_type
25 {
26 };
27 } // namespace trait
28
29 template<typename T>
31
32 namespace concepts
33 {
34 /** Concept to check if a type is a SIMD pointer
35 *
36 * @tparam T Type to check
37 * @tparam T_ValueType enforce a value type of the SIMD pointer, if not provided the value type is not checked
38 * @tparam T_width enforce lane width of the SIMD pointer, if not provided the value is not checked
39 */
40 template<typename T, typename T_ValueType = alpaka::NotRequired, uint32_t T_width = alpaka::notRequiredWidth>
42 && (std::same_as<T_ValueType, trait::GetValueType_t<std::decay_t<T>>>
43 || std::same_as<T_ValueType, alpaka::NotRequired>)
44 && ((T_width == alpaka::notRequiredWidth) || (T::width() == T_width));
45 } // namespace concepts
46
47 /** pointer to a SIMD pack with the width T_SimdWidth
48 *
49 * The pointer is used to load/store data from/to memory
50 *
51 * @tparam T_MdSpan type of the memory the pointer is pointing to
52 * @tparam T_IdxType type of the index
53 * @tparam T_MemAlignment alignment of the memory the pointer is pointing to
54 * @tparam T_SimdWidth width of the SIMD pack
55 */
56 template<
57 typename T_MdSpan,
59 alpaka::concepts::Alignment T_MemAlignment,
60 alpaka::concepts::CVector T_SimdWidth>
61 struct SimdPtr : private T_MdSpan
62 {
63 using value_type = typename T_MdSpan::value_type;
64 using IdxType = typename T_IdxType::UniVec;
65
66 static consteval uint32_t width()
67 {
68 return T_SimdWidth{}.back();
69 }
70
71 constexpr SimdPtr(T_MdSpan const& mdSpan, T_IdxType const& idx, T_MemAlignment, T_SimdWidth)
72 : T_MdSpan(mdSpan)
73 , m_idx(idx)
74 {
75 }
76
77 /** Shift the element the pointer is pointing to by idx
78 *
79 * @param idx number of elements to shift the pointer by
80 * @return a new simd pointer pointing to the shifted element
81 *
82 * @{
83 */
84 constexpr alpaka::concepts::SimdPtr auto operator[](auto const& idx) const
85 {
86 /* Do not use concepts::IndexVec as concept in the function signature else nvcc (tested 12.X -> 13.0)
87 * segfaults during compile.
88 */
89 static_assert(
90 alpaka::concepts::IndexVec<ALPAKA_TYPEOF(idx), typename IdxType::type, T_MdSpan::dim()>,
91 "The dimension of idx must match the encapsulated MdSpan dimension and the index type of idx must be "
92 "lossless castable to the MdSpan index type");
93 constexpr uint32_t valueAlignment = static_cast<uint32_t>(alignof(value_type));
94 constexpr auto align = Alignment<valueAlignment>{};
95 return SimdPtr<T_MdSpan, IdxType, ALPAKA_TYPEOF(align), T_SimdWidth>{
96 static_cast<T_MdSpan>(*this),
97 idx + m_idx,
98 align,
99 T_SimdWidth{}};
100 }
101
102 constexpr alpaka::concepts::SimdPtr auto operator[](auto const& idx)
103 {
104 /* Do not use concepts::IndexVec as concept in the function signature else nvcc (tested 12.X -> 13.0)
105 * segfaults during compile.
106 */
107 static_assert(
108 alpaka::concepts::IndexVec<ALPAKA_TYPEOF(idx), typename IdxType::type, T_MdSpan::dim()>,
109 "The dimension of idx must match the encapsulated MdSpan dimension and the index type of idx must be "
110 "lossless castable to the MdSpan index type");
111 constexpr uint32_t valueAlignment = static_cast<uint32_t>(alignof(value_type));
112 constexpr auto align = Alignment<valueAlignment>{};
113 return SimdPtr<T_MdSpan, IdxType, ALPAKA_TYPEOF(align), T_SimdWidth>{
114 static_cast<T_MdSpan>(*this),
115 idx + m_idx,
116 align,
117 T_SimdWidth{}};
118 }
119
120 /** @} */
121
122 constexpr decltype(auto) load() const
123 {
124 return internal::loadAsSimd<width()>(static_cast<T_MdSpan const&>(*this), getAlignment(), m_idx);
125 }
126
127 constexpr decltype(auto) load()
128 {
129 return internal::loadAsSimd<width()>(static_cast<T_MdSpan&>(*this), getAlignment(), m_idx);
130 }
131
132 /** get the alignment of the memory the pointer is pointing to
133 *
134 * @attention If the pointer is shifted by `operator[]` the alignment is equal to the data alignment of an
135 * single element
136 *
137 * @return the alignment of the memory (in byte) the pointer is pointing to
138 */
139 static constexpr auto getAlignment()
140 {
141 using SpanElemType = typename T_MdSpan::value_type;
142 constexpr uint32_t spanAlignment = T_MdSpan::getAlignment().template get<SpanElemType>();
143 using MemoryAlignment = std::conditional_t<
144 std::is_same_v<AutoAligned, T_MemAlignment>,
147 return MemoryAlignment{};
148 }
149
150 /** store the simd pack to the memory the pointer is pointing to
151 *
152 * @param rhs simd pack to store
153 *
154 * @{
155 */
156 template<typename T_Storage>
157 constexpr void storeTo(Simd<value_type, SimdPtr::width(), T_Storage> const& rhs) const
158 {
159 auto* ptr = &T_MdSpan::operator[](m_idx);
160
161 rhs.copyTo(ptr, getAlignment());
162 }
163
164 template<typename T_Storage>
165 constexpr void storeTo(Simd<value_type, SimdPtr::width(), T_Storage> const& rhs)
166 {
167 auto* ptr = &T_MdSpan::operator[](m_idx);
168 rhs.copyTo(ptr, getAlignment());
169 }
170
171 template<typename T_Storage>
172 constexpr SimdPtr const& operator=(Simd<value_type, SimdPtr::width(), T_Storage> const& rhs) const
173 {
174 storeTo(rhs);
175 return *this;
176 }
177
178 template<typename T_Storage>
179 constexpr SimdPtr& operator=(Simd<value_type, SimdPtr::width(), T_Storage> const& rhs)
180 {
181 storeTo(rhs);
182 return *this;
183 }
184
185 /** @} */
186
187 /** offset in elements relative to the MdSpan given at construction
188 *
189 * The index points to the first element followed by T_SimdWidth elements.
190 *
191 * @return the index of the first element relative to the MdSpan given at construction
192 */
193 constexpr IdxType getIdx() const
194 {
195 return m_idx;
196 }
197
198 private:
200 };
201
202 namespace internal
203 {
204 template<
206 alpaka::concepts::Alignment T_MdSpanAlignment,
208 struct LoadAsSimd::Op<T_MdSpan, T_MdSpanAlignment, T_Idx>
209 {
210 template<uint32_t T_simdWidth>
211 constexpr auto load(auto&& dataSource, T_MdSpanAlignment alignment, T_Idx const& idx) const
212 {
213 static_assert(
214 std::is_same_v<T_MdSpan, ALPAKA_TYPEOF(dataSource)>,
215 "Data source type must match the class template signature.");
216 auto&& d = dataSource[idx];
217 using DataTypeType = std::remove_reference_t<decltype(d)>;
218 using DstType = std::conditional_t<
219 std::is_const_v<DataTypeType>,
220 Simd<std::decay_t<DataTypeType>, T_simdWidth> const,
221 Simd<std::decay_t<DataTypeType>, T_simdWidth>>;
222
223 alpaka::concepts::Simd auto dest = DstType{};
224 dest.copyFrom(&d, alignment);
225 return dest;
226 }
227 };
228 } // namespace internal
229
230 namespace trait
231 {
232 template<typename T>
234 struct IsSimdPtr<T> : std::true_type
235 {
236 };
237 } // namespace trait
238} // namespace alpaka
#define ALPAKA_TYPEOF(...)
Get the type of instance.
Definition common.hpp:154
Concept to check for an alignment object.
Definition Alignment.hpp:89
Concept to check if a type is a CVector.
Definition Vec.hpp:75
Interface concept for objects describing multidimensional memory access.
Definition IMdSpan.hpp:91
Check whether the specified type is a multidimensional index.
Definition IndexVec.hpp:22
Concept to check if a type is a SIMD pointer.
Definition SimdPtr.hpp:41
Concept to check if a type is a vector.
Definition Vec.hpp:54
alpaka internal implementations.
Definition generic.hpp:19
constexpr auto loadAsSimd(auto &&anyDataSource, auto dataAlignment, auto const &index)
Get data as SIMD vector.
main alpaka namespace.
Definition alpaka.hpp:76
constexpr bool isSimdPtr_v
Definition SimdPtr.hpp:30
constexpr uint32_t notRequiredWidth
Definition trait.hpp:24
constexpr bool isSpecializationOf_v
checks if T is a instance of U
Definition utility.hpp:103
constexpr decltype(auto) get(concepts::SpecializationOf< Dict > auto &t) noexcept
Definition Dict.hpp:156
STL namespace.
Strongly typed and constexpr representation of a byte-alignment of memory.
Definition Alignment.hpp:26
constexpr SimdPtr & operator=(Simd< value_type, SimdPtr::width(), T_Storage > const &rhs)
store the simd pack to the memory the pointer is pointing to
Definition SimdPtr.hpp:179
static consteval uint32_t width()
Definition SimdPtr.hpp:66
static constexpr auto getAlignment()
get the alignment of the memory the pointer is pointing to
Definition SimdPtr.hpp:139
constexpr void storeTo(Simd< value_type, SimdPtr::width(), T_Storage > const &rhs)
store the simd pack to the memory the pointer is pointing to
Definition SimdPtr.hpp:165
constexpr void storeTo(Simd< value_type, SimdPtr::width(), T_Storage > const &rhs) const
store the simd pack to the memory the pointer is pointing to
Definition SimdPtr.hpp:157
constexpr IdxType getIdx() const
offset in elements relative to the MdSpan given at construction
Definition SimdPtr.hpp:193
typename T_MdSpan::value_type value_type
Definition SimdPtr.hpp:63
constexpr SimdPtr(T_MdSpan const &mdSpan, T_IdxType const &idx, T_MemAlignment, T_SimdWidth)
Definition SimdPtr.hpp:71
constexpr alpaka::concepts::SimdPtr auto operator[](auto const &idx)
Shift the element the pointer is pointing to by idx.
Definition SimdPtr.hpp:102
typename T_IdxType::UniVec IdxType
Definition SimdPtr.hpp:64
constexpr decltype(auto) load()
Definition SimdPtr.hpp:127
constexpr decltype(auto) load() const
Definition SimdPtr.hpp:122
constexpr SimdPtr const & operator=(Simd< value_type, SimdPtr::width(), T_Storage > const &rhs) const
store the simd pack to the memory the pointer is pointing to
Definition SimdPtr.hpp:172
constexpr alpaka::concepts::SimdPtr auto operator[](auto const &idx) const
Shift the element the pointer is pointing to by idx.
Definition SimdPtr.hpp:84
Simd vector.
Definition Simd.hpp:78
constexpr auto load(auto &&dataSource, T_MdSpanAlignment alignment, T_Idx const &idx) const
Definition SimdPtr.hpp:211