Itoyori  v0.0.1
global_vector.hpp
Go to the documentation of this file.
1 #pragma once
2 
3 #include "ityr/common/util.hpp"
4 #include "ityr/ito/ito.hpp"
5 #include "ityr/ori/ori.hpp"
11 
12 namespace ityr {
13 
22  bool collective : 1;
23 
28 
33 
37  int cutoff_count : 29;
38 
39  constexpr static int default_cutoff_count = 1024;
40 
42  : collective(false),
43  parallel_construct(false),
44  parallel_destruct(false),
46 
47  constexpr explicit global_vector_options(bool collective)
52 
54  int cutoff_count)
59 
61  bool parallel_construct,
62  bool parallel_destruct,
68 };
69 
70 // should be 32 bit long
71 static_assert(sizeof(global_vector_options) == 4);
72 
128 template <typename T>
130  using this_t = global_vector;
131 
132 public:
133  using element_type = T;
134  using value_type = std::remove_cv_t<element_type>;
135  using size_type = std::size_t;
138  using difference_type = typename std::iterator_traits<pointer>::difference_type;
139  using reference = typename std::iterator_traits<pointer>::reference;
140  using const_reference = typename std::iterator_traits<const_pointer>::reference;
141  using iterator = pointer;
143  using reverse_iterator = std::reverse_iterator<iterator>;
144  using const_reverse_iterator = std::reverse_iterator<const_iterator>;
145 
146  global_vector() noexcept
148 
149  explicit global_vector(size_type count)
150  : global_vector(global_vector_options(), count) {}
151 
152  explicit global_vector(size_type count, const value_type& value)
153  : global_vector(global_vector_options(), count, value) {}
154 
155  template <typename InputIterator>
156  global_vector(InputIterator first, InputIterator last)
157  : global_vector(global_vector_options(), first, last) {}
158 
159  global_vector(std::initializer_list<T> il)
161 
162  /* with options */
163 
164  explicit global_vector(const global_vector_options& opts) noexcept : opts_(opts) {}
165 
166  explicit global_vector(const global_vector_options& opts, size_type count) : opts_(opts) {
167  initialize_uniform(count);
168  }
169 
170  explicit global_vector(const global_vector_options& opts, size_type count, const T& value) : opts_(opts) {
171  initialize_uniform(count, value);
172  }
173 
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>>>
177  global_vector(const global_vector_options& opts, InputIterator first, InputIterator last) : opts_(opts) {
178  // TODO: automatic checkout by making global iterators?
179  initialize_from_iter(
180  first, last,
181  typename std::iterator_traits<InputIterator>::iterator_category{});
182  }
183 
184  global_vector(const global_vector_options& opts, std::initializer_list<T> il) : opts_(opts) {
185  initialize_from_iter(il.begin(), il.end(), std::random_access_iterator_tag{});
186  }
187 
188  ~global_vector() { destroy(); }
189 
190  global_vector(const this_t& other) : opts_(other.options()) {
191  initialize_from_iter(
194  std::random_access_iterator_tag{});
195  }
196  this_t& operator=(const this_t& other) {
197  // TODO: skip freeing memory and reuse it when it has enough amount of memory
198  destroy();
199  // should we copy options?
200  opts_ = other.options();
201  initialize_from_iter(
204  std::random_access_iterator_tag{});
205  return *this;
206  }
207 
208  global_vector(this_t&& other) noexcept
209  : opts_(other.opts_),
210  begin_(other.begin_),
211  end_(other.end_),
212  reserved_end_(other.reserved_end_) {
213  other.begin_ = other.end_ = other.reserved_end_ = nullptr;
214  }
215  this_t& operator=(this_t&& other) noexcept {
216  destroy();
217  opts_ = other.opts_;
218  begin_ = other.begin_;
219  end_ = other.end_;
220  reserved_end_ = other.reserved_end_;
221  other.begin_ = other.end_ = other.reserved_end_ = nullptr;
222  return *this;
223  }
224 
225  pointer data() noexcept { return begin_; }
226  const_pointer data() const noexcept { return begin_; }
227 
228  size_type size() const noexcept { return end_ - begin_; }
229  size_type capacity() const noexcept { return reserved_end_ - begin_; }
230 
231  global_vector_options options() const noexcept { return opts_; }
232 
233  iterator begin() noexcept { return begin_; }
234  iterator end() noexcept { return end_; }
235  const_iterator begin() const noexcept { return begin_; }
236  const_iterator end() const noexcept { return end_; }
237 
238  const_iterator cbegin() const noexcept { return ori::const_pointer_cast<std::add_const_t<T>>(begin_); }
239  const_iterator cend() const noexcept { return ori::const_pointer_cast<std::add_const_t<T>>(end_); }
240 
241  reverse_iterator rbegin() const noexcept { return std::make_reverse_iterator(end()); }
242  reverse_iterator rend() const noexcept { return std::make_reverse_iterator(begin()); }
245 
248 
250  ITYR_CHECK(i <= size());
251  return *(begin() + i);
252  }
253 
255  ITYR_CHECK(i <= size());
256  return *(begin() + i);
257  }
258 
260  check_range(i);
261  return (*this)[i];
262  }
263 
265  check_range(i);
266  return (*this)[i];
267  }
268 
269  reference front() { ITYR_CHECK(!empty()); return *begin(); }
270  reference back() { ITYR_CHECK(!empty()); return *(end() - 1); }
271  const_reference front() const { ITYR_CHECK(!empty()); return *begin(); }
272  const_reference back() const { ITYR_CHECK(!empty()); return *(end() - 1); }
273 
274  bool empty() const noexcept { return size() == 0; }
275 
276  void swap(this_t& other) noexcept {
277  using std::swap;
278  swap(opts_ , other.opts_ );
279  swap(begin_ , other.begin_ );
280  swap(end_ , other.end_ );
281  swap(reserved_end_, other.reserved_end_);
282  }
283 
284  void clear() {
285  if (!empty()) {
286  destruct_elems(begin(), end());
287  end_ = begin();
288  }
289  }
290 
291  void reserve(size_type new_cap) {
292  if (capacity() == 0 && new_cap > 0) {
293  begin_ = allocate_mem(new_cap);
294  end_ = begin_;
295  reserved_end_ = begin_ + new_cap;
296 
297  } else if (new_cap > capacity()) {
298  realloc_mem(new_cap);
299  }
300  }
301 
302  void resize(size_type count) {
303  resize_impl(count);
304  }
305 
306  void resize(size_type count, const value_type& value) {
307  resize_impl(count, value);
308  }
309 
310  void push_back(const value_type& value) {
311  push_back_impl(value);
312  }
313 
314  void push_back(value_type&& value) {
315  push_back_impl(std::move(value));
316  }
317 
318  template <typename... Args>
320  push_back_impl(std::forward<Args>(args)...);
321  return back();
322  }
323 
324  void pop_back() {
325  ITYR_CHECK(size() > 0);
326  root_exec_if_coll([&] {
327  auto cs = make_checkout(end() - 1, 1, checkout_mode::read_write);
328  std::destroy_at(&cs[0]);
329  });
330  --end_;
331  }
332 
333  iterator insert(const_iterator position, const T& x) {
334  return insert_one(position - cbegin(), x);
335  }
336 
337  iterator insert(const_iterator position, T&& x) {
338  return insert_one(position - cbegin(), std::move(x));
339  }
340 
341  iterator insert(const_iterator position, size_type n, const T& x) {
342  return insert_n(position - cbegin(), n, x);
343  }
344 
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>>>
348  iterator insert(const_iterator position, InputIterator first, InputIterator last) {
349  return insert_iter(position - cbegin(), first, last,
350  typename std::iterator_traits<InputIterator>::iterator_category{});
351  }
352 
353  iterator insert(const_iterator position, std::initializer_list<T> il) {
354  return insert_iter(position - cbegin(), il.begin(), il.end(),
355  std::random_access_iterator_tag{});
356  }
357 
358  template <typename... Args>
359  iterator emplace(const_iterator position, Args&&... args) {
360  return insert_iter(position - begin(), std::forward<Args>(args)...);
361  }
362 
363 private:
364  void destroy() {
365  if (begin() != nullptr) {
366  destruct_elems(begin(), end());
367  free_mem(begin(), capacity());
368  }
369  }
370 
371  void check_range(size_type i) const {
372  if (i >= size()) {
373  std::stringstream ss;
374  ss << "Global vector: Index " << i << " is out of range [0, " << size() << ").";
375  throw std::out_of_range(ss.str());
376  }
377  }
378 
379  size_type next_size(size_type least) const {
380  return std::max(least, size() * 2);
381  }
382 
383  pointer allocate_mem(size_type count) const {
384  if (opts_.collective) {
385  return coll_exec_if_coll([=] {
386  return ori::malloc_coll<T>(count);
387  });
388  } else {
389  return ori::malloc<T>(count);
390  }
391  }
392 
393  void free_mem(pointer p, size_type count) const {
394  if (opts_.collective) {
395  coll_exec_if_coll([=] {
396  ori::free_coll<T>(p);
397  });
398  } else {
399  ori::free<T>(p, count);
400  }
401  }
402 
403  template <typename Fn, typename... Args>
404  auto root_exec_if_coll(Fn&& fn, Args&&... args) const {
405  if (opts_.collective) {
406  if (ito::is_spmd()) {
407  return root_exec(std::forward<Fn>(fn), std::forward<Args>(args)...);
408  } else {
409  return std::forward<Fn>(fn)(std::forward<Args>(args)...);
410  }
411  } else {
412  return std::forward<Fn>(fn)(std::forward<Args>(args)...);
413  }
414  }
415 
416  template <typename Fn, typename... Args>
417  auto coll_exec_if_coll(Fn&& fn, Args&&... args) const {
418  if (opts_.collective) {
419  if (ito::is_spmd()) {
420  return std::forward<Fn>(fn)(std::forward<Args>(args)...);
421  } else if (ito::is_root()) {
422  return ito::coll_exec(std::forward<Fn>(fn), std::forward<Args>(args)...);
423  } else {
424  common::die("Collective operations for ityr::global_vector must be executed on the root thread or SPMD region.");
425  }
426  } else {
427  return std::forward<Fn>(fn)(std::forward<Args>(args)...);
428  }
429  }
430 
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;
436 
437  construct_elems(begin(), end(), args...);
438  }
439 
440  template <typename InputIterator>
441  void initialize_from_iter(InputIterator first, InputIterator last, std::input_iterator_tag) {
442  ITYR_CHECK(!opts_.collective);
444 
445  for (; first != last; ++first) {
446  push_back_impl(*first);
447  }
448  }
449 
450  template <typename ForwardIterator>
451  void initialize_from_iter(ForwardIterator first, ForwardIterator last, std::forward_iterator_tag) {
452  auto d = std::distance(first, last);
453 
454  if (d > 0) {
455  begin_ = allocate_mem(d);
456  end_ = begin_ + d;
457  reserved_end_ = begin_ + d;
458 
459  construct_elems_from_iter(first, last, begin());
460 
461  } else {
462  begin_ = end_ = reserved_end_ = nullptr;
463  }
464  }
465 
466  template <typename... Args>
467  void construct_elems(pointer b, pointer e, const Args&... args) const {
468  root_exec_if_coll([=, opts = opts_]() {
469  if (opts.parallel_construct) {
470  for_each(
471  execution::parallel_policy(opts.cutoff_count),
472  make_construct_iterator(b),
473  make_construct_iterator(e),
474  [=](T* p) { new (p) T(args...); });
475  } else {
476  for_each(
477  execution::sequenced_policy(opts.cutoff_count),
480  [&](T* p) { new (p) T(args...); });
481  }
482  });
483  }
484 
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) {
489  for_each(
490  execution::parallel_policy(opts.cutoff_count),
491  first,
492  last,
493  make_construct_iterator(b),
494  [](auto&& src, T* p) { new (p) T(std::forward<decltype(src)>(src)); });
495  } else {
496  for_each(
497  execution::sequenced_policy(opts.cutoff_count),
498  first,
499  last,
501  [](auto&& src, T* p) { new (p) T(std::forward<decltype(src)>(src)); });
502  }
503  });
504  }
505 
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) {
510  for_each(
511  execution::parallel_policy(opts.cutoff_count),
512  make_destruct_iterator(b),
513  make_destruct_iterator(e),
514  [](T* p) { std::destroy_at(p); });
515  } else {
516  for_each(
517  execution::sequenced_policy(opts.cutoff_count),
520  [](T* p) { std::destroy_at(p); });
521  }
522  });
523  }
524  }
525 
526  void realloc_mem(size_type count) {
527  pointer old_begin = begin_;
528  pointer old_end = end_;
529  size_type old_capacity = capacity();
530 
531  begin_ = allocate_mem(count);
532  end_ = begin_ + (old_end - old_begin);
533  reserved_end_ = begin_ + count;
534 
535  if (old_end - old_begin > 0) {
536  construct_elems_from_iter(
537  make_move_iterator(old_begin),
538  make_move_iterator(old_end),
539  begin());
540 
541  destruct_elems(old_begin, old_end);
542  }
543 
544  if (old_capacity > 0) {
545  free_mem(old_begin, old_capacity);
546  }
547  }
548 
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);
555  }
556  construct_elems(end(), begin() + count, args...);
557  end_ = begin() + count;
558 
559  } else if (count < size()) {
560  destruct_elems(begin() + count, end());
561  end_ = begin() + count;
562  }
563  }
564 
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);
570  }
571 
572  root_exec_if_coll([&] {
573  auto cs = make_checkout(end(), 1, checkout_mode::write);
574  new (&cs[0]) T(std::forward<Args>(args)...);
575  });
576 
577  ++end_;
578  }
579 
580  void make_space_for_insertion(size_type i, size_type n) {
581  ITYR_CHECK(i <= size());
582  ITYR_CHECK(n > 0);
583 
584  if (size() + n > capacity()) {
585  size_type new_cap = next_size(size() + n);
586  realloc_mem(new_cap);
587  }
588 
589  construct_elems(end(), end() + n);
590 
592  execution::sequenced_policy(opts_.cutoff_count),
593  begin() + i, end(), end() + n);
594  }
595 
596  template <typename... Args>
597  iterator insert_one(size_type i, Args&&... args) {
598  if (i == size()) {
599  push_back_impl(std::forward<Args>(args)...);
600  return begin() + i;
601  }
602 
603  make_space_for_insertion(i, 1);
604 
605  root_exec_if_coll([&] {
606  auto cs = make_checkout(begin() + i, 1, internal::dest_checkout_mode_t<T>{});
607  cs[0] = T(std::forward<Args>(args)...);
608  });
609 
610  ++end_;
611  return begin() + i;
612  }
613 
614  iterator insert_n(size_type i, size_type n, const value_type& value) {
615  if (n == 0) {
616  return begin() + i;
617  }
618 
619  make_space_for_insertion(i, n);
620 
621  root_exec_if_coll([&] {
622  fill(execution::sequenced_policy(opts_.cutoff_count),
623  begin() + i, begin() + i + n, value);
624  });
625 
626  end_ += n;
627  return begin() + i;
628  }
629 
630  template <typename InputIterator>
631  iterator insert_iter(size_type i, InputIterator first, InputIterator last, std::input_iterator_tag) {
632  size_type pos = i;
633  for (; first != last; ++first) {
634  insert_one(pos++, *first);
635  }
636  return begin() + i;
637  }
638 
639  template <typename ForwardIterator>
640  iterator insert_iter(size_type i, ForwardIterator first, ForwardIterator last, std::forward_iterator_tag) {
641  if (first == last) {
642  return begin() + i;
643  }
644 
645  size_type n = std::distance(first, last);
646  make_space_for_insertion(i, n);
647 
648  root_exec_if_coll([&] {
649  copy(execution::sequenced_policy(opts_.cutoff_count),
650  first, last, begin() + i);
651  });
652 
653  end_ += n;
654  return begin() + i;
655  }
656 
657  global_vector_options opts_;
658  pointer begin_ = nullptr;
659  pointer end_ = nullptr;
660  pointer reserved_end_ = nullptr;
661 };
662 
663 template <typename T>
664 inline void swap(global_vector<T>& v1, global_vector<T>& v2) noexcept {
665  v1.swap(v2);
666 }
667 
668 template <typename T>
669 bool operator==(const global_vector<T>& x, const global_vector<T>& y) {
670  return equal(
672  x.begin(), x.end(), y.begin(), y.end());
673 }
674 
675 template <typename T>
676 bool operator!=(const global_vector<T>& x, const global_vector<T>& y) {
677  return !(x == y);
678 }
679 
680 ITYR_TEST_CASE("[ityr::container::global_vector] test") {
681  ito::init();
682  ori::init();
683 
686 
687  long n = 10000;
688 
689  ITYR_SUBCASE("collective") {
690  global_vector<long> gv1(global_vector_options{true, 256},
691  count_iterator<long>(0),
692  count_iterator<long>(n));
693  ITYR_CHECK(!gv1.empty());
694  ITYR_CHECK(gv1.size() == std::size_t(n));
695  ITYR_CHECK(gv1.capacity() >= std::size_t(n));
696  root_exec([&] {
697  long count = reduce(
698  execution::parallel_policy(128),
699  gv1.begin(), gv1.end());
700  ITYR_CHECK(count == n * (n - 1) / 2);
701  });
702 
703  ITYR_SUBCASE("copy") {
704  global_vector<long> gv2 = gv1;
705  root_exec([&] {
706  for_each(
707  execution::parallel_policy(128),
710  [](long& i) { i *= 2; });
711 
712  long count1 = reduce(
713  execution::parallel_policy(128),
714  gv1.begin(), gv1.end());
715  ITYR_CHECK(count1 == n * (n - 1) / 2);
716 
717  long count2 = reduce(
718  execution::parallel_policy(128),
719  gv2.begin(), gv2.end());
720  ITYR_CHECK(count2 == n * (n - 1));
721 
722  // collective allocation on the root thread
723  global_vector<long> gv3 = gv1;
724 
725  for_each(
726  execution::parallel_policy(128),
730  [](long i, long j) { ITYR_CHECK(i == j); });
731  });
732  }
733 
734  ITYR_SUBCASE("move") {
735  global_vector<long> gv2 = std::move(gv1);
736  ITYR_CHECK(gv1.empty());
737  ITYR_CHECK(gv1.capacity() == 0);
738  root_exec([&] {
739  long count = reduce(
740  execution::parallel_policy(128),
741  gv2.begin(), gv2.end());
742  ITYR_CHECK(count == n * (n - 1) / 2);
743  });
744  }
745 
746  ITYR_SUBCASE("resize") {
747  gv1.resize(n * 10, 3);
748  root_exec([&] {
749  long count = reduce(
750  execution::parallel_policy(128),
751  gv1.begin(), gv1.end());
752  ITYR_CHECK(count == n * (n - 1) / 2 + (n * 9) * 3);
753  });
754  gv1.resize(n * 5);
755  root_exec([&] {
756  long count = reduce(
757  execution::parallel_policy(128),
758  gv1.begin(), gv1.end());
759  ITYR_CHECK(count == n * (n - 1) / 2 + (n * 4) * 3);
760  });
761  }
762 
763  ITYR_SUBCASE("clear") {
764  gv1.clear();
765  ITYR_CHECK(gv1.empty());
766  ITYR_CHECK(gv1.capacity() >= std::size_t(n));
767  }
768 
769  ITYR_SUBCASE("move-only elems") {
770  global_vector<common::move_only_t> gv2(global_vector_options{true, 256},
771  gv1.begin(),
772  gv1.end());
773  long next_size = gv2.capacity() * 2;
774  gv2.resize(next_size);
775  root_exec([&] {
776  long count = transform_reduce(
777  execution::parallel_policy(128),
778  gv2.begin(),
779  gv2.end(),
780  reducer::plus<long>{},
781  [](const common::move_only_t& mo) { return mo.value(); });
782 
783  ITYR_CHECK(count == n * (n - 1) / 2);
784  });
785  }
786  }
787 
788  ITYR_SUBCASE("noncollective") {
789  global_vector<global_vector<long>> gvs(global_vector_options{true, false, false});
790 
791  gvs.resize(n_ranks);
792 
793  global_vector<long> gv1;
794 
795  for (long i = 0; i < n; i++) {
796  gv1.push_back(i);
797  }
798 
799  gvs[my_rank] = std::move(gv1);
800 
801  root_exec([&]() {
802  auto check_sum = [&](long ans) {
803  long count = transform_reduce(
807  reducer::plus<long>{},
808  [&](auto&& gv_ref) {
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();
812  cs.checkin();
813  return reduce(execution::parallel_policy(128),
814  gv_begin, gv_end);
815  });
816 
817  ITYR_CHECK(count == ans);
818  };
819 
820  check_sum(n * (n - 1) / 2 * n_ranks);
821 
822  for_each(
826  [&](global_vector<long>& gv) {
827  for (long i = 0; i < 100; i++) {
828  gv.push_back(i);
829  }
830  for (long i = 0; i < 100; i++) {
831  gv.pop_back();
832  }
833  gv.resize(2 * n);
834  for_each(
835  execution::sequenced_policy(128),
836  count_iterator<long>(n),
837  count_iterator<long>(2 * n),
839  [](long i, long& x) { x = i; });
840  });
841 
842  check_sum((2 * n) * (2 * n - 1) / 2 * n_ranks);
843  });
844  }
845 
846  ITYR_SUBCASE("insert") {
847  root_exec([&]() {
848  global_vector<int> v1 = {1, 2, 3, 4, 5};
849  global_vector<int> v2 = {10, 20, 30};
850 
851  v1.insert(v1.begin() + 2, 0);
852  ITYR_CHECK(v1 == global_vector<int>({1, 2, 0, 3, 4, 5}));
853 
854  v1.insert(v1.end() - 1, 3, -1);
855  ITYR_CHECK(v1 == global_vector<int>({1, 2, 0, 3, 4, -1, -1, -1, 5}));
856 
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}));
859  });
860  }
861 
862  ITYR_SUBCASE("initializer list") {
863  root_exec([&]() {
864  global_vector<int> v = {1, 2, 3, 4, 5};
865 
866  int product = reduce(execution::par, v.begin(), v.end(), reducer::multiplies<int>{});
867  ITYR_CHECK(product == 120);
868 
869  v.insert(v.end(), {6, 7, 8});
870  ITYR_CHECK(v == global_vector<int>({1, 2, 3, 4, 5, 6, 7, 8}));
871  });
872  }
873 
874  ori::fini();
875  ito::fini();
876 }
877 
878 }
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