1 | /* |
2 | * memory_conf.hpp |
3 | * |
4 | * Created on: Aug 28, 2014 |
5 | * Author: Pietro Incardona |
6 | */ |
7 | |
8 | #ifndef MEMORY_CONF_HPP_ |
9 | #define MEMORY_CONF_HPP_ |
10 | |
11 | #include "util/variadic_to_vmpl.hpp" |
12 | #include "t_to_memory_c.hpp" |
13 | #include "Vector/vect_isel.hpp" |
14 | #include "Vector/util.hpp" |
15 | |
16 | constexpr int SOA_layout_IA = 2; |
17 | constexpr int SOA_layout = 1; |
18 | constexpr int AOS_layout = 0; |
19 | |
20 | /*! \brief This class convert a boost::mpl::fusion/vector to a boost::mpl::fusion/vector with memory_c interleaved |
21 | * |
22 | * This class convert a boost::mpl::fusion/vector to a boost::mpl::fusion/vector with memory_c interleaved |
23 | * |
24 | * Example: |
25 | * |
26 | * typedef boost::mpl::vector<float,float,float[3][3], ... > A |
27 | * |
28 | * inter_memc<A> |
29 | * |
30 | * produce |
31 | * |
32 | * boost::fusion::vector<memory_c<float>,memory_c<float>, memory_c<multi_array<boost::mpl::vector<float,3,3>, ...... > |
33 | * |
34 | * \param Seq Is suppose to be an boost::mpl::vector/fusion |
35 | * |
36 | */ |
37 | template<typename Seq> |
38 | struct inter_memc |
39 | { |
40 | typedef typename v_transform<t_to_memory_c,Seq>::type type; |
41 | }; |
42 | |
43 | /*! \brief This class convert a boost::mpl::fusion/vector to a boost::mpl::fusion/vector with memory_c<.....,MEMORY_C_REDUCED> interleaved |
44 | * |
45 | * This class convert a boost::mpl::fusion/vector to a boost::mpl::fusion/vector with memory_c<.....,MEMORY_C_REDUCED> interleaved |
46 | * |
47 | * Example: |
48 | * |
49 | * typedef boost::mpl::vector<float,float,float[3][3], ... > A |
50 | * |
51 | * inter_memc<A> |
52 | * |
53 | * produce |
54 | * |
55 | * boost::fusion::vector<memory_c<float>,memory_c<float>, memory_c<multi_array<boost::mpl::vector<float,3,3>, ...... > |
56 | * |
57 | * \param Seq Is suppose to be an boost::mpl::vector/fusion |
58 | * |
59 | */ |
60 | template<typename Seq> |
61 | struct inter_memc_red |
62 | { |
63 | typedef typename v_transform<t_to_memory_c_red,Seq>::type type; |
64 | }; |
65 | |
66 | /*! \brief Transform the boost::fusion::vector into memory specification (memory_traits) |
67 | * |
68 | * Transform the boost::fusion::vector into memory_traits. |
69 | * In this implementation we interleave each property of the base type with memory_c |
70 | * |
71 | * We basically create a buffer for each property |
72 | * |
73 | * \see see inter_mem_c for detail |
74 | * |
75 | * \param T base type (T::type must define a boost::fusion::vector ) |
76 | * |
77 | * |
78 | */ |
79 | template<typename T> |
80 | struct memory_traits_inte |
81 | { |
82 | //! for each element in the vector interleave memory_c |
83 | typedef typename inter_memc<typename T::type>::type type; |
84 | |
85 | //! indicate that it change the memory layout from the original |
86 | typedef int yes_is_inte; |
87 | |
88 | typedef boost::mpl::int_<SOA_layout_IA> type_value; |
89 | |
90 | /*! \brief Return a reference to the selected element |
91 | * |
92 | * \param data object from where to take the element |
93 | * \param g1 grid information |
94 | * \param v1 element id |
95 | * |
96 | * \return a reference to the object selected |
97 | * |
98 | */ |
99 | template<unsigned int p, typename data_type, typename g1_type, typename key_type> |
100 | __host__ __device__ static inline auto get(data_type & data_, const g1_type & g1, const key_type & v1) -> decltype(boost::fusion::at_c<p>(data_).mem_r.operator[](g1.LinId(v1))) |
101 | { |
102 | return boost::fusion::at_c<p>(data_).mem_r.operator[](g1.LinId(v1)); |
103 | } |
104 | |
105 | /*! \brief Return a reference to the selected element |
106 | * |
107 | * \param data object from where to take the element |
108 | * \param g1 grid information |
109 | * \param v1 element id |
110 | * |
111 | * \return a reference to the object selected |
112 | * |
113 | */ |
114 | template<unsigned int p, typename data_type, typename g1_type> |
115 | __host__ __device__ static inline auto get_lin(data_type & data_, const g1_type & g1, size_t lin_id) -> decltype(boost::fusion::at_c<p>(data_).mem_r.operator[](lin_id)) |
116 | { |
117 | return boost::fusion::at_c<p>(data_).mem_r.operator[](lin_id); |
118 | } |
119 | |
120 | /*! \brief Return a reference to the selected element |
121 | * |
122 | * \param data object from where to take the element |
123 | * \param g1 grid information |
124 | * \param v1 element id |
125 | * |
126 | * \return a const reference to the object selected |
127 | * |
128 | */ |
129 | template<unsigned int p, typename data_type, typename g1_type, typename key_type> |
130 | __host__ __device__ static inline auto get_c(const data_type & data_, const g1_type & g1, const key_type & v1) -> decltype(boost::fusion::at_c<p>(data_).mem_r.operator[](g1.LinId(v1))) |
131 | { |
132 | return boost::fusion::at_c<p>(data_).mem_r.operator[](g1.LinId(v1)); |
133 | } |
134 | |
135 | /*! \brief Return a reference to the selected element |
136 | * |
137 | * \param data object from where to take the element |
138 | * \param g1 grid information |
139 | * \param v1 element id |
140 | * |
141 | * \return a const reference to the object selected |
142 | * |
143 | */ |
144 | template<unsigned int p, typename data_type, typename g1_type> |
145 | __host__ __device__ static inline auto get_lin_c(const data_type & data_, const g1_type & g1, size_t lin_id) -> decltype(boost::fusion::at_c<p>(data_).mem_r.operator[](lin_id)) |
146 | { |
147 | return boost::fusion::at_c<p>(data_).mem_r.operator[](lin_id); |
148 | } |
149 | }; |
150 | |
151 | /*! \brief Transform the boost::fusion::vector into memory specification (memory_traits) |
152 | * |
153 | * Transform the boost::fusion::vector into memory_traits. |
154 | * In this implementation we interleave each property of the base type with memory_c |
155 | * |
156 | * We basically create a buffer for each property |
157 | * |
158 | * \see see inter_mem_c for detail |
159 | * |
160 | * \param T base type (T::type must define a boost::fusion::vector ) |
161 | * |
162 | * |
163 | */ |
164 | /*template<typename T> |
165 | struct memory_traits_inte_red |
166 | { |
167 | //! for each element in the vector interleave memory_c |
168 | typedef typename inter_memc_red<typename T::type>::type type; |
169 | |
170 | //! indicate that it change the memory layout from the original |
171 | typedef int yes_is_inte; |
172 | };*/ |
173 | |
174 | /*! \brief small meta-function to get the type of the memory |
175 | * |
176 | * |
177 | */ |
178 | template<typename T, bool is_agg> |
179 | struct memory_traits_lin_type |
180 | { |
181 | typedef memory_c<typename T::type> type; |
182 | }; |
183 | |
184 | /*! \brief small meta-function to get the type of the memory |
185 | * |
186 | * |
187 | */ |
188 | template<typename T> |
189 | struct memory_traits_lin_type<T,false> |
190 | { |
191 | typedef void type; |
192 | }; |
193 | |
194 | /*! \brief Transform the boost::fusion::vector into memory specification (memory_traits) |
195 | * |
196 | * Transform the boost::fusion::vector into memory specification (memory_traits). |
197 | * In this implementation we create a buffer of base type with memory_c |
198 | * |
199 | * We basically create a buffer for each property |
200 | * |
201 | * \param T base type (T::type must define a boost::fusion::vector ) |
202 | * |
203 | * |
204 | */ |
205 | |
206 | template<typename T> |
207 | struct memory_traits_lin |
208 | { |
209 | //! for each element in the vector interleave memory_c |
210 | typedef typename memory_traits_lin_type<T,openfpm::vect_isel<T>::value == OPENFPM_NATIVE>::type type; |
211 | |
212 | typedef int yes_is_tlin; |
213 | |
214 | typedef boost::mpl::int_<AOS_layout> type_value; |
215 | |
216 | /*! \brief Return a reference to the selected element |
217 | * |
218 | * \param data object from where to take the element |
219 | * \param g1 grid information |
220 | * \param v1 element id |
221 | * |
222 | * \return a reference to the object selected |
223 | * |
224 | */ |
225 | template<unsigned int p, typename data_type, typename g1_type, typename key_type> |
226 | __host__ __device__ static inline auto get(data_type & data_, const g1_type & g1, const key_type & v1) -> decltype(boost::fusion::at_c<p>(data_.mem_r.operator[](g1.LinId(v1)))) & |
227 | { |
228 | return boost::fusion::at_c<p>(data_.mem_r.operator[](g1.LinId(v1))); |
229 | } |
230 | |
231 | /*! \brief Return a reference to the selected element |
232 | * |
233 | * \param data object from where to take the element |
234 | * \param g1 grid information |
235 | * \param v1 element id |
236 | * |
237 | * \return a reference to the object selected |
238 | * |
239 | */ |
240 | template<unsigned int p, typename data_type, typename g1_type> |
241 | __host__ __device__ static inline auto get_lin(data_type & data_, const g1_type & g1, const size_t lin_id) -> decltype(boost::fusion::at_c<p>(data_.mem_r.operator[](lin_id))) & |
242 | { |
243 | return boost::fusion::at_c<p>(data_.mem_r.operator[](lin_id)); |
244 | } |
245 | |
246 | /*! \brief Return a reference to the selected element |
247 | * |
248 | * \param data object from where to take the element |
249 | * \param g1 grid information |
250 | * \param v1 element id |
251 | * |
252 | * \return a reference to the object selected |
253 | * |
254 | */ |
255 | template<unsigned int p, typename data_type, typename g1_type, typename key_type> |
256 | __host__ __device__ static inline auto get_c(const data_type & data_, const g1_type & g1, const key_type & v1) -> decltype(boost::fusion::at_c<p>(data_.mem_r.operator[](g1.LinId(v1)))) & |
257 | { |
258 | return boost::fusion::at_c<p>(data_.mem_r.operator[](g1.LinId(v1))); |
259 | } |
260 | |
261 | /*! \brief Return a reference to the selected element |
262 | * |
263 | * \param data object from where to take the element |
264 | * \param g1 grid information |
265 | * \param v1 element id |
266 | * |
267 | * \return a reference to the object selected |
268 | * |
269 | */ |
270 | template<unsigned int p, typename data_type, typename g1_type> |
271 | __host__ __device__ static inline auto get_lin_c(const data_type & data_, const g1_type & g1, const size_t lin_id) -> decltype(boost::fusion::at_c<p>(data_.mem_r.operator[](lin_id))) & |
272 | { |
273 | return boost::fusion::at_c<p>(data_.mem_r.operator[](lin_id)); |
274 | } |
275 | }; |
276 | |
277 | |
278 | ////////////////////////////////////////////////////////////// |
279 | |
280 | template<typename T, typename Sfinae = void> |
281 | struct is_layout_mlin: std::false_type {}; |
282 | |
283 | |
284 | /*! \brief is_layout_mlin |
285 | * |
286 | * ### Example |
287 | * |
288 | * \snippet util.hpp Check if the memory layout is memory_traits_lin |
289 | * |
290 | * return true if T is a memory_traits_lin |
291 | * |
292 | */ |
293 | template<typename T> |
294 | struct is_layout_mlin<T, typename Void< typename T::yes_is_tlin>::type> : std::true_type |
295 | {}; |
296 | |
297 | |
298 | template<typename T, typename Sfinae = void> |
299 | struct is_layout_inte: std::false_type {}; |
300 | |
301 | |
302 | /*! \brief is_layout_inte |
303 | * |
304 | * ### Example |
305 | * |
306 | * \snippet util.hpp Check if the memory layout is memory_traits_inte |
307 | * |
308 | * return true if T is a memory_traits_inte |
309 | * |
310 | */ |
311 | template<typename T> |
312 | struct is_layout_inte<T, typename Void< typename T::yes_is_inte>::type> : std::true_type |
313 | {}; |
314 | |
315 | /*! \brief is_multiple_buffer_each_prp |
316 | * |
317 | * return if each property is splitted on a separate buffer. This class make sense to be used if T is |
318 | * a vector in case it is not it always return 0 |
319 | * |
320 | * ### Example |
321 | * |
322 | * \snippet util_test.hpp Check if the vector has multiple buffers for each vector |
323 | * |
324 | * |
325 | */ |
326 | template<typename T, unsigned int impl = is_vector<T>::value > |
327 | struct is_multiple_buffer_each_prp: std::false_type |
328 | {}; |
329 | |
330 | template<typename T> |
331 | struct is_multiple_buffer_each_prp<T,true>: is_layout_inte<typename T::layout_base_> |
332 | {}; |
333 | |
334 | #endif |
335 | |