16#ifndef dealii_aligned_vector_h
17#define dealii_aligned_vector_h
29#include <boost/version.hpp>
30#if BOOST_VERSION >= 106400
31# include <boost/serialization/array_wrapper.hpp>
33# include <boost/serialization/array.hpp>
35#include <boost/serialization/split_member.hpp>
90 typename RandomAccessIterator,
91 typename = std::enable_if_t<std::is_convertible_v<
92 typename std::iterator_traits<RandomAccessIterator>::iterator_category,
93 std::random_access_iterator_tag>>>
251 template <
typename ForwardIterator>
264 typename RandomAccessIterator,
265 typename = std::enable_if_t<std::is_convertible_v<
266 typename std::iterator_traits<RandomAccessIterator>::iterator_category,
267 std::random_access_iterator_tag>>>
270 RandomAccessIterator
begin,
271 RandomAccessIterator
end);
473 template <
class Archive>
482 template <
class Archive>
492 template <
class Archive>
508 "Changing the vector after a call to "
509 "replicate_across_communicator() is not allowed.");
622#ifdef DEAL_II_WITH_MPI
631 const bool is_shmem_root,
632 T *aligned_shmem_pointer,
634 MPI_Win shmem_window);
676#ifdef DEAL_II_WITH_MPI
776 template <
typename RandomAccessIterator,
typename T>
781 160000 /
sizeof(T) + 1;
815 const std::size_t end)
const override
821 if constexpr (std::is_trivially_copyable_v<T> ==
true &&
822 (std::is_same_v<T *, RandomAccessIterator> ||
823 std::is_same_v<const T *, RandomAccessIterator>) ==
true)
826 (end - begin) *
sizeof(T));
828 for (std::size_t i = begin; i < end; ++i)
844 template <
typename RandomAccessIterator,
typename T>
849 160000 /
sizeof(T) + 1;
883 const std::size_t end)
const override
889 if constexpr (std::is_trivially_copyable_v<T> ==
true &&
890 (std::is_same_v<T *, RandomAccessIterator> ||
891 std::is_same_v<const T *, RandomAccessIterator>) ==
true)
894 (end - begin) *
sizeof(T));
898 for (std::size_t i = begin; i < end; ++i)
925 template <
typename T,
bool initialize_memory>
929 160000 /
sizeof(T) + 1;
950 if constexpr (std::is_trivially_default_constructible_v<T> ==
true &&
951 std::is_same_v<T, long double> ==
false)
953 const unsigned char zero[
sizeof(T)] = {};
954 if (std::memcmp(zero, &element,
sizeof(T)) == 0)
968 const std::size_t end)
const override
972 if constexpr (std::is_trivially_default_constructible_v<T> ==
true)
975 std::memset(
destination_ + begin, 0, (end - begin) *
sizeof(T));
981 std::bool_constant<initialize_memory>());
992 const std::size_t end,
993 std::bool_constant<false>)
const
995 for (std::size_t i = begin; i < end; ++i)
1002 const std::size_t end,
1003 std::bool_constant<true>)
const
1005 for (std::size_t i = begin; i < end; ++i)
1024 template <
typename T,
bool initialize_memory>
1029 160000 /
sizeof(T) + 1;
1054 const std::size_t end)
const override
1058 if constexpr (std::is_trivially_default_constructible_v<T> ==
true)
1059 std::memset(
destination_ + begin, 0, (end - begin) *
sizeof(T));
1063 std::bool_constant<initialize_memory>());
1072 const std::size_t end,
1073 std::bool_constant<false>)
const
1075 for (std::size_t i = begin; i < end; ++i)
1082 const std::size_t end,
1083 std::bool_constant<true>)
const
1085 for (std::size_t i = begin; i < end; ++i)
1097template <
typename T>
1099 : deleter_action_object(
nullptr)
1104# ifdef DEAL_II_WITH_MPI
1106template <
typename T>
1108 const bool is_shmem_root,
1109 T *aligned_shmem_pointer,
1111 MPI_Win shmem_window)
1112 : deleter_action_object(
1114 aligned_shmem_pointer,
1115 shmem_group_communicator,
1122template <
typename T>
1128 if (deleter_action_object ==
nullptr)
1132 Assert(owning_aligned_vector->used_elements_end !=
nullptr,
1135 if (std::is_trivially_destructible_v<T> ==
false)
1136 for (T *p = owning_aligned_vector->used_elements_end - 1; p >= ptr;
1145 deleter_action_object->delete_array(owning_aligned_vector, ptr);
1150template <
typename T>
1159# ifdef DEAL_II_WITH_MPI
1161template <
typename T>
1164 T *aligned_shmem_pointer,
1166 MPI_Win shmem_window)
1167 : is_shmem_root(is_shmem_root)
1168 , aligned_shmem_pointer(aligned_shmem_pointer)
1169 , shmem_group_communicator(shmem_group_communicator)
1170 , shmem_window(shmem_window)
1175template <
typename T>
1192 if (std::is_trivially_destructible_v<T> ==
false)
1193 for (T *p =
aligned_vector->used_elements_end - 1; p >= ptr; --p)
1210 , allocated_elements_end(
nullptr)
1212 , replicated_across_communicator(
false)
1219template <
typename RandomAccessIterator,
typename>
1221 RandomAccessIterator end)
1224 , allocated_elements_end(
nullptr)
1225 , replicated_across_communicator(
false)
1227 allocate_and_move(0
u, end - begin, end - begin);
1228 used_elements_end = allocated_elements_end;
1239 , allocated_elements_end(
nullptr)
1241 , replicated_across_communicator(
false)
1254 , allocated_elements_end(
nullptr)
1256 , replicated_across_communicator(
false)
1260 reserve(
vec.size());
1261 used_elements_end = allocated_elements_end;
1263 vec.used_elements_end,
1274 *
this = std::move(
vec);
1293 vec.used_elements_end,
1297 used_elements_end = elements.get() +
new_size;
1316 elements = std::move(
vec.elements);
1317 elements.get_deleter().reset_owning_object(
this);
1320 used_elements_end =
vec.used_elements_end;
1321 allocated_elements_end =
vec.allocated_elements_end;
1323 vec.used_elements_end =
nullptr;
1324 vec.allocated_elements_end =
nullptr;
1347 if (std::is_trivially_destructible_v<T> ==
false)
1348 for (T *p = used_elements_end - 1; p >= elements.get() +
new_size; --p)
1350 used_elements_end = elements.get() +
new_size;
1356 used_elements_end = elements.get() +
new_size;
1360 if (std::is_trivially_default_constructible_v<T> ==
false)
1384 if (std::is_trivially_destructible_v<T> ==
false)
1385 for (T *p = used_elements_end - 1; p >= elements.get() +
new_size; --p)
1387 used_elements_end = elements.get() +
new_size;
1393 used_elements_end = elements.get() +
new_size;
1419 if (std::is_trivially_destructible_v<T> ==
false)
1420 for (T *p = used_elements_end - 1; p >= elements.get() +
new_size; --p)
1422 used_elements_end = elements.get() +
new_size;
1428 used_elements_end = elements.get() +
new_size;
1473 used_elements_end = elements.get() +
old_size;
1474 allocated_elements_end = elements.get() +
new_size;
1509 Assert(replicated_across_communicator ==
false,
1510 ExcAlignedVectorChangeAfterReplication());
1513 const size_type allocated_size = allocated_elements_end - elements.get();
1532 used_elements_end =
nullptr;
1533 allocated_elements_end =
nullptr;
1543 if (used_elements_end == allocated_elements_end)
1545 new (used_elements_end++) T(
in_data);
1555 T *
field = used_elements_end - 1;
1566 const T *
field = used_elements_end - 1;
1573template <
typename ForwardIterator>
1580 new (used_elements_end) T(*begin);
1586template <
typename RandomAccessIterator,
typename>
1589 RandomAccessIterator begin,
1590 RandomAccessIterator end)
1592 Assert(replicated_across_communicator ==
false,
1593 ExcAlignedVectorChangeAfterReplication());
1595 ExcMessage(
"The position iterator is not valid."));
1596 const auto offset = position - this->begin();
1614 elements.get(), elements.get() + offset,
new_data_ptr);
1618 elements.get() + offset,
1624 used_elements_end = elements.get() +
new_size;
1625 allocated_elements_end = elements.get() +
new_size;
1627 return this->begin() + offset;
1658# ifdef DEAL_II_WITH_MPI
1679 used_elements_end =
nullptr;
1680 allocated_elements_end =
nullptr;
1717 &shmem_group_communicator);
1728 const bool is_shmem_root =
1764 (is_shmem_root ? 0 : 1),
1785 if (std::is_trivially_copyable_v<T> ==
true)
1863 MPI_Win shmem_window;
1878 "mpi_minimum_memory_alignment",
1884 shmem_group_communicator,
1912 if (is_shmem_root ==
false)
1939 T *aligned_shmem_pointer =
static_cast<T *
>(
1978 if (std::is_trivially_copyable_v<T> ==
true)
1979 std::memcpy(aligned_shmem_pointer, elements.get(),
sizeof(T) *
size());
1981 for (std::size_t i = 0; i <
size(); ++i)
1982 new (&aligned_shmem_pointer[i]) T(std::move(elements[i]));
2007 elements =
decltype(elements)(aligned_shmem_pointer,
2010 aligned_shmem_pointer,
2011 shmem_group_communicator,
2018 used_elements_end = elements.get() +
new_size;
2019 allocated_elements_end = used_elements_end;
2025 replicated_across_communicator =
true;
2047 std::swap(elements,
vec.elements);
2048 elements.get_deleter().reset_owning_object(
this);
2049 vec.elements.get_deleter().reset_owning_object(&
vec);
2052 std::swap(used_elements_end,
vec.used_elements_end);
2053 std::swap(allocated_elements_end,
vec.allocated_elements_end);
2062 return used_elements_end == elements.get();
2071 return used_elements_end - elements.get();
2080 return allocated_elements_end - elements.get();
2090 return elements[
index];
2100 return elements[
index];
2105template <
typename T>
2109 return elements.get();
2114template <
typename T>
2118 return elements.get();
2127 return elements.get();
2136 return used_elements_end;
2145 return elements.get();
2154 return used_elements_end;
2160template <
class Archive>
2167 ar &boost::serialization::make_array(elements.get(),
vec_size);
2173template <
class Archive>
2183 ar &boost::serialization::make_array(elements.get(),
vec_size);
2184 used_elements_end = elements.get() +
vec_size;
2195 for (
const T *t = elements.get(); t != used_elements_end; ++t)
2197 memory +=
sizeof(T) * (allocated_elements_end - used_elements_end);
2214 if (
lhs.size() !=
rhs.size())
bool operator==(const AlignedVector< T > &lhs, const AlignedVector< T > &rhs)
virtual ~DeleterActionBase()=default
virtual void delete_array(const AlignedVector< T > *owning_aligned_vector, T *ptr)=0
MPI_Comm shmem_group_communicator
virtual void delete_array(const AlignedVector< T > *aligned_vector, T *ptr)
MPISharedMemDeleterAction(const bool is_shmem_root, T *aligned_shmem_pointer, MPI_Comm shmem_group_communicator, MPI_Win shmem_window)
T * aligned_shmem_pointer
Deleter(AlignedVector< T > *owning_object, const bool is_shmem_root, T *aligned_shmem_pointer, MPI_Comm shmem_group_communicator, MPI_Win shmem_window)
Deleter(AlignedVector< T > *owning_object)
std::unique_ptr< DeleterActionBase > deleter_action_object
void reset_owning_object(const AlignedVector< T > *new_aligned_vector_ptr)
const AlignedVector< T > * owning_aligned_vector
void replicate_across_communicator(const MPI_Comm communicator, const unsigned int root_process)
size_type memory_consumption() const
void resize_fast(const size_type new_size)
std::unique_ptr< T[], Deleter > elements
reference operator[](const size_type index)
void fill(const T &element)
const_iterator end() const
AlignedVector(AlignedVector< T > &&vec) noexcept
void reserve(const size_type new_allocated_size)
void serialize(Archive &archive, const unsigned int version)
bool operator!=(const AlignedVector< T > &lhs, const AlignedVector< T > &rhs)
const_reference operator[](const size_type index) const
void resize(const size_type new_size, const T &init)
AlignedVector & operator=(AlignedVector< T > &&vec) noexcept
AlignedVector(RandomAccessIterator begin, RandomAccessIterator end)
size_type capacity() const
AlignedVector & operator=(const AlignedVector< T > &vec)
void swap(AlignedVector< T > &vec) noexcept
const value_type * const_pointer
bool replicated_across_communicator
void push_back(const T in_data)
iterator insert(const_iterator position, RandomAccessIterator begin, RandomAccessIterator end)
const_iterator begin() const
AlignedVector(const size_type size, const T &init=T())
T * allocated_elements_end
AlignedVector(const AlignedVector< T > &vec)
const_reference back() const
bool operator==(const AlignedVector< T > &lhs, const AlignedVector< T > &rhs)
const value_type * const_iterator
void resize(const size_type new_size)
void load(Archive &ar, const unsigned int version)
void allocate_and_move(const size_t old_size, const size_t new_size, const size_t new_allocated_size)
void save(Archive &ar, const unsigned int version) const
void insert_back(ForwardIterator begin, ForwardIterator end)
const value_type & const_reference
const_pointer data() const
AlignedVectorCopyConstruct(RandomAccessIterator source_begin, RandomAccessIterator source_end, T *const destination)
RandomAccessIterator source_
static const std::size_t minimum_parallel_grain_size
virtual void apply_to_subrange(const std::size_t begin, const std::size_t end) const override
AlignedVectorDefaultInitialize(const std::size_t size, T *const destination)
static const std::size_t minimum_parallel_grain_size
virtual void apply_to_subrange(const std::size_t begin, const std::size_t end) const override
void default_construct_or_assign(const std::size_t begin, const std::size_t end, std::bool_constant< false >) const
void default_construct_or_assign(const std::size_t begin, const std::size_t end, std::bool_constant< true >) const
void copy_construct_or_assign(const std::size_t begin, const std::size_t end, std::bool_constant< false >) const
static const std::size_t minimum_parallel_grain_size
virtual void apply_to_subrange(const std::size_t begin, const std::size_t end) const override
void copy_construct_or_assign(const std::size_t begin, const std::size_t end, std::bool_constant< true >) const
AlignedVectorInitialize(const std::size_t size, const T &element, T *const destination)
RandomAccessIterator source_
AlignedVectorMoveConstruct(RandomAccessIterator source_begin, RandomAccessIterator source_end, T *const destination)
virtual void apply_to_subrange(const std::size_t begin, const std::size_t end) const override
static const std::size_t minimum_parallel_grain_size
#define DEAL_II_NAMESPACE_OPEN
#define DEAL_II_NAMESPACE_CLOSE
#define Assert(cond, exc)
#define AssertThrowMPI(error_code)
#define AssertIndexRange(index, range)
#define DeclExceptionMsg(Exception, defaulttext)
static ::ExceptionBase & ExcInternalError()
static ::ExceptionBase & ExcMessage(std::string arg1)
static ::ExceptionBase & ExcAlignedVectorChangeAfterReplication()
std::vector< index_type > data
types::global_dof_index size_type
std::enable_if_t< std::is_fundamental_v< T >, std::size_t > memory_consumption(const T &t)
VectorType::value_type * end(VectorType &V)
VectorType::value_type * begin(VectorType &V)
T max(const T &t, const MPI_Comm mpi_communicator)
T min(const T &t, const MPI_Comm mpi_communicator)
unsigned int this_mpi_process(const MPI_Comm mpi_communicator)
void free_communicator(MPI_Comm mpi_communicator)
T broadcast(const MPI_Comm comm, const T &object_to_send, const unsigned int root_process=0)
void posix_memalign(void **memptr, std::size_t alignment, std::size_t size)
size_t pack(const T &object, std::vector< char > &dest_buffer, const bool allow_compression=true)
::VectorizedArray< Number, width > max(const ::VectorizedArray< Number, width > &, const ::VectorizedArray< Number, width > &)
void apply_parallel(const std::size_t begin, const std::size_t end, const std::size_t minimum_parallel_grain_size) const