dist_array.h
Go to the documentation of this file.
1 /*
2  * This file is a part of TiledArray.
3  * Copyright (C) 2013 Virginia Tech
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program. If not, see <http://www.gnu.org/licenses/>.
17  *
18  */
19 
20 #ifndef TILEDARRAY_ARRAY_H__INCLUDED
21 #define TILEDARRAY_ARRAY_H__INCLUDED
22 
23 #include <cstdlib>
24 
25 #include <madness/world/parallel_archive.h>
26 
27 #include "TiledArray/array_impl.h"
32 #include "TiledArray/replicator.h"
36 #include "TiledArray/util/random.h"
37 
38 namespace TiledArray {
39 
40 // Forward declarations
41 template <typename, typename>
42 class Tensor;
43 namespace expressions {
44 template <typename, bool>
45 class TsrExpr;
46 } // namespace expressions
47 
49 
55 template <typename Tile = Tensor<double, Eigen::aligned_allocator<double>>,
56  typename Policy = DensePolicy>
57 class DistArray : public madness::archive::ParallelSerializableObject {
58  public:
63 
70 
75 
77  typedef
79  typedef typename impl_type::shape_type
81  typedef typename impl_type::range_type::index1_type
83  typedef typename impl_type::range_type::index
86  typedef typename impl_type::value_type value_type;
87  typedef
89  typedef typename impl_type::reference future;
90  typedef typename impl_type::reference reference;
91  typedef
93  typedef typename impl_type::iterator iterator;
94  typedef typename impl_type::const_iterator
96  typedef typename impl_type::pmap_interface
98 
103 
109  template <typename OtherTile>
110  using is_my_type = std::is_same<DistArray_, DistArray<OtherTile, Policy>>;
111 
112  template <typename OtherTile>
114  std::enable_if_t<not is_my_type<OtherTile>::value>;
115 
116  template <typename Index>
117  static constexpr bool is_integral_or_integral_range_v =
118  std::is_integral_v<Index> || detail::is_integral_range_v<Index>;
119 
120  template <typename Index>
122  std::enable_if_t<is_integral_or_integral_range_v<Index>>;
123 
124  template <typename Index>
125  using enable_if_is_integral = std::enable_if_t<std::is_integral_v<Index>>;
126 
127  template <typename Value>
128  static constexpr bool is_value_or_future_to_value_v =
129  std::is_same_v<std::decay_t<Value>, Future<value_type>> ||
130  std::is_same_v<std::decay_t<Value>, value_type>;
131 
132  private:
133  std::shared_ptr<impl_type> pimpl_;
134 
135  static madness::AtomicInt cleanup_counter_;
136 
138 
142  static void lazy_deleter(const impl_type* const pimpl) {
143  if (pimpl) {
144  if (madness::initialized()) {
145  World& world = pimpl->world();
146  const madness::uniqueidT id = pimpl->id();
147  cleanup_counter_++;
148 
149  try {
150  world.gop.lazy_sync(id, [pimpl]() {
151  delete pimpl;
152  DistArray_::cleanup_counter_--;
153  });
154  } catch (madness::MadnessException& e) {
155  fprintf(stderr,
156  "!! ERROR TiledArray: madness::MadnessException thrown in "
157  "Array::lazy_deleter().\n"
158  "%s\n"
159  "!! ERROR TiledArray: The exception has been absorbed.\n"
160  "!! ERROR TiledArray: rank=%i\n",
161  e.what(), world.rank());
162 
163  cleanup_counter_--;
164  delete pimpl;
165  } catch (std::exception& e) {
166  fprintf(stderr,
167  "!! ERROR TiledArray: std::exception thrown in "
168  "Array::lazy_deleter().\n"
169  "%s\n"
170  "!! ERROR TiledArray: The exception has been absorbed.\n"
171  "!! ERROR TiledArray: rank=%i\n",
172  e.what(), world.rank());
173 
174  cleanup_counter_--;
175  delete pimpl;
176  } catch (...) {
177  fprintf(stderr,
178  "!! ERROR TiledArray: An unknown exception was thrown in "
179  "Array::lazy_deleter().\n"
180  "!! ERROR TiledArray: The exception has been absorbed.\n"
181  "!! ERROR TiledArray: rank=%i\n",
182  world.rank());
183 
184  cleanup_counter_--;
185  delete pimpl;
186  }
187  } else {
188  delete pimpl;
189  }
190  }
191  }
192 
194 
199  static std::shared_ptr<impl_type> init(World& world,
200  const trange_type& trange,
201  const shape_type& shape,
202  std::shared_ptr<pmap_interface> pmap) {
203  // User level validation of input
204 
205  if (!pmap) {
206  // Construct a default process map
207  pmap = Policy::default_pmap(world, trange.tiles_range().volume());
208  } else {
209  // Validate the process map
210  TA_ASSERT(pmap->size() == trange.tiles_range().volume() &&
211  "Array::Array() -- The size of the process map is not "
212  "equal to the number of tiles in the TiledRange object.");
213  TA_ASSERT(
214  pmap->rank() == typename pmap_interface::size_type(world.rank()) &&
215  "Array::Array() -- The rank of the process map is not equal to that "
216  "of the world object.");
217  TA_ASSERT(
218  pmap->procs() == typename pmap_interface::size_type(world.size()) &&
219  "Array::Array() -- The number of processes in the process map is not "
220  "equal to that of the world object.");
221  }
222 
223  // Validate the shape
224  TA_ASSERT(!shape.empty() &&
225  "Array::Array() -- The shape is not initialized.");
226  TA_ASSERT(shape.validate(trange.tiles_range()) &&
227  "Array::Array() -- The range of the shape is not equal to "
228  "the tiles range.");
229 
230  return std::shared_ptr<impl_type>(new impl_type(world, trange, shape, pmap),
231  lazy_deleter);
232  }
233 
234  public:
236 
241 
242  DistArray() : pimpl_() {}
243 
245 
248  DistArray(const DistArray_& other) : pimpl_(other.pimpl_) {}
249 
251 
259  const std::shared_ptr<pmap_interface>& pmap =
260  std::shared_ptr<pmap_interface>())
261  : pimpl_(init(world, trange, shape_type(1, trange), pmap)) {}
262 
264 
273  const std::shared_ptr<pmap_interface>& pmap =
274  std::shared_ptr<pmap_interface>())
275  : pimpl_(init(world, trange, shape, pmap)) {}
276 
281 
302  template <typename T>
305 
306  template <typename T>
309 
310  template <typename T>
313 
314  template <typename T>
317 
318  template <typename T>
321 
322  template <typename T>
326 
331 
353  template <typename T>
356 
357  template <typename T>
360 
361  template <typename T>
364 
365  template <typename T>
368 
369  template <typename T>
372 
373  template <typename T>
377 
379 
384  template <typename OtherTile, typename = enable_if_not_my_type<OtherTile>>
385  explicit DistArray(const DistArray<OtherTile, Policy>& other) : pimpl_() {
386  *this = foreach<Tile>(other, [](Tile& result, const OtherTile& source) {
387  result = TiledArray::Cast<Tile, OtherTile>{}(source);
388  });
389  }
390 
392 
398  template <typename OtherTile, typename Op>
399  DistArray(const DistArray<OtherTile, Policy>& other, Op&& op) : pimpl_() {
400  *this = foreach<Tile>(other, std::forward<Op>(op));
401  }
402 
404 
409 
411 
413  DistArray_ clone() const { return TiledArray::clone(*this); }
414 
416 
418  std::shared_ptr<const impl_type> pimpl() const { return pimpl_; }
419 
421 
423  std::shared_ptr<impl_type> pimpl() { return pimpl_; }
424 
426 
428  std::weak_ptr<const impl_type> weak_pimpl() const { return pimpl_; }
429 
431 
433  std::weak_ptr<impl_type> weak_pimpl() { return pimpl_; }
434 
436 
444  static void wait_for_lazy_cleanup(World& world, const double = 60.0) {
445  try {
446  world.await([&]() { return (cleanup_counter_ == 0); }, true);
447  } catch (...) {
448  printf("%i: Array lazy cleanup timeout with %i pending cleanup(s)\n",
449  world.rank(), int(cleanup_counter_));
450  throw;
451  }
452  }
453 
455 
457  void wait_for_lazy_cleanup() const {
459  }
460 
462 
465  DistArray_& operator=(const DistArray_& other) {
466  pimpl_ = other.pimpl_;
467 
468  return *this;
469  }
470 
472 
477  madness::uniqueidT id() const { return impl_ref().id(); }
478 
480 
484  iterator begin() { return impl_ref().begin(); }
485 
487 
491  const_iterator begin() const { return impl_ref().cbegin(); }
492 
494 
498  iterator end() { return impl_ref().end(); }
499 
501 
505  const_iterator end() const { return impl_ref().cend(); }
506 
508 
522  template <typename Index,
523  typename = enable_if_is_integral_or_integral_range<Index>>
524  Future<value_type> find(const Index& i) const {
525  check_index(i);
526  return pimpl_->get(i);
527  }
528 
530 
542  template <typename Integer, typename = enable_if_is_integral<Integer>>
543  Future<value_type> find(const std::initializer_list<Integer>& i) const {
544  return find<std::initializer_list<Integer>>(i);
545  }
546 
548 
553  template <typename Index,
554  typename = std::enable_if_t<std::is_integral_v<Index> ||
555  detail::is_integral_range_v<Index>>>
556  const Future<value_type>& find_local(const Index& i) const {
557  check_local_index(i);
558  return pimpl_->get_local(i);
559  }
560 
562 
567  template <typename Integer,
568  typename = std::enable_if_t<(std::is_integral_v<Integer>)>>
570  const std::initializer_list<Integer>& i) const {
571  return find_local<std::initializer_list<Integer>>(i);
572  }
573 
575 
580  template <typename Index,
581  typename = std::enable_if_t<std::is_integral_v<Index> ||
582  detail::is_integral_range_v<Index>>>
583  Future<value_type>& find_local(const Index& i) {
584  check_local_index(i);
585  return pimpl_->get_local(i);
586  }
587 
589 
594  template <typename Integer,
595  typename = std::enable_if_t<(std::is_integral_v<Integer>)>>
596  Future<value_type>& find_local(const std::initializer_list<Integer>& i) {
597  return find_local<std::initializer_list<Integer>>(i);
598  }
599 
615  template <
616  typename Index, typename InIter,
617  typename = std::enable_if_t<is_integral_or_integral_range_v<Index> &&
619  void set(const Index& i, InIter first) {
620  check_index(i);
621  pimpl_->set(i, value_type(pimpl_->trange().make_tile_range(i), first));
622  }
623 
639  template <typename Integer, typename InIter,
640  typename = std::enable_if_t<(std::is_integral_v<Integer>)&&detail::
641  is_input_iterator<InIter>::value>>
642  typename std::enable_if<detail::is_input_iterator<InIter>::value>::type set(
643  const std::initializer_list<Integer>& i, InIter first) {
644  set<std::initializer_list<Integer>>(i, first);
645  }
646 
648 
666  template <typename Index,
667  typename = enable_if_is_integral_or_integral_range<Index>>
668  void set(const Index& i, const element_type& value = element_type()) {
669  check_index(i);
670  pimpl_->set(i, value_type(pimpl_->trange().make_tile_range(i), value));
671  }
672 
674 
692  template <typename Integer, typename = enable_if_is_integral<Integer>>
693  void set(const std::initializer_list<Integer>& i,
694  const element_type& value = element_type()) {
695  set<std::initializer_list<Integer>>(i, value);
696  }
697 
699 
712  template <
713  typename Index, typename Value,
714  typename = std::enable_if_t<(is_integral_or_integral_range_v<Index> &&
715  is_value_or_future_to_value_v<Value>)>>
716  void set(const Index& i, Value&& v) {
717  check_index(i);
718  pimpl_->set(i, std::forward<Value>(v));
719  }
720 
722 
734  template <
735  typename Index, typename Value,
736  typename = std::enable_if_t<
737  (std::is_integral_v<Index>)&&is_value_or_future_to_value_v<Value>>>
738  void set(const std::initializer_list<Index>& i, Value&& v) {
739  set<std::initializer_list<Index>>(i, std::forward<Value>(v));
740  }
741 
743 
750  void fill_local(const element_type& value = element_type(),
751  bool skip_set = false) {
752  init_tiles(
753  [value](const range_type& range) { return value_type(range, value); },
754  skip_set);
755  }
756 
758 
765  void fill(const element_type& value = numeric_type(), bool skip_set = false) {
766  fill_local(value, skip_set);
767  }
768 
790  template <typename T = element_type,
792  void fill_random(bool skip_set = false) {
794  [](const auto&) { return detail::MakeRandom<T>::generate_value(); });
795  }
796 
798 
833  template <typename Op>
834  void init_tiles(Op&& op, bool skip_set = false) {
835  // lifetime management of op depends on whether it is a lvalue ref (i.e. has
836  // an external owner) or an rvalue ref
837  // - if op is an lvalue ref: pass op to tasks
838  // - if op is an rvalue ref pass make_shared_function(op) to tasks
839  auto op_shared_handle = make_op_shared_handle(std::forward<Op>(op));
840 
841  auto it = impl_ref().pmap()->begin();
842  const auto end = pimpl_->pmap()->end();
843  for (; it != end; ++it) {
844  const auto& index = *it;
845  if (!pimpl_->is_zero(index)) {
846  if (skip_set) {
847  auto fut = find(index);
848  if (fut.probe()) continue;
849  }
850  Future<value_type> tile = pimpl_->world().taskq.add(
851  [pimpl = this->weak_pimpl(), index = ordinal_type(index),
852  op_shared_handle]() -> value_type {
853  auto pimpl_ptr = pimpl.lock();
854  if (pimpl_ptr)
855  return op_shared_handle(
856  pimpl_ptr->trange().make_tile_range(index));
857  else
858  return {};
859  });
860  set(index, tile);
861  }
862  }
863  }
864 
866 
889  template <typename Op>
890  void init_elements(Op&& op, bool skip_set = false) {
891  auto op_shared_handle = make_op_shared_handle(std::forward<Op>(op));
892  init_tiles(
893  [op = std::move(op_shared_handle)](
894  const TiledArray::Range& range) -> value_type {
895  // Initialize the tile with the given range object
896  Tile tile(range);
897 
898  // Initialize tile elements
899  for (auto& idx : range) tile[idx] = op(idx);
900 
901  return tile;
902  },
903  skip_set);
904  }
905 
907 
917  const trange_type& trange() const { return impl_ref().trange(); }
918 
920 
931  // TODO: uncomment [[deprecated("use DistArray::tiles_range()")]]
932  const range_type& range() const { return impl_ref().tiles_range(); }
933 
935 
937  const range_type& tiles_range() const { return impl_ref().tiles_range(); }
938 
940  [[deprecated("use DistArray::elements_range()")]] const typename trange_type::
941  range_type&
942  elements() const {
943  return elements_range();
944  }
945 
947 
958  const typename trange_type::range_type& elements_range() const {
959  return impl_ref().trange().elements_range();
960  }
961 
963 
972  auto size() const { return impl_ref().size(); }
973 
975 
981  const std::string& vars) const {
982  check_str_index(vars);
984  vars);
985  }
986 
988 
994  const std::string& vars) {
995  check_str_index(vars);
997  }
998 
1000  [[deprecated]] World& get_world() const { return world(); }
1001 
1003 
1007  World& world() const { return impl_ref().world(); }
1008 
1010  [[deprecated]] const std::shared_ptr<pmap_interface>& get_pmap() const {
1011  return pmap();
1012  }
1013 
1015 
1019  const std::shared_ptr<pmap_interface>& pmap() const {
1020  return impl_ref().pmap();
1021  }
1022 
1024 
1028  bool is_dense() const { return impl_ref().is_dense(); }
1029 
1031  [[deprecated]] const shape_type& get_shape() const { return shape(); }
1032 
1034 
1039  inline const shape_type& shape() const { return impl_ref().shape(); }
1040 
1042 
1056  template <typename Index,
1057  typename = enable_if_is_integral_or_integral_range<Index>>
1058  ProcessID owner(const Index& i) const {
1059  check_index(i);
1060  return pimpl_->owner(i);
1061  }
1062 
1064 
1077  template <typename Index, typename = enable_if_is_integral<Index>>
1078  ProcessID owner(const std::initializer_list<Index>& i) const {
1079  return owner<std::initializer_list<Index>>(i);
1080  }
1081 
1083 
1096  template <typename Index,
1097  typename = enable_if_is_integral_or_integral_range<Index>>
1098  bool is_local(const Index& i) const {
1099  check_index(i);
1100  return pimpl_->is_local(i);
1101  }
1102 
1104 
1116  template <typename Index, typename = enable_if_is_integral<Index>>
1117  bool is_local(const std::initializer_list<Index>& i) const {
1118  return is_local<std::initializer_list<Index>>(i);
1119  }
1120 
1122 
1135  template <typename Index,
1136  typename = enable_if_is_integral_or_integral_range<Index>>
1137  bool is_zero(const Index& i) const {
1138  check_index(i);
1139  return pimpl_->is_zero(i);
1140  }
1141 
1143 
1155  template <typename Index, typename = enable_if_is_integral<Index>>
1156  bool is_zero(const std::initializer_list<Index>& i) const {
1157  return is_zero<std::initializer_list<Index>>(i);
1158  }
1159 
1161 
1164  void swap(DistArray_& other) { std::swap(pimpl_, other.pimpl_); }
1165 
1170  if ((!impl_ref().pmap()->is_replicated()) && (world().size() > 1)) {
1171  // Construct a replicated array
1172  auto pmap = std::make_shared<detail::ReplicatedPmap>(world(), size());
1173  DistArray_ result = DistArray_(world(), trange(), shape(), pmap);
1174 
1175  // Create the replicator object that will do an all-to-all broadcast of
1176  // the local tile data.
1177  auto replicator =
1178  std::make_shared<detail::Replicator<DistArray_>>(*this, result);
1179 
1180  // Put the replicator pointer in the deferred cleanup object so it will
1181  // be deleted at the end of the next fence.
1182  TA_ASSERT(replicator.unique()); // Required for deferred_cleanup
1183  madness::detail::deferred_cleanup(world(), replicator);
1184 
1185  DistArray_::operator=(result);
1186  }
1187  }
1188 
1193 
1196  void truncate(
1197  typename shape_type::value_type thresh = shape_type::threshold()) {
1198  TiledArray::truncate(*this, thresh);
1199  }
1200 
1202 
1206  bool is_initialized() const { return static_cast<bool>(pimpl_); }
1207 
1209 
1213  explicit operator bool() const { return is_initialized(); }
1214 
1216 
1220  template <typename Archive,
1221  typename = std::enable_if_t<
1222  !Archive::is_parallel_archive &&
1224  void serialize(const Archive& ar) const {
1225  // serialize array type, world size, rank, and pmap type to be able
1226  // to ensure same data type and same data distribution expected
1227  ar& typeid(*this).hash_code() & world().size() & world().rank() & trange() &
1228  shape() & typeid(pmap().get()).hash_code();
1229  int64_t count = 0;
1230  for (auto it = begin(); it != end(); ++it) ++count;
1231  ar& count;
1232  for (auto it = begin(); it != end(); ++it) ar & it->get();
1233  }
1234 
1236 
1240  template <typename Archive,
1241  typename = std::enable_if_t<
1242  !Archive::is_parallel_archive &&
1244  void serialize(const Archive& ar) {
1246 
1247  std::size_t typeid_hash = 0l;
1248  ar& typeid_hash;
1249  if (typeid_hash != typeid(*this).hash_code())
1250  TA_EXCEPTION(
1251  "DistArray::serialize: source DistArray type != this DistArray type");
1252 
1253  ProcessID world_size = -1;
1254  ProcessID world_rank = -1;
1255  ar& world_size& world_rank;
1256  if (world_size != world.size() || world_rank != world.rank())
1257  TA_EXCEPTION(
1258  "DistArray::serialize: source DistArray world != this DistArray "
1259  "world");
1260 
1262  shape_type shape;
1263  ar& trange& shape;
1264 
1265  // use default pmap, ensure it's the same pmap used to serialize
1266  auto volume = trange.tiles_range().volume();
1268  size_t pmap_hash_code = 0;
1269  ar& pmap_hash_code;
1270  if (pmap_hash_code != typeid(pmap.get()).hash_code())
1271  TA_EXCEPTION(
1272  "DistArray::serialize: source DistArray pmap != this DistArray pmap");
1273  pimpl_.reset(
1274  new impl_type(world, std::move(trange), std::move(shape), pmap));
1275 
1276  int64_t count = 0;
1277  ar& count;
1278  for (auto it = begin(); it != end(); ++it, --count) {
1279  Tile tile;
1280  ar& tile;
1281  this->set(it.ordinal(), std::move(tile));
1282  }
1283  if (count != 0)
1284  TA_EXCEPTION(
1285  "DistArray::serialize: # of tiles in archive != # of tiles expected");
1286  }
1287 
1290 
1299  template <typename Archive>
1300  void load(World& world, Archive& ar) {
1301  auto me = world.rank();
1302  const Tag tag = world.mpi.unique_tag(); // for broadcasting metadata
1303 
1304  if (ar.dofence()) world.gop.fence();
1305 
1306  if (ar.is_io_node()) { // on each io node ...
1307 
1308  auto& localar = ar.local_archive();
1309 
1310  // make sure source data matches the expected type
1311  // TODO would be nice to be able to convert the data upon reading
1312  std::size_t typeid_hash = 0l;
1313  localar& typeid_hash;
1314  if (typeid_hash != typeid(*this).hash_code())
1315  TA_EXCEPTION(
1316  "DistArray::load: source DistArray type != this DistArray type");
1317 
1318  // make sure same number of clients for every I/O node
1319  int num_io_clients = 0;
1320  localar& num_io_clients;
1321  if (num_io_clients != ar.num_io_clients())
1322  TA_EXCEPTION("DistArray::load: invalid parallel archive");
1323 
1325  shape_type shape;
1326  localar& trange& shape;
1327 
1328  // send trange and shape to every client
1329  for (ProcessID p = 0; p < world.size(); ++p) {
1330  if (p != me && ar.io_node(p) == me) {
1331  world.mpi.Send(int(1), p, tag); // Tell client to expect the data
1332  madness::archive::MPIOutputArchive dest(world, p);
1333  dest& trange& shape;
1334  dest.flush();
1335  }
1336  }
1337 
1338  // use default pmap
1339  auto volume = trange.tiles_range().volume();
1341  pimpl_.reset(
1342  new impl_type(world, std::move(trange), std::move(shape), pmap));
1343 
1344  int64_t count = 0;
1345  localar& count;
1346  for (size_t ord = 0; ord != volume; ++ord) {
1347  if (!is_zero(ord)) {
1348  auto owner_rank = pmap->owner(ord);
1349  if (ar.io_node(owner_rank) == me) {
1350  Tile tile;
1351  localar& tile;
1352  this->set(ord, std::move(tile));
1353  --count;
1354  }
1355  }
1356  }
1357  if (count != 0)
1358  TA_EXCEPTION(
1359  "DistArray::load: # of tiles in archive != # of tiles expected");
1360  } else { // non-I/O node still needs to initialize metadata
1361 
1363  shape_type shape;
1364 
1365  ProcessID p = ar.my_io_node();
1366  int flag;
1367  world.mpi.Recv(flag, p, tag);
1368  TA_ASSERT(flag == 1);
1369  madness::archive::MPIInputArchive source(world, p);
1370  source& trange& shape;
1371 
1372  // use default pmap
1373  auto volume = trange.tiles_range().volume();
1375  pimpl_.reset(
1376  new impl_type(world, std::move(trange), std::move(shape), pmap));
1377  }
1378 
1379  if (ar.dofence()) world.gop.fence();
1380  }
1381 
1383 
1391  template <typename Archive>
1392  void store(Archive& ar) const {
1393  auto me = world().rank();
1394 
1395  if (ar.dofence()) world().gop.fence();
1396 
1397  if (ar.is_io_node()) { // on each io node ...
1398  auto& localar = ar.local_archive();
1399  // ... store metadata first ...
1400  localar& typeid(*this).hash_code() & ar.num_io_clients() & trange() &
1401  shape();
1402  // ... then loop over tiles and dump the data from ranks
1403  // assigned to this I/O node in order ...
1404  // for sanity check dump tile count assigned to this I/O node
1405  const auto volume = trange().tiles_range().volume();
1406  int64_t count = 0;
1407  for (size_t ord = 0; ord != volume; ++ord) {
1408  if (!is_zero(ord)) {
1409  const auto owner_rank = pmap()->owner(ord);
1410  if (ar.io_node(owner_rank) == me) {
1411  ++count;
1412  }
1413  }
1414  }
1415  localar& count;
1416  for (size_t ord = 0; ord != volume; ++ord) {
1417  if (!is_zero(ord)) {
1418  auto owner_rank = pmap()->owner(ord);
1419  if (ar.io_node(owner_rank) == me) localar& find(ord).get();
1420  }
1421  }
1422  } // am I an I/O node?
1423  if (ar.dofence()) world().gop.fence();
1424  }
1425 
1427 
1433  std::function<void(const impl_type&, int64_t)> notifier = {}) {
1434  impl_type::set_notifier_accessor() = notifier;
1435  }
1436 
1437  private:
1438  template <typename Index>
1439  std::enable_if_t<std::is_integral_v<Index>, void> check_index(
1440  const Index i) const {
1441  TA_ASSERT(
1442  impl_ref().tiles_range().includes(i) &&
1443  "The ordinal index used to access an array tile is out of range.");
1444  }
1445 
1446  template <typename Index>
1447  std::enable_if_t<detail::is_integral_range_v<Index>, void> check_index(
1448  const Index& i) const {
1449  TA_ASSERT(
1450  impl_ref().tiles_range().includes(i) &&
1451  "The coordinate index used to access an array tile is out of range.");
1452  }
1453 
1454  template <typename Index1>
1455  void check_index(const std::initializer_list<Index1>& i) const {
1456  check_index<std::initializer_list<Index1>>(i);
1457  }
1458 
1459  template <typename Index>
1460  std::enable_if_t<std::is_integral_v<Index>, void> check_local_index(
1461  const Index i) const {
1462  check_index(i);
1463  TA_ASSERT(pimpl_->is_local(i) // pimpl_ already checked
1464  &&
1465  "The ordinal index used to access an array tile is not local.");
1466  }
1467 
1468  template <typename Index>
1469  std::enable_if_t<detail::is_integral_range_v<Index>, void> check_local_index(
1470  const Index& i) const {
1471  check_index(i);
1472  TA_ASSERT(
1473  pimpl_->is_local(i) // pimpl_ already checked
1474  && "The coordinate index used to access an array tile is not local.");
1475  }
1476 
1477  template <typename Index1>
1478  void check_local_index(const std::initializer_list<Index1>& i) const {
1479  check_local_index<std::initializer_list<Index1>>(i);
1480  }
1481 
1489  void check_str_index(const std::string& vars) const {
1490 #if (TA_ASSERT_POLICY != TA_ASSERT_IGNORE)
1491  // Only check indices if the PIMPL is initialized (okay to not initialize
1492  // the RHS of an equation)
1493  if (!is_initialized()) return;
1494 
1495  constexpr bool is_tot = detail::is_tensor_of_tensor_v<value_type>;
1496  const auto rank = range().rank();
1497  // TODO: Make constexpr and use structured bindings when CUDA supports C++17
1498  if (is_tot) {
1499  // Make sure the index is capable of being interpreted as a ToT index
1501 
1502  // Rank of outer tiles must match number of outer indices
1503  // is_tot_index(vars) implies vars.find(';') < vars.size()
1504  TA_ASSERT(std::count(vars.begin(), vars.begin() + vars.find(';'), ',') +
1505  1ul ==
1506  rank);
1507 
1508  // Check inner index rank?
1509  } else {
1510  // Better not be a ToT index
1512 
1513  // Number of indices must match rank
1514  TA_ASSERT(std::count(vars.begin(), vars.end(), ',') + 1ul == rank);
1515  }
1516 #endif // NDEBUG
1517  }
1518 
1520  void assert_pimpl() const {
1521  TA_ASSERT(pimpl_ &&
1522  "The Array has not been initialized, likely reason: it was "
1523  "default constructed and used.");
1524  }
1525 
1535  auto& impl_ref() const {
1536  assert_pimpl();
1537  return *pimpl_;
1538  }
1539 
1549  auto& impl_ref() {
1550  assert_pimpl();
1551  return *pimpl_;
1552  }
1553 
1554 }; // class DistArray
1555 
1556 template <typename Tile, typename Policy>
1557 madness::AtomicInt DistArray<Tile, Policy>::cleanup_counter_;
1558 
1559 #ifndef TILEDARRAY_HEADER_ONLY
1560 
1561 extern template class DistArray<
1562  Tensor<double, Eigen::aligned_allocator<double>>, DensePolicy>;
1563 extern template class DistArray<Tensor<float, Eigen::aligned_allocator<float>>,
1564  DensePolicy>;
1565 extern template class DistArray<Tensor<int, Eigen::aligned_allocator<int>>,
1566  DensePolicy>;
1567 extern template class DistArray<Tensor<long, Eigen::aligned_allocator<long>>,
1568  DensePolicy>;
1569 // extern template
1570 // class DistArray<Tensor<std::complex<double>,
1571 // Eigen::aligned_allocator<std::complex<double> > >, DensePolicy>; extern
1572 // template class DistArray<Tensor<std::complex<float>,
1573 // Eigen::aligned_allocator<std::complex<float> > >, DensePolicy>
1574 
1575 extern template class DistArray<
1576  Tensor<double, Eigen::aligned_allocator<double>>, SparsePolicy>;
1577 extern template class DistArray<Tensor<float, Eigen::aligned_allocator<float>>,
1578  SparsePolicy>;
1579 extern template class DistArray<Tensor<int, Eigen::aligned_allocator<int>>,
1580  SparsePolicy>;
1581 extern template class DistArray<Tensor<long, Eigen::aligned_allocator<long>>,
1582  SparsePolicy>;
1583 // extern template
1584 // class DistArray<Tensor<std::complex<double>,
1585 // Eigen::aligned_allocator<std::complex<double> > >, SparsePolicy>; extern
1586 // template class DistArray<Tensor<std::complex<float>,
1587 // Eigen::aligned_allocator<std::complex<float> > >, SparsePolicy>;
1588 
1589 #endif // TILEDARRAY_HEADER_ONLY
1590 
1592 
1601 template <typename Tile, typename Policy>
1602 inline std::ostream& operator<<(std::ostream& os,
1603  const DistArray<Tile, Policy>& a) {
1604  if (a.world().rank() == 0) {
1605  for (std::size_t i = 0; i < a.size(); ++i)
1606  if (!a.is_zero(i)) {
1607  const typename DistArray<Tile, Policy>::value_type tile =
1608  a.find(i).get();
1609  os << i << ": " << tile << "\n";
1610  }
1611  }
1612  a.world().gop.fence();
1613  return os;
1614 }
1615 
1616 template <typename Tile, typename Policy>
1618  return a.trange().tiles_range().rank();
1619 }
1620 
1621 template <typename Tile, typename Policy>
1623  // this is the number of tiles
1624  if (a.size() > 0) // assuming dense shape
1625  return a.trange().elements_range().volume();
1626  return 0;
1627 }
1628 
1629 template <typename Tile, typename Policy>
1631  return a(detail::dummy_annotation(rank(a))).abs_min();
1632 }
1633 
1634 template <typename Tile, typename Policy>
1636  return a(detail::dummy_annotation(rank(a))).abs_max();
1637 }
1638 
1639 template <typename Tile, typename Policy>
1641  return (a(detail::dummy_annotation(rank(a)))
1643  .get();
1644 }
1645 
1646 template <typename Tile, typename Policy>
1648  const DistArray<Tile, Policy>& b) {
1649  return (a(detail::dummy_annotation(rank(a)))
1651  .get();
1652 }
1653 
1654 template <typename Tile, typename Policy>
1656  return a(detail::dummy_annotation(rank(a))).squared_norm();
1657 }
1658 
1659 template <typename Tile, typename Policy>
1661  return std::sqrt(squared_norm(a));
1662 }
1663 
1664 } // namespace TiledArray
1665 
1666 // serialization
1667 namespace madness {
1668 namespace archive {
1669 template <class Tile, class Policy>
1670 struct ArchiveLoadImpl<ParallelInputArchive,
1671  TiledArray::DistArray<Tile, Policy>> {
1672  static inline void load(const ParallelInputArchive& ar,
1674  x.load(*ar.get_world(), ar);
1675  }
1676 };
1677 
1678 template <class Tile, class Policy>
1679 struct ArchiveStoreImpl<ParallelOutputArchive,
1680  TiledArray::DistArray<Tile, Policy>> {
1681  static inline void store(const ParallelOutputArchive& ar,
1683  x.store(ar);
1684  }
1685 };
1686 } // namespace archive
1687 
1688 template <class Tile, class Policy>
1690  const std::string name) {
1691  archive::ParallelOutputArchive ar2(x.world(), name.c_str(), 1);
1692  ar2& x;
1693 }
1694 
1695 template <class Tile, class Policy>
1696 void load(TiledArray::DistArray<Tile, Policy>& x, const std::string name) {
1697  archive::ParallelInputArchive ar2(x.world(), name.c_str(), 1);
1698  ar2& x;
1699 }
1700 
1701 } // namespace madness
1702 
1703 #endif // TILEDARRAY_ARRAY_H__INCLUDED
const std::shared_ptr< pmap_interface > & get_pmap() const
Definition: dist_array.h:1010
auto norm2(const DistArray< Tile, Policy > &a)
Definition: dist_array.h:1660
static std::function< void(const ArrayImpl_ &, int64_t)> & set_notifier_accessor()
Definition: array_impl.h:630
impl_type::const_iterator const_iterator
Local tile const iterator.
Definition: dist_array.h:95
bool is_initialized() const
Check if the array is initialized.
Definition: dist_array.h:1206
Tensor implementation and base for other tensor implementation objects.
Definition: array_impl.h:410
impl_type::range_type::index1_type index1_type
1-index type
Definition: dist_array.h:82
static void store(const ParallelOutputArchive &ar, const TiledArray::DistArray< Tile, Policy > &x)
Definition: dist_array.h:1681
DistArray(World &world, detail::tensor4_il< T > il)
Definition: dist_array.h:315
std::enable_if_t< is_integral_or_integral_range_v< Index > > enable_if_is_integral_or_integral_range
Definition: dist_array.h:122
static void register_set_notifier(std::function< void(const impl_type &, int64_t)> notifier={})
Debugging/tracing instrumentation.
Definition: dist_array.h:1432
impl_type::value_type value_type
Tile type.
Definition: dist_array.h:86
TensorImpl_::ordinal_type ordinal_type
Ordinal type.
Definition: array_impl.h:415
::blas::Op Op
Definition: blas.h:46
std::string dummy_annotation(unsigned int n_outer_size, unsigned int n_inner_size=0)
Definition: annotation.h:35
void swap(DistArray_ &other)
Swap this array with other.
Definition: dist_array.h:1164
DistArray_ clone() const
Create a deep copy of this array.
Definition: dist_array.h:413
World & world() const
World accessor.
Definition: tensor_impl.h:175
TiledArray::expressions::TsrExpr< DistArray_, true > operator()(const std::string &vars)
Create a tensor expression.
Definition: dist_array.h:993
impl_type::reference reference
future type
Definition: dist_array.h:90
const Future< value_type > & find_local(const Index &i) const
Find local tile.
Definition: dist_array.h:556
impl_type::pmap_interface pmap_interface
Process map interface type.
Definition: dist_array.h:97
const_iterator end() const
End const iterator factory function.
Definition: dist_array.h:505
const_iterator begin() const
Begin const iterator factory function.
Definition: dist_array.h:491
TiledArray::expressions::TsrExpr< const DistArray_, true > operator()(const std::string &vars) const
Create a tensor expression.
Definition: dist_array.h:980
detail::numeric_type< Tile >::type numeric_type
Definition: dist_array.h:69
std::enable_if< detail::is_input_iterator< InIter >::value >::type set(const std::initializer_list< Integer > &i, InIter first)
Definition: dist_array.h:642
madness::uniqueidT id() const
Global object id.
Definition: dist_array.h:477
TensorImpl_::index1_type index1_type
1-index type
Definition: array_impl.h:414
DistArray_ & operator=(const DistArray_ &other)
Copy assignment.
Definition: dist_array.h:465
TensorImpl_::range_type range_type
Elements/tiles range type.
Definition: array_impl.h:421
void wait_for_lazy_cleanup() const
Wait for lazy tile cleanup.
Definition: dist_array.h:457
void swap(Bitset< B > &b0, Bitset< B > &b1)
Definition: bitset.h:565
auto inner_product(const DistArray< Tile, Policy > &a, const DistArray< Tile, Policy > &b)
Definition: dist_array.h:1647
std::shared_ptr< const impl_type > pimpl() const
Accessor for the (shared_ptr to) implementation object.
Definition: dist_array.h:418
DistArray(World &world, const trange_type &trange, detail::tensor4_il< T > il)
Definition: dist_array.h:366
Expression wrapper for array objects.
Definition: tsr_expr.h:83
DistArray()
Default constructor.
Definition: dist_array.h:242
impl_type::trange_type trange_type
Tile range type.
Definition: dist_array.h:76
Distributed tensor iterator.
Definition: array_impl.h:236
DistArray(World &world, const trange_type &trange, detail::tensor3_il< T > il)
Definition: dist_array.h:362
bool is_zero(const Index &i) const
Query for a zero tile.
Definition: tensor_impl.h:147
TensorImpl_::pmap_interface pmap_interface
process map interface type
Definition: array_impl.h:424
const range_type & tiles_range() const
Tile range accessor.
Definition: dist_array.h:937
Type trait for extracting the scalar type of tensors and arrays.
Definition: type_traits.h:744
void fill_local(const element_type &value=element_type(), bool skip_set=false)
Fill all local tiles with the specified value.
Definition: dist_array.h:750
void set(const Index &i, InIter first)
Definition: dist_array.h:619
std::initializer_list< T > vector_il
impl_type::const_reference const_reference
future type
Definition: dist_array.h:92
DistArray< Tile, Policy > DistArray_
This object's type.
Definition: dist_array.h:59
DistArray< Tile, Policy > clone(const DistArray< Tile, Policy > &arg)
Create a deep copy of an array.
Definition: clone.h:43
TensorImpl_::policy_type policy_type
Policy type for this object.
Definition: array_impl.h:417
Future< value_type > find(const std::initializer_list< Integer > &i) const
Find local or remote tile.
Definition: dist_array.h:543
void serialize(const Archive &ar)
deserialize local contents of a DistArray from an Archive object
Definition: dist_array.h:1244
auto make_op_shared_handle(Op &&op)
Definition: function.h:129
#define TA_EXCEPTION(m)
Definition: error.h:83
auto dot(const DistArray< Tile, Policy > &a, const DistArray< Tile, Policy > &b)
Definition: dist_array.h:1640
std::weak_ptr< impl_type > weak_pimpl()
Accessor for the (shared_ptr to) implementation object.
Definition: dist_array.h:433
const std::shared_ptr< pmap_interface > & pmap() const
Tensor process map accessor.
Definition: tensor_impl.h:89
void fill_random(bool skip_set=false)
Definition: dist_array.h:792
auto abs_min(const DistArray< Tile, Policy > &a)
Definition: dist_array.h:1630
impl_type::range_type range_type
Elements/tiles range type.
Definition: dist_array.h:78
auto rank(const DistArray< Tile, Policy > &a)
Definition: dist_array.h:1617
typename tensor_type::value_type value_type
value type
Definition: tile.h:89
const shape_type & get_shape() const
Definition: dist_array.h:1031
typename T::policy_type policy_t
Definition: type_traits.h:1180
static constexpr bool is_value_or_future_to_value_v
Definition: dist_array.h:128
iterator begin()
Begin iterator factory function.
Definition: dist_array.h:484
impl_type::eval_type eval_type
The tile evaluation type.
Definition: dist_array.h:88
std::initializer_list< tensor4_il< T > > tensor5_il
DistArray(const DistArray< OtherTile, Policy > &other, Op &&op)
Unary transform constructor.
Definition: dist_array.h:399
void init_elements(Op &&op, bool skip_set=false)
Initialize elements of local, non-zero tiles with a user provided functor.
Definition: dist_array.h:890
DistArray(World &world, detail::matrix_il< T > il)
Definition: dist_array.h:307
auto array_from_il(World &world, const TiledRange &trange, T &&il)
Converts an std::initializer_list into a tiled array.
bool is_local(const std::initializer_list< Index > &i) const
Check if the tile at index i is stored locally.
Definition: dist_array.h:1117
auto abs_max(const DistArray< Tile, Policy > &a)
Definition: dist_array.h:1635
Tile cast operation.
Definition: cast.h:168
DistArray(World &world, const trange_type &trange, detail::matrix_il< T > il)
Definition: dist_array.h:358
#define TA_ASSERT(EXPR,...)
Definition: error.h:39
World & get_default_world()
Definition: madness.h:90
static void wait_for_lazy_cleanup(World &world, const double=60.0)
Wait for lazy tile cleanup.
Definition: dist_array.h:444
bool is_tot_index(const std::string &idx)
Definition: annotation.h:160
ProcessID owner(const Index &i) const
Query a tile owner.
Definition: tensor_impl.h:122
void load(TiledArray::DistArray< Tile, Policy > &x, const std::string name)
Definition: dist_array.h:1696
auto size() const
Returns the number of tiles in the tensor.
Definition: dist_array.h:972
const trange_type & trange() const
Tiled range accessor.
Definition: dist_array.h:917
Tensor tile reference.
Definition: array_impl.h:49
DistArray(World &world, const trange_type &trange, detail::tensor5_il< T > il)
Definition: dist_array.h:370
Future< value_type > find(const Index &i) const
Find local or remote tile by index.
Definition: dist_array.h:524
auto squared_norm(const DistArray< Tile, Policy > &a)
Definition: dist_array.h:1655
std::initializer_list< tensor5_il< T > > tensor6_il
const shape_type & shape() const
Shape accessor.
Definition: dist_array.h:1039
impl_type::policy_type policy_type
Policy type.
Definition: dist_array.h:62
void set(const Index &i, Value &&value)
Set tile.
Definition: array_impl.h:551
const range_type & range() const
Tile range accessor.
Definition: dist_array.h:932
DistArray(World &world, const trange_type &trange, detail::vector_il< T > il)
Definition: dist_array.h:354
std::initializer_list< matrix_il< T > > tensor3_il
DistArray(World &world, detail::vector_il< T > il)
Definition: dist_array.h:303
DistArray(World &world, detail::tensor5_il< T > il)
Definition: dist_array.h:319
DistArray(World &world, const trange_type &trange, const shape_type &shape, const std::shared_ptr< pmap_interface > &pmap=std::shared_ptr< pmap_interface >())
Sparse array constructor.
Definition: dist_array.h:272
Forward declarations.
Definition: dist_array.h:57
std::weak_ptr< const impl_type > weak_pimpl() const
Accessor for the (weak_ptr to) implementation object.
Definition: dist_array.h:428
value_type::value_type element_type
Definition: dist_array.h:102
impl_type::iterator iterator
Local tile iterator.
Definition: dist_array.h:93
iterator end()
End iterator factory function.
Definition: dist_array.h:498
DistArray(World &world, const trange_type &trange, const std::shared_ptr< pmap_interface > &pmap=std::shared_ptr< pmap_interface >())
Dense array constructor.
Definition: dist_array.h:258
World & world() const
World accessor.
Definition: dist_array.h:1007
static constexpr bool is_integral_or_integral_range_v
Definition: dist_array.h:117
DistArray(World &world, detail::tensor3_il< T > il)
Definition: dist_array.h:311
const future & get_local(const Index &i) const
Local tile future accessor.
Definition: array_impl.h:496
void set(const std::initializer_list< Index > &i, Value &&v)
Set a tile directly using a future to a tile.
Definition: dist_array.h:738
bool is_local(const Index &i) const
Check if the tile at index i is stored locally.
Definition: dist_array.h:1098
World & get_world() const
Definition: dist_array.h:1000
std::ostream & operator<<(std::ostream &os, const DistArray< Tile, Policy > &a)
Add the tensor to an output stream.
Definition: dist_array.h:1602
impl_type::ordinal_type ordinal_type
Ordinal type.
Definition: dist_array.h:85
static ValueType generate_value()
Generates a random value of type ValueType.
Definition: random.h:94
void save(const TiledArray::DistArray< Tile, Policy > &x, const std::string name)
Definition: dist_array.h:1689
std::initializer_list< vector_il< T > > matrix_il
const trange_type::range_type & elements_range() const
Element range accessor.
Definition: dist_array.h:958
static void load(const ParallelInputArchive &ar, TiledArray::DistArray< Tile, Policy > &x)
Definition: dist_array.h:1672
void store(Archive &ar) const
Stores this array to an Archive object.
Definition: dist_array.h:1392
bool is_zero(const Index &i) const
Check for zero tiles.
Definition: dist_array.h:1137
std::enable_if_t< not is_my_type< OtherTile >::value > enable_if_not_my_type
Definition: dist_array.h:114
Future< value_type > & find_local(const std::initializer_list< Integer > &i)
Find local tile.
Definition: dist_array.h:596
TiledArray::detail::ArrayImpl< Tile, Policy > impl_type
The type of the PIMPL.
Definition: dist_array.h:61
bool is_zero(const std::initializer_list< Index > &i) const
Check for zero tiles.
Definition: dist_array.h:1156
impl_type::range_type::index index
Array coordinate index type.
Definition: dist_array.h:84
DistArray(World &world, const trange_type &trange, detail::tensor6_il< T > il)
Definition: dist_array.h:374
size_t volume(const DistArray< Tile, Policy > &a)
Definition: dist_array.h:1622
DistArray(const DistArray< OtherTile, Policy > &other)
converting copy constructor
Definition: dist_array.h:385
eval_trait< Tile >::type eval_type
The tile evaluation type.
Definition: array_impl.h:427
void set(const std::initializer_list< Integer > &i, const element_type &value=element_type())
Set every element of a tile to a specified value.
Definition: dist_array.h:693
void init_tiles(Op &&op, bool skip_set=false)
Initialize (local) tiles with a user provided functor.
Definition: dist_array.h:834
const trange_type::range_type & elements() const
Definition: dist_array.h:942
DistArray(World &world, detail::tensor6_il< T > il)
Definition: dist_array.h:323
Type trait for extracting the numeric type of tensors and arrays.
Definition: type_traits.h:709
std::shared_ptr< impl_type > pimpl()
Accessor for the (shared_ptr to) implementation object.
Definition: dist_array.h:423
constexpr bool is_replicated(World &world, const DenseShape &t)
Definition: dense_shape.h:386
std::initializer_list< tensor3_il< T > > tensor4_il
void serialize(const Archive &ar) const
serialize local contents of a DistArray to an Archive object
Definition: dist_array.h:1224
future get(const Index &i) const
Tile future accessor.
Definition: array_impl.h:470
std::enable_if_t< is_dense_v< Policy >, void > truncate(DistArray< Tile, Policy > &array, typename Policy::shape_type::value_type=0)
Truncate a dense Array.
Definition: truncate.h:46
Future< value_type > & find_local(const Index &i)
Find local tile.
Definition: dist_array.h:583
void fill(const element_type &value=numeric_type(), bool skip_set=false)
Fill all local tiles with the specified value.
Definition: dist_array.h:765
std::enable_if_t< can_make_random_v< T > > enable_if_can_make_random_t
Definition: random.h:77
bool initialized()
Definition: tiledarray.cpp:63
const trange_type & trange() const
Tiled range accessor.
Definition: tensor_impl.h:167
impl_type::reference future
Future of value_type.
Definition: dist_array.h:89
TensorImpl_::trange_type trange_type
Tiled range type for this object.
Definition: array_impl.h:419
detail::scalar_type< Tile >::type scalar_type
Definition: dist_array.h:74
bool is_dense() const
Check dense/sparse.
Definition: dist_array.h:1028
ProcessID owner(const Index &i) const
Tile ownership.
Definition: dist_array.h:1058
std::enable_if_t< std::is_integral_v< Index > > enable_if_is_integral
Definition: dist_array.h:125
const std::shared_ptr< pmap_interface > & pmap() const
Process map accessor.
Definition: dist_array.h:1019
void load(World &world, Archive &ar)
Definition: dist_array.h:1300
~DistArray()
Destructor.
Definition: dist_array.h:408
DistArray(const DistArray_ &other)
Copy constructor.
Definition: dist_array.h:248
void set(const Index &i, const element_type &value=element_type())
Set a tile and fill it using a value.
Definition: dist_array.h:668
TensorImpl_::shape_type shape_type
Shape type.
Definition: array_impl.h:422
An N-dimensional shallow copy wrapper for tile objects.
Definition: tile.h:82
bool is_local(const Index &i) const
Query for a locally owned tile.
Definition: tensor_impl.h:134
const Future< value_type > & find_local(const std::initializer_list< Integer > &i) const
Find local tile.
Definition: dist_array.h:569
impl_type::shape_type shape_type
Shape type for array tiling.
Definition: dist_array.h:80
void truncate(typename shape_type::value_type thresh=shape_type::threshold())
Definition: dist_array.h:1196
std::is_same< DistArray_, DistArray< OtherTile, Policy > > is_my_type
Definition: dist_array.h:110
void set(const Index &i, Value &&v)
Set a tile directly using a future to a tile.
Definition: dist_array.h:716
A (hyperrectangular) interval on , space of integer -indices.
Definition: range.h:46
ProcessID owner(const std::initializer_list< Index > &i) const
Tile ownership.
Definition: dist_array.h:1078