71 static_assert(
sizeof(global_vector_options) == 4);
128 template <
typename T>
139 using reference =
typename std::iterator_traits<pointer>::reference;
155 template <
typename InputIterator>
167 initialize_uniform(count);
171 initialize_uniform(count, value);
174 template <
typename InputIterator,
175 typename = std::enable_if_t<std::is_convertible_v<typename std::iterator_traits<InputIterator>::iterator_category,
176 std::input_iterator_tag>>>
179 initialize_from_iter(
181 typename std::iterator_traits<InputIterator>::iterator_category{});
185 initialize_from_iter(il.begin(), il.end(), std::random_access_iterator_tag{});
191 initialize_from_iter(
194 std::random_access_iterator_tag{});
201 initialize_from_iter(
204 std::random_access_iterator_tag{});
209 : opts_(other.opts_),
210 begin_(other.begin_),
212 reserved_end_(other.reserved_end_) {
213 other.begin_ = other.end_ = other.reserved_end_ =
nullptr;
218 begin_ = other.begin_;
220 reserved_end_ = other.reserved_end_;
221 other.begin_ = other.end_ = other.reserved_end_ =
nullptr;
251 return *(
begin() + i);
256 return *(
begin() + i);
278 swap(opts_ , other.opts_ );
279 swap(begin_ , other.begin_ );
280 swap(end_ , other.end_ );
281 swap(reserved_end_, other.reserved_end_);
292 if (
capacity() == 0 && new_cap > 0) {
293 begin_ = allocate_mem(new_cap);
295 reserved_end_ = begin_ + new_cap;
298 realloc_mem(new_cap);
307 resize_impl(count, value);
311 push_back_impl(value);
318 template <
typename... Args>
320 push_back_impl(std::forward<Args>(
args)...);
326 root_exec_if_coll([&] {
328 std::destroy_at(&cs[0]);
334 return insert_one(position -
cbegin(), x);
342 return insert_n(position -
cbegin(), n, x);
345 template <
typename InputIterator,
346 typename = std::enable_if_t<std::is_convertible_v<typename std::iterator_traits<InputIterator>::iterator_category,
347 std::input_iterator_tag>>>
349 return insert_iter(position -
cbegin(), first, last,
350 typename std::iterator_traits<InputIterator>::iterator_category{});
354 return insert_iter(position -
cbegin(), il.begin(), il.end(),
355 std::random_access_iterator_tag{});
358 template <
typename... Args>
360 return insert_iter(position -
begin(), std::forward<Args>(
args)...);
365 if (
begin() !=
nullptr) {
373 std::stringstream ss;
374 ss <<
"Global vector: Index " << i <<
" is out of range [0, " <<
size() <<
").";
375 throw std::out_of_range(ss.str());
385 return coll_exec_if_coll([=] {
386 return ori::malloc_coll<T>(count);
389 return ori::malloc<T>(count);
395 coll_exec_if_coll([=] {
396 ori::free_coll<T>(p);
399 ori::free<T>(p, count);
403 template <
typename Fn,
typename... Args>
404 auto root_exec_if_coll(Fn&& fn, Args&&...
args)
const {
407 return root_exec(std::forward<Fn>(fn), std::forward<Args>(
args)...);
409 return std::forward<Fn>(fn)(std::forward<Args>(
args)...);
412 return std::forward<Fn>(fn)(std::forward<Args>(
args)...);
416 template <
typename Fn,
typename... Args>
417 auto coll_exec_if_coll(Fn&& fn, Args&&...
args)
const {
420 return std::forward<Fn>(fn)(std::forward<Args>(
args)...);
424 common::die(
"Collective operations for ityr::global_vector must be executed on the root thread or SPMD region.");
427 return std::forward<Fn>(fn)(std::forward<Args>(
args)...);
431 template <
typename... Args>
432 void initialize_uniform(
size_type count,
const Args&...
args) {
433 begin_ = allocate_mem(count);
434 end_ = begin_ + count;
435 reserved_end_ = begin_ + count;
440 template <
typename InputIterator>
441 void initialize_from_iter(InputIterator first, InputIterator last, std::input_iterator_tag) {
445 for (; first != last; ++first) {
446 push_back_impl(*first);
450 template <
typename ForwardIterator>
451 void initialize_from_iter(ForwardIterator first, ForwardIterator last, std::forward_iterator_tag) {
452 auto d = std::distance(first, last);
455 begin_ = allocate_mem(d);
457 reserved_end_ = begin_ + d;
459 construct_elems_from_iter(first, last,
begin());
462 begin_ = end_ = reserved_end_ =
nullptr;
466 template <
typename... Args>
468 root_exec_if_coll([=, opts = opts_]() {
469 if (opts.parallel_construct) {
471 execution::parallel_policy(opts.cutoff_count),
472 make_construct_iterator(b),
473 make_construct_iterator(e),
474 [=](T* p) { new (p) T(args...); });
477 execution::sequenced_policy(opts.cutoff_count),
480 [&](T* p) {
new (p) T(
args...); });
485 template <
typename ForwardIterator>
486 void construct_elems_from_iter(ForwardIterator first, ForwardIterator last, pointer b)
const {
487 root_exec_if_coll([=, opts = opts_]() {
488 if (opts.parallel_construct) {
490 execution::parallel_policy(opts.cutoff_count),
493 make_construct_iterator(b),
494 [](auto&& src, T* p) { new (p) T(std::forward<decltype(src)>(src)); });
497 execution::sequenced_policy(opts.cutoff_count),
501 [](
auto&& src, T* p) {
new (p) T(std::forward<decltype(src)>(src)); });
506 void destruct_elems(pointer b, pointer e)
const {
507 if constexpr (!std::is_trivially_destructible_v<T>) {
508 root_exec_if_coll([=, opts = opts_]() {
509 if (opts.parallel_destruct) {
511 execution::parallel_policy(opts.cutoff_count),
512 make_destruct_iterator(b),
513 make_destruct_iterator(e),
514 [](T* p) { std::destroy_at(p); });
517 execution::sequenced_policy(opts.cutoff_count),
520 [](T* p) { std::destroy_at(p); });
526 void realloc_mem(size_type count) {
527 pointer old_begin = begin_;
528 pointer old_end = end_;
529 size_type old_capacity = capacity();
531 begin_ = allocate_mem(count);
532 end_ = begin_ + (old_end - old_begin);
533 reserved_end_ = begin_ + count;
535 if (old_end - old_begin > 0) {
536 construct_elems_from_iter(
541 destruct_elems(old_begin, old_end);
544 if (old_capacity > 0) {
545 free_mem(old_begin, old_capacity);
549 template <
typename... Args>
550 void resize_impl(size_type count,
const Args&...
args) {
551 if (count >
size()) {
552 if (count > capacity()) {
553 size_type new_cap = next_size(count);
554 realloc_mem(new_cap);
557 end_ =
begin() + count;
559 }
else if (count <
size()) {
560 destruct_elems(
begin() + count,
end());
561 end_ =
begin() + count;
565 template <
typename... Args>
566 void push_back_impl(Args&&...
args) {
567 if (
size() + 1 > capacity()) {
568 size_type new_cap = next_size(
size() + 1);
569 realloc_mem(new_cap);
572 root_exec_if_coll([&] {
574 new (&cs[0]) T(std::forward<Args>(
args)...);
580 void make_space_for_insertion(size_type i, size_type n) {
584 if (
size() + n > capacity()) {
585 size_type new_cap = next_size(
size() + n);
586 realloc_mem(new_cap);
589 construct_elems(
end(),
end() + n);
592 execution::sequenced_policy(opts_.cutoff_count),
596 template <
typename... Args>
597 iterator insert_one(size_type i, Args&&...
args) {
599 push_back_impl(std::forward<Args>(
args)...);
603 make_space_for_insertion(i, 1);
605 root_exec_if_coll([&] {
607 cs[0] = T(std::forward<Args>(
args)...);
614 iterator insert_n(size_type i, size_type n,
const value_type& value) {
619 make_space_for_insertion(i, n);
621 root_exec_if_coll([&] {
622 fill(execution::sequenced_policy(opts_.cutoff_count),
630 template <
typename InputIterator>
631 iterator insert_iter(size_type i, InputIterator first, InputIterator last, std::input_iterator_tag) {
633 for (; first != last; ++first) {
634 insert_one(pos++, *first);
639 template <
typename ForwardIterator>
640 iterator insert_iter(size_type i, ForwardIterator first, ForwardIterator last, std::forward_iterator_tag) {
645 size_type n = std::distance(first, last);
646 make_space_for_insertion(i, n);
648 root_exec_if_coll([&] {
649 copy(execution::sequenced_policy(opts_.cutoff_count),
650 first, last,
begin() + i);
657 global_vector_options opts_;
658 pointer begin_ =
nullptr;
659 pointer end_ =
nullptr;
660 pointer reserved_end_ =
nullptr;
663 template <
typename T>
668 template <
typename T>
675 template <
typename T>
680 ITYR_TEST_CASE(
"[ityr::container::global_vector] test") {
690 global_vector<long> gv1(global_vector_options{
true, 256},
691 count_iterator<long>(0),
692 count_iterator<long>(n));
698 execution::parallel_policy(128),
699 gv1.begin(), gv1.end());
704 global_vector<long> gv2 = gv1;
707 execution::parallel_policy(128),
710 [](
long& i) { i *= 2; });
713 execution::parallel_policy(128),
714 gv1.begin(), gv1.end());
718 execution::parallel_policy(128),
719 gv2.begin(), gv2.end());
723 global_vector<long> gv3 = gv1;
726 execution::parallel_policy(128),
730 [](
long i,
long j) { ITYR_CHECK(i == j); });
735 global_vector<long> gv2 =
std::move(gv1);
740 execution::parallel_policy(128),
741 gv2.begin(), gv2.end());
747 gv1.resize(n * 10, 3);
750 execution::parallel_policy(128),
751 gv1.begin(), gv1.end());
752 ITYR_CHECK(count == n * (n - 1) / 2 + (n * 9) * 3);
757 execution::parallel_policy(128),
758 gv1.begin(), gv1.end());
759 ITYR_CHECK(count == n * (n - 1) / 2 + (n * 4) * 3);
770 global_vector<common::move_only_t> gv2(global_vector_options{
true, 256},
773 long next_size = gv2.capacity() * 2;
774 gv2.resize(next_size);
777 execution::parallel_policy(128),
780 reducer::plus<long>{},
781 [](
const common::move_only_t& mo) { return mo.value(); });
789 global_vector<global_vector<long>> gvs(global_vector_options{
true,
false,
false});
793 global_vector<long> gv1;
795 for (
long i = 0; i < n; i++) {
802 auto check_sum = [&](
long ans) {
807 reducer::plus<long>{},
809 auto cs = make_checkout(&gv_ref, 1, checkout_mode::read_write);
810 auto gv_begin = cs[0].begin();
811 auto gv_end = cs[0].end();
813 return reduce(execution::parallel_policy(128),
820 check_sum(n * (n - 1) / 2 *
n_ranks);
826 [&](global_vector<long>& gv) {
827 for (long i = 0; i < 100; i++) {
830 for (
long i = 0; i < 100; i++) {
835 execution::sequenced_policy(128),
836 count_iterator<long>(n),
837 count_iterator<long>(2 * n),
839 [](
long i,
long& x) { x = i; });
842 check_sum((2 * n) * (2 * n - 1) / 2 *
n_ranks);
848 global_vector<int> v1 = {1, 2, 3, 4, 5};
849 global_vector<int> v2 = {10, 20, 30};
851 v1.insert(v1.begin() + 2, 0);
852 ITYR_CHECK(v1 == global_vector<int>({1, 2, 0, 3, 4, 5}));
854 v1.insert(v1.end() - 1, 3, -1);
855 ITYR_CHECK(v1 == global_vector<int>({1, 2, 0, 3, 4, -1, -1, -1, 5}));
857 v1.insert(v1.begin(), v2.begin(), v2.end());
858 ITYR_CHECK(v1 == global_vector<int>({10, 20, 30, 1, 2, 0, 3, 4, -1, -1, -1, 5}));
864 global_vector<int> v = {1, 2, 3, 4, 5};
869 v.insert(v.end(), {6, 7, 8});
870 ITYR_CHECK(v == global_vector<int>({1, 2, 3, 4, 5, 6, 7, 8}));
Global vector to manage a global memory region.
Definition: global_vector.hpp:129
reference operator[](size_type i)
Definition: global_vector.hpp:249
global_vector(const this_t &other)
Definition: global_vector.hpp:190
iterator begin() noexcept
Definition: global_vector.hpp:233
global_vector(const global_vector_options &opts, std::initializer_list< T > il)
Definition: global_vector.hpp:184
global_vector(InputIterator first, InputIterator last)
Definition: global_vector.hpp:156
size_type size() const noexcept
Definition: global_vector.hpp:228
void push_back(value_type &&value)
Definition: global_vector.hpp:314
const_reverse_iterator crbegin() const noexcept
Definition: global_vector.hpp:246
typename std::iterator_traits< pointer >::reference reference
Definition: global_vector.hpp:139
const_reverse_iterator rend() noexcept
Definition: global_vector.hpp:244
global_vector_options options() const noexcept
Definition: global_vector.hpp:231
bool empty() const noexcept
Definition: global_vector.hpp:274
global_vector(const global_vector_options &opts, size_type count, const T &value)
Definition: global_vector.hpp:170
void push_back(const value_type &value)
Definition: global_vector.hpp:310
const_reference at(size_type i) const
Definition: global_vector.hpp:264
void swap(this_t &other) noexcept
Definition: global_vector.hpp:276
void resize(size_type count, const value_type &value)
Definition: global_vector.hpp:306
global_vector() noexcept
Definition: global_vector.hpp:146
const_reference back() const
Definition: global_vector.hpp:272
reference back()
Definition: global_vector.hpp:270
ori::global_ptr< std::add_const_t< element_type > > const_pointer
Definition: global_vector.hpp:137
const_reference front() const
Definition: global_vector.hpp:271
const_iterator cbegin() const noexcept
Definition: global_vector.hpp:238
global_vector(this_t &&other) noexcept
Definition: global_vector.hpp:208
global_vector(std::initializer_list< T > il)
Definition: global_vector.hpp:159
iterator insert(const_iterator position, T &&x)
Definition: global_vector.hpp:337
iterator insert(const_iterator position, const T &x)
Definition: global_vector.hpp:333
iterator end() noexcept
Definition: global_vector.hpp:234
reverse_iterator rbegin() const noexcept
Definition: global_vector.hpp:241
std::reverse_iterator< const_iterator > const_reverse_iterator
Definition: global_vector.hpp:144
pointer data() noexcept
Definition: global_vector.hpp:225
global_vector(size_type count, const value_type &value)
Definition: global_vector.hpp:152
void resize(size_type count)
Definition: global_vector.hpp:302
void pop_back()
Definition: global_vector.hpp:324
reference front()
Definition: global_vector.hpp:269
std::size_t size_type
Definition: global_vector.hpp:135
const_reference operator[](size_type i) const
Definition: global_vector.hpp:254
size_type capacity() const noexcept
Definition: global_vector.hpp:229
reference at(size_type i)
Definition: global_vector.hpp:259
void clear()
Definition: global_vector.hpp:284
global_vector(size_type count)
Definition: global_vector.hpp:149
iterator insert(const_iterator position, std::initializer_list< T > il)
Definition: global_vector.hpp:353
ori::global_ptr< element_type > pointer
Definition: global_vector.hpp:136
global_vector(const global_vector_options &opts) noexcept
Definition: global_vector.hpp:164
typename std::iterator_traits< const_pointer >::reference const_reference
Definition: global_vector.hpp:140
const_iterator begin() const noexcept
Definition: global_vector.hpp:235
const_iterator cend() const noexcept
Definition: global_vector.hpp:239
std::reverse_iterator< iterator > reverse_iterator
Definition: global_vector.hpp:143
const_iterator end() const noexcept
Definition: global_vector.hpp:236
iterator insert(const_iterator position, InputIterator first, InputIterator last)
Definition: global_vector.hpp:348
reverse_iterator rend() const noexcept
Definition: global_vector.hpp:242
typename std::iterator_traits< pointer >::difference_type difference_type
Definition: global_vector.hpp:138
const_reverse_iterator crend() const noexcept
Definition: global_vector.hpp:247
iterator emplace(const_iterator position, Args &&... args)
Definition: global_vector.hpp:359
void reserve(size_type new_cap)
Definition: global_vector.hpp:291
std::remove_cv_t< element_type > value_type
Definition: global_vector.hpp:134
global_vector(const global_vector_options &opts, InputIterator first, InputIterator last)
Definition: global_vector.hpp:177
this_t & operator=(this_t &&other) noexcept
Definition: global_vector.hpp:215
reference emplace_back(Args &&... args)
Definition: global_vector.hpp:319
const_pointer data() const noexcept
Definition: global_vector.hpp:226
iterator insert(const_iterator position, size_type n, const T &x)
Definition: global_vector.hpp:341
~global_vector()
Definition: global_vector.hpp:188
global_vector(const global_vector_options &opts, size_type count)
Definition: global_vector.hpp:166
T element_type
Definition: global_vector.hpp:133
const_reverse_iterator rbegin() noexcept
Definition: global_vector.hpp:243
this_t & operator=(const this_t &other)
Definition: global_vector.hpp:196
#define ITYR_SUBCASE(name)
Definition: util.hpp:41
#define ITYR_CHECK(cond)
Definition: util.hpp:48
constexpr read_write_t read_write
Read+Write checkout mode.
Definition: checkout_span.hpp:39
constexpr read_t read
Read-only checkout mode.
Definition: checkout_span.hpp:19
constexpr no_access_t no_access
Checkout mode to disable automatic checkout.
Definition: checkout_span.hpp:48
constexpr write_t write
Write-only checkout mode.
Definition: checkout_span.hpp:29
void end()
Definition: profiler.hpp:334
void begin()
Definition: profiler.hpp:329
rank_t n_ranks()
Definition: topology.hpp:208
rank_t my_rank()
Definition: topology.hpp:207
va_list args
Definition: util.hpp:76
constexpr auto size(const span< T > &s) noexcept
Definition: span.hpp:61
constexpr parallel_policy par
Default parallel execution policy for iterator-based loop functions.
Definition: execution.hpp:89
void fini()
Definition: ito.hpp:45
auto root_exec(Fn &&fn, Args &&... args)
Definition: ito.hpp:50
auto coll_exec(const Fn &fn, const Args &... args)
Definition: ito.hpp:72
void init(MPI_Comm comm=MPI_COMM_WORLD)
Definition: ito.hpp:41
bool is_root()
Definition: ito.hpp:66
bool is_spmd()
Definition: ito.hpp:61
monoid< T, max_functor<>, lowest< T > > max
Definition: reducer.hpp:104
Definition: allocator.hpp:16
global_reverse_iterator< global_iterator< T, Mode > > make_reverse_iterator(ori::global_ptr< T > gptr, Mode mode)
Make a reverse iterator for global memory.
Definition: global_iterator.hpp:333
bool operator==(const global_vector< T > &x, const global_vector< T > &y)
Definition: global_vector.hpp:669
global_destruct_iterator< GlobalIterator > make_destruct_iterator(GlobalIterator git)
Make a global iterator for destructing objects.
Definition: global_iterator.hpp:499
global_construct_iterator< GlobalIterator > make_construct_iterator(GlobalIterator git)
Make a global iterator for constructing objects.
Definition: global_iterator.hpp:406
bool operator!=(const global_vector< T > &x, const global_vector< T > &y)
Definition: global_vector.hpp:676
ForwardIteratorD copy(const ExecutionPolicy &policy, ForwardIterator1 first1, ForwardIterator1 last1, ForwardIteratorD first_d)
Copy a range to another.
Definition: parallel_loop.hpp:856
void for_each(const ExecutionPolicy &policy, ForwardIterator first, ForwardIterator last, Op op)
Apply an operator to each element in a range.
Definition: parallel_loop.hpp:136
BidirectionalIteratorD move_backward(const execution::sequenced_policy &policy, BidirectionalIterator1 first1, BidirectionalIterator1 last1, BidirectionalIteratorD first_d)
Definition: serial_loop.hpp:108
checkout_span< T, Mode > make_checkout(ori::global_ptr< T > gptr, std::size_t n, Mode mode)
Checkout a global memory region.
Definition: checkout_span.hpp:238
void fill(const ExecutionPolicy &policy, ForwardIterator first, ForwardIterator last, const T &value)
Fill a range with a given value.
Definition: parallel_loop.hpp:771
auto root_exec(Fn &&fn, Args &&... args)
Spawn the root thread (collective).
Definition: root_exec.hpp:47
Reducer::accumulator_type transform_reduce(const ExecutionPolicy &policy, ForwardIterator first, ForwardIterator last, Reducer reducer, UnaryTransformOp unary_transform_op)
Calculate reduction while transforming each element.
Definition: parallel_reduce.hpp:167
void swap(global_vector< T > &v1, global_vector< T > &v2) noexcept
Definition: global_vector.hpp:664
Reducer::accumulator_type reduce(const ExecutionPolicy &policy, ForwardIterator first, ForwardIterator last, Reducer reducer)
Calculate reduction.
Definition: parallel_reduce.hpp:340
global_iterator< T, Mode > make_global_iterator(ori::global_ptr< T > gptr, Mode)
Make a global iterator to enable/disable automatic checkout.
Definition: global_iterator.hpp:158
global_move_iterator< global_iterator< T, internal::src_checkout_mode_t< T > > > make_move_iterator(ori::global_ptr< T > gptr)
Make a global iterator for moving objects.
Definition: global_iterator.hpp:258
bool equal(const ExecutionPolicy &policy, ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, BinaryPredicate pred)
Check if two ranges have equal values.
Definition: parallel_reduce.hpp:887
ForwardIteratorD move(const ExecutionPolicy &policy, ForwardIterator1 first1, ForwardIterator1 last1, ForwardIteratorD first_d)
Move a range to another.
Definition: parallel_loop.hpp:934
Parallel execution policy for iterator-based loop functions.
Definition: execution.hpp:36
Options for ityr::global_vector.
Definition: global_vector.hpp:18
constexpr global_vector_options(bool collective, bool parallel_construct, bool parallel_destruct, int cutoff_count=default_cutoff_count)
Definition: global_vector.hpp:60
constexpr global_vector_options(bool collective, int cutoff_count)
Definition: global_vector.hpp:53
int cutoff_count
The number of elements for leaf tasks to stop parallel recursion in construction and destruction.
Definition: global_vector.hpp:37
constexpr global_vector_options()
Definition: global_vector.hpp:41
bool parallel_destruct
Destruction of vector elements is parallelized if true.
Definition: global_vector.hpp:32
bool collective
A collective global vector is initialized if true.
Definition: global_vector.hpp:22
constexpr static int default_cutoff_count
Definition: global_vector.hpp:39
bool parallel_construct
Construction of vector elements is parallelized if true.
Definition: global_vector.hpp:27
constexpr global_vector_options(bool collective)
Definition: global_vector.hpp:47