Cabana 0.8.0-dev
 
Loading...
Searching...
No Matches
Cabana_AoSoA.hpp
Go to the documentation of this file.
1/****************************************************************************
2 * Copyright (c) 2018-2023 by the Cabana authors *
3 * All rights reserved. *
4 * *
5 * This file is part of the Cabana library. Cabana is distributed under a *
6 * BSD 3-clause license. For the licensing terms see the LICENSE file in *
7 * the top-level directory. *
8 * *
9 * SPDX-License-Identifier: BSD-3-Clause *
10 ****************************************************************************/
11
16#ifndef CABANA_AOSOA_HPP
17#define CABANA_AOSOA_HPP
18
20#include <Cabana_Slice.hpp>
21#include <Cabana_SoA.hpp>
22#include <Cabana_Tuple.hpp>
23#include <Cabana_Types.hpp>
24#include <Cabana_Utils.hpp>
25#include <impl/Cabana_Index.hpp>
27
28#include <Kokkos_Core.hpp>
29
30#include <cmath>
31#include <cstdlib>
32#include <string>
33#include <type_traits>
34
35namespace Cabana
36{
37//---------------------------------------------------------------------------//
38// AoSoA forward declaration.
39template <class DataTypes, class MemorySpace, int VectorLength,
40 class MemoryTraits>
41class AoSoA;
42
43//---------------------------------------------------------------------------//
45template <class>
46struct is_aosoa_impl : public std::false_type
47{
48};
49
50template <class DataTypes, class MemorySpace, int VectorLength,
51 class MemoryTraits>
52struct is_aosoa_impl<AoSoA<DataTypes, MemorySpace, VectorLength, MemoryTraits>>
53 : public std::true_type
54{
55};
57
59template <class T>
60struct is_aosoa : public is_aosoa_impl<typename std::remove_cv<T>::type>::type
61{
62};
63
64//---------------------------------------------------------------------------//
75template <std::size_t M, class AoSoA_t>
76typename AoSoA_t::template member_slice_type<M>
77slice( const AoSoA_t& aosoa, const std::string& slice_label = "" )
78{
79 static_assert(
80 0 == sizeof( typename AoSoA_t::soa_type ) %
81 sizeof( typename AoSoA_t::template member_value_type<M> ),
82 "Slice stride cannot be calculated for misaligned memory!" );
83
84 return typename AoSoA_t::template member_slice_type<M>(
85 Impl::soaMemberPtr<M>( aosoa.data() ), aosoa.size(), aosoa.numSoA(),
86 slice_label );
87}
88
89//---------------------------------------------------------------------------//
116template <class DataTypes, class MemorySpace,
117 int VectorLength = Impl::PerformanceTraits<
118 typename MemorySpace::execution_space>::vector_length,
119 class MemoryTraits = Kokkos::MemoryManaged>
120class AoSoA
121{
122 public:
126
129
131 "AoSoA data types must be member types" );
133 "AoSoA data type failure" );
135 using member_types = DataTypes;
136
137 // FIXME: extracting the self type for backwards compatibility with previous
138 // template on DeviceType. Should simply be MemorySpace after next release.
140 using memory_space = typename MemorySpace::memory_space;
141 // FIXME: replace warning with memory space assert after next release.
142 static_assert( Impl::deprecated( Kokkos::is_device<MemorySpace>() ) );
143
145 using device_type [[deprecated]] = typename memory_space::device_type;
147 using execution_space = typename memory_space::execution_space;
148
149 static_assert( Impl::IsVectorLengthValid<VectorLength>::value,
150 "Vector length must be valid" );
152 static constexpr int vector_length = VectorLength;
153
155 using memory_traits = MemoryTraits;
156
158 using size_type = typename memory_space::size_type;
159
162
164 using soa_view = Kokkos::View<soa_type*, memory_space, memory_traits>;
165
167 static constexpr std::size_t number_of_members = member_types::size;
168
170 static constexpr std::size_t max_supported_rank = 3;
171
174
177
181 template <std::size_t M>
183
185 template <std::size_t M>
187 typename std::remove_all_extents<member_data_type<M>>::type;
188
190 template <std::size_t M>
192 typename std::add_pointer<member_value_type<M>>::type;
193
195 template <std::size_t M>
199 sizeof( soa_type ) / sizeof( member_value_type<M> )>;
200
201 public:
209 AoSoA( const std::string& label = "" )
210 : _size( 0 )
211 , _capacity( 0 )
212 , _num_soa( 0 )
213 , _data( Kokkos::ViewAllocateWithoutInitializing( label ), 0 )
214 {
215 static_assert(
216 !memory_traits::is_unmanaged,
217 "Construction by allocation cannot use unmanaged memory" );
218 }
219
227 AoSoA( const std::string label, const size_type n )
228 : _size( n )
229 , _capacity( 0 )
230 , _num_soa( 0 )
231 , _data( Kokkos::ViewAllocateWithoutInitializing( label ), 0 )
232 {
233 static_assert(
234 !memory_traits::is_unmanaged,
235 "Construction by allocation cannot use unmanaged memory" );
236 resize( _size );
237 }
238
248 AoSoA( soa_type* ptr, const size_type num_soa, const size_type n )
249 : _size( n )
250 , _capacity( num_soa * vector_length )
251 , _num_soa( num_soa )
252 , _data( ptr, num_soa )
253 {
254 static_assert( memory_traits::is_unmanaged,
255 "Pointer construction requires unmanaged memory" );
256 }
257
265 std::string label() const { return _data.label(); }
266
274 KOKKOS_FUNCTION
275 size_type size() const { return _size; }
276
284 KOKKOS_FUNCTION
285 bool empty() const { return ( size() == 0 ); }
286
304 KOKKOS_FUNCTION
305 size_type capacity() const { return _capacity; }
306
324 void resize( const size_type n )
325 {
326 static_assert( !memory_traits::is_unmanaged,
327 "Cannot resize unmanaged memory" );
328
329 // Reserve memory if needed.
330 reserve( n );
331
332 // Update the sizes of the data. This is potentially different than
333 // the amount of allocated data.
334 _size = n;
335 _num_soa = std::ceil( static_cast<double>( n ) / vector_length );
336 }
337
356 void reserve( const size_type n )
357 {
358 static_assert( !memory_traits::is_unmanaged,
359 "Cannot reserve unmanaged memory" );
360
361 // If we aren't asking for more memory then we have nothing to do.
362 if ( n <= _capacity )
363 return;
364
365 // Figure out the new capacity.
366 size_type num_soa_alloc = std::floor( n / vector_length );
367 if ( 0 < n % vector_length )
368 ++num_soa_alloc;
369
370 // If we aren't asking for any more SoA objects then we still have
371 // nothing to do.
372 if ( num_soa_alloc <= _num_soa )
373 return;
374
375 // Assign the new capacity.
376 _capacity = num_soa_alloc * vector_length;
377
378 // We need more SoA objects so allocate a new view and copy the
379 // existing data.
380 soa_view resized_data(
381 Kokkos::ViewAllocateWithoutInitializing( _data.label() ),
382 num_soa_alloc );
383 if ( _num_soa > 0 )
384 Kokkos::deep_copy(
385 Kokkos::subview(
386 resized_data,
387 Kokkos::pair<size_type, size_type>( 0, _num_soa ) ),
388 Kokkos::subview( _data, Kokkos::pair<size_type, size_type>(
389 0, _num_soa ) ) );
390 _data = resized_data;
391 }
392
402 {
403 static_assert( !memory_traits::is_unmanaged,
404 "Cannot shrink unmanaged memory" );
405
406 // If we aren't asking for any fewer SoA objects then we have nothing
407 // to do. The amount of allocated data has to be at least as big as
408 // _num_soa so we just need to check here that they are equivalent. If
409 // they are equivalent, the container is already as small as it can be.
410 if ( _data.size() == _num_soa )
411 return;
412
413 // Assign the new capacity.
414 _capacity = _num_soa * vector_length;
415
416 // We need fewer SoA objects so allocate a new view and copy the
417 // existing data.
418 soa_view resized_data(
419 Kokkos::ViewAllocateWithoutInitializing( _data.label() ),
420 _num_soa );
421 if ( _num_soa > 0 )
422 Kokkos::deep_copy(
423 resized_data,
424 Kokkos::subview( _data, Kokkos::pair<size_type, size_type>(
425 0, _num_soa ) ) );
426 _data = resized_data;
427 }
428
433 KOKKOS_INLINE_FUNCTION
434 size_type numSoA() const { return _num_soa; }
435
441 KOKKOS_INLINE_FUNCTION
443 {
444 // the SoA struct size should be full size, i.e. vector_length if:
445 // 1) s is not the last SoA struct
446 // or 2) if _size = _num_soa * vector_length
447 return ( ( (size_type)s < _num_soa - 1 ) ||
448 ( _size % vector_length == 0 ) )
449 ? vector_length // if s is a full SoA struct
450 : ( _size % vector_length ); // if s is the last SoA struct
451 }
452
458 KOKKOS_FORCEINLINE_FUNCTION
459 soa_type& access( const size_type s ) const { return _data( s ); }
460
466 KOKKOS_INLINE_FUNCTION
468 {
469 tuple_type tpl;
470 Impl::tupleCopy( tpl, 0, _data( index_type::s( i ) ),
471 index_type::a( i ) );
472 return tpl;
473 }
474
480 KOKKOS_INLINE_FUNCTION
481 void setTuple( const size_type i, const tuple_type& tpl ) const
482 {
483 Impl::tupleCopy( _data( index_type::s( i ) ), index_type::a( i ), tpl,
484 0 );
485 }
486
491 soa_type* data() const { return _data.data(); }
492
493 private:
494 // Total number of tuples in the container.
495 size_type _size;
496
497 // Allocated number of tuples in all arrays in all structs.
498 size_type _capacity;
499
500 // Number of structs-of-arrays in the array.
501 size_type _num_soa;
502
503 // Structs-of-Arrays managed data. This Kokkos View manages the block of
504 // memory owned by this class such that the copy constructor and
505 // assignment operator for this class perform a shallow and reference
506 // counted copy of the data.
507 soa_view _data;
508};
509
510//---------------------------------------------------------------------------//
511
512} // end namespace Cabana
513
514#endif // CABANA_AOSOA_HPP
AoSoA indexing.
AoSoA tuple member types.
Default settings for execution spaces.
Slice a single particle property from an AoSoA.
Struct-of-Arrays for building AoSoA.
Tuple of single particle information to build AoSoA.
Memory access type checking.
Cabana utilities.
Array-of-Struct-of-Arrays.
Definition Cabana_AoSoA.hpp:121
Impl::Index< vector_length > index_type
Definition Cabana_AoSoA.hpp:173
typename MemberTypeAtIndex< M, member_types >::type member_data_type
Definition Cabana_AoSoA.hpp:182
Tuple< member_types > tuple_type
Definition Cabana_AoSoA.hpp:176
void reserve(const size_type n)
Requests that the container capacity be at least enough to contain n tuples.
Definition Cabana_AoSoA.hpp:356
typename MemorySpace::memory_space memory_space
Definition Cabana_AoSoA.hpp:140
std::string label() const
Definition Cabana_AoSoA.hpp:265
typename memory_space::size_type size_type
Definition Cabana_AoSoA.hpp:158
void shrinkToFit()
Remove unused capacity.
Definition Cabana_AoSoA.hpp:401
AoSoA(soa_type *ptr, const size_type num_soa, const size_type n)
Create an unmanaged AoSoA with user-provided memory.
Definition Cabana_AoSoA.hpp:248
static constexpr int vector_length
Definition Cabana_AoSoA.hpp:152
KOKKOS_INLINE_FUNCTION size_type arraySize(const size_type s) const
Get the size of the data array at a given struct member index.
Definition Cabana_AoSoA.hpp:442
MemoryTraits memory_traits
Definition Cabana_AoSoA.hpp:155
KOKKOS_FUNCTION bool empty() const
Returns if the container is empty or not.
Definition Cabana_AoSoA.hpp:285
typename memory_space::execution_space execution_space
Definition Cabana_AoSoA.hpp:147
soa_type * data() const
Get a typed raw pointer to the entire data block.
Definition Cabana_AoSoA.hpp:491
KOKKOS_INLINE_FUNCTION tuple_type getTuple(const size_type i) const
Get a tuple at a given index via a deep copy.
Definition Cabana_AoSoA.hpp:467
Slice< member_data_type< M >, memory_space, DefaultAccessMemory, vector_length, sizeof(soa_type)/sizeof(member_value_type< M >)> member_slice_type
Definition Cabana_AoSoA.hpp:196
typename std::add_pointer< member_value_type< M > >::type member_pointer_type
Definition Cabana_AoSoA.hpp:191
KOKKOS_INLINE_FUNCTION void setTuple(const size_type i, const tuple_type &tpl) const
Set a tuple at a given index via a deep copy.
Definition Cabana_AoSoA.hpp:481
SoA< member_types, vector_length > soa_type
Definition Cabana_AoSoA.hpp:161
KOKKOS_FUNCTION size_type size() const
Returns the number of tuples in the container.
Definition Cabana_AoSoA.hpp:275
typename std::remove_all_extents< member_data_type< M > >::type member_value_type
Definition Cabana_AoSoA.hpp:186
static constexpr std::size_t number_of_members
Definition Cabana_AoSoA.hpp:167
KOKKOS_INLINE_FUNCTION size_type numSoA() const
Get the number of structs-of-arrays in the container.
Definition Cabana_AoSoA.hpp:434
Kokkos::View< soa_type *, memory_space, memory_traits > soa_view
Definition Cabana_AoSoA.hpp:164
static constexpr std::size_t max_supported_rank
Definition Cabana_AoSoA.hpp:170
AoSoA(const std::string &label="")
Default constructor.
Definition Cabana_AoSoA.hpp:209
AoSoA< DataTypes, MemorySpace, VectorLength, MemoryTraits > aosoa_type
AoSoA type.
Definition Cabana_AoSoA.hpp:124
AoSoA(const std::string label, const size_type n)
Allocate a container with n tuples.
Definition Cabana_AoSoA.hpp:227
KOKKOS_FORCEINLINE_FUNCTION soa_type & access(const size_type s) const
Get a reference to the SoA at a given index.
Definition Cabana_AoSoA.hpp:459
void resize(const size_type n)
Resizes the container so that it contains n tuples.
Definition Cabana_AoSoA.hpp:324
AoSoA< DataTypes, Kokkos::HostSpace, VectorLength > host_mirror_type
Definition Cabana_AoSoA.hpp:128
KOKKOS_FUNCTION size_type capacity() const
Returns the size of the storage space currently allocated for the container, expressed in terms of tu...
Definition Cabana_AoSoA.hpp:305
Class for converting between 1d and 2d aosoa indices.
Definition Cabana_Index.hpp:38
static KOKKOS_FORCEINLINE_FUNCTION constexpr std::size_t a(const std::size_t i)
Definition Cabana_Index.hpp:77
static KOKKOS_FORCEINLINE_FUNCTION constexpr std::size_t s(const std::size_t i)
Definition Cabana_Index.hpp:62
A slice of an array-of-structs-of-arrays with data access to a single multidimensional member.
Definition Cabana_Slice.hpp:502
Core: particle data structures and algorithms.
Definition Cabana_AoSoA.hpp:36
AoSoA_t::template member_slice_type< M > slice(const AoSoA_t &aosoa, const std::string &slice_label="")
Create a slice from an AoSoA.
Definition Cabana_AoSoA.hpp:77
Check that member types are valid.
Definition Cabana_MemberTypes.hpp:124
Definition Cabana_Types.hpp:37
Get the type of the member at a given index.
Definition Cabana_MemberTypes.hpp:75
Definition Cabana_SoA.hpp:32
Definition Cabana_Tuple.hpp:32
AoSoA static type checker.
Definition Cabana_AoSoA.hpp:61
Static type checker.
Definition Cabana_MemberTypes.hpp:50