MADNESS 0.10.1
worlddc.h
Go to the documentation of this file.
1/*
2 This file is part of MADNESS.
3
4 Copyright (C) 2007,2010 Oak Ridge National Laboratory
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19
20 For more information please contact:
21
22 Robert J. Harrison
23 Oak Ridge National Laboratory
24 One Bethel Valley Road
25 P.O. Box 2008, MS-6367
26
27 email: harrisonrj@ornl.gov
28 tel: 865-241-3937
29 fax: 865-572-0680
30*/
31
32#ifndef MADNESS_WORLD_WORLDDC_H__INCLUDED
33#define MADNESS_WORLD_WORLDDC_H__INCLUDED
34
35/*!
36 \file worlddc.h
37 \brief Implements WorldContainer
38 \addtogroup worlddc
39 @{
40
41*/
42
43#include <functional>
44#include <set>
45#include <map>
46#include <vector>
47#include <algorithm>
48#include <unordered_set>
49
50
56
57namespace madness
58{
59
60 template <typename keyT, typename valueT, typename hashfunT>
61 class WorldContainer;
62
63 template <typename keyT, typename valueT, typename hashfunT>
64 class WorldContainerImpl;
65
66 template <typename keyT, typename valueT, typename hashfunT>
67 void swap(WorldContainer<keyT, valueT, hashfunT> &, WorldContainer<keyT, valueT, hashfunT> &);
68
69 template <typename keyT>
70 class WorldDCPmapInterface;
71
72 template <typename keyT>
74 {
75 public:
76 virtual std::size_t size() const = 0;
77 virtual void redistribute_phase1(const std::shared_ptr<WorldDCPmapInterface<keyT>> &newmap) = 0;
78 virtual void redistribute_phase2() = 0;
79 virtual void redistribute_phase3() = 0;
81 };
82
83 /// some introspection of how data is distributed
85 Distributed, ///< no replication of the container, the container is distributed over the world
86 RankReplicated, ///< replicate the container over all world ranks
87 NodeReplicated ///< replicate the container over all hosts (compute nodes), once per node,
88 ///< even if there are several ranks per node
89 };
90
91 template<typename T=long>
92 std::ostream& operator<<(std::ostream& os, const DistributionType type) {
93 if (type==DistributionType::Distributed) os << "Distributed";
94 if (type==DistributionType::RankReplicated) os << "RankReplicated";
95 if (type==DistributionType::NodeReplicated) os << "NodeReplicated";
96 return os;
97 }
98
99 template<typename T=long>
100 std::string to_string(const DistributionType type) {
101 std::stringstream ss; ss << type;
102 return ss.str();
103 }
104
105 template<typename T=long>
107 // to lower case
108 std::transform(type.begin(), type.end(), type.begin(), [](unsigned char c){ return std::tolower(c); });
109 if (type=="distributed") return Distributed;
110 if (type=="rankreplicated") return RankReplicated;
111 if (type=="nodereplicated") return NodeReplicated;
112 std::string msg="unknown distribution type:"+type;
113 MADNESS_EXCEPTION(msg.c_str(),1)
114 return Distributed;
115 }
116
117
118
119 /// Interface to be provided by any process map
120
121 /// NOTE: if the map is not distributed, but replicated, you must override the distribution_type() method.
122 /// \ingroup worlddc
123 template <typename keyT>
125 {
126 public:
128
129
130 private:
131 std::set<ptrT> ptrs;
132
133 public:
134 /// Maps key to processor
135
136 /// @param[in] key Key for container
137 /// @return Processor that logically owns the key
138 virtual ProcessID owner(const keyT &key) const = 0;
139
141
142 virtual void print() const {}
143
144 /// by default the map is distributed
146 {
147 return Distributed;
148 }
149
150 /// The one rank every key maps to on every process, or -1. Lets a cross-world
151 /// copy fetch from one owner instead of polling all ranks. Stronger than
152 /// WorldDCLocalPmap, whose owner is the calling rank.
153 virtual ProcessID single_owner() const
154 {
155 return -1;
156 }
157
158 /// Registers object for receipt of redistribute callbacks
159
160 /// @param[in] ptr Pointer to class derived from WorldDCRedistributedInterface
162 {
163 ptrs.insert(ptr);
164 }
165
166 /// Deregisters object for receipt of redistribute callbacks
167
168 /// @param[in] ptr Pointer to class derived from WorldDCRedistributedInterface
170 {
171 ptrs.erase(ptr);
172 }
173
174 /// Invoking this switches all registered objects from this process map to the new one
175
176 /// After invoking this routine all objects will be registered with the
177 /// new map and no objects will be registered in the current map.
178 /// @param[in] world The associated world
179 /// @param[in] newpmap The new process map
180 void redistribute(World &world, const std::shared_ptr<WorldDCPmapInterface<keyT>> &newpmap)
181 {
182 print_data_sizes(world, "before redistributing");
183 world.gop.fence();
184 for (typename std::set<ptrT>::iterator iter = ptrs.begin();
185 iter != ptrs.end();
186 ++iter)
187 {
188 (*iter)->redistribute_phase1(newpmap);
189 }
190 world.gop.fence();
191 for (typename std::set<ptrT>::iterator iter = ptrs.begin();
192 iter != ptrs.end();
193 ++iter)
194 {
195 (*iter)->redistribute_phase2();
196 newpmap->register_callback(*iter);
197 }
198 world.gop.fence();
199 for (typename std::set<ptrT>::iterator iter = ptrs.begin();
200 iter != ptrs.end();
201 ++iter)
202 {
203 (*iter)->redistribute_phase3();
204 }
205 world.gop.fence();
206 ptrs.clear();
207 newpmap->print_data_sizes(world, "after redistributing");
208 }
209
210 /// Counts global number of entries in all containers associated with this process map
211
212 /// Collective operation with global fence
213 std::size_t global_size(World &world) const
214 {
215 world.gop.fence();
216 std::size_t sum = local_size();
217 world.gop.sum(sum);
218 world.gop.fence();
219 return sum;
220 }
221
222 /// Counts local number of entries in all containers associated with this process map
223 std::size_t local_size() const
224 {
225 std::size_t sum = 0;
226 for (typename std::set<ptrT>::iterator iter = ptrs.begin(); iter != ptrs.end(); ++iter)
227 {
228 sum += (*iter)->size();
229 }
230 return sum;
231 }
232
233 /// Prints size info to std::cout
234
235 /// Collective operation with global fence
236 void print_data_sizes(World &world, const std::string msg = "") const
237 {
238 world.gop.fence();
239 std::size_t total = global_size(world);
240 std::vector<std::size_t> sizes(world.size());
241 sizes[world.rank()] = local_size();
242 world.gop.sum(&sizes[0], world.size());
243 if (world.rank() == 0)
244 {
245 madness::print("data distribution info", msg);
246 madness::print(" total: ", total);
247 std::cout << " procs: ";
248 for (int i = 0; i < world.size(); i++)
249 std::cout << sizes[i] << " ";
250 std::cout << std::endl;
251 }
252 world.gop.fence();
253 }
254 };
255
256 /// Default process map is "random" using madness::hash(key)
257
258 /// \ingroup worlddc
259 template <typename keyT, typename hashfunT = Hash<keyT>>
261 {
262 private:
263 const int nproc;
264 hashfunT hashfun;
265
266 public:
267 WorldDCDefaultPmap(World &world, const hashfunT &hf = hashfunT()) : nproc(world.mpi.nproc()),
268 hashfun(hf)
269 {
270 }
271
272 ProcessID owner(const keyT &key) const
273 {
274 if (nproc == 1)
275 return 0;
276 return hashfun(key) % nproc;
277 }
278 };
279
280 /// Local process map will always return the current process as owner
281
282 /// \ingroup worlddc
283 template <typename keyT, typename hashfunT = Hash<keyT>>
285 {
286 private:
288
289 public:
290 WorldDCLocalPmap(World &world) : me(world.rank()) {}
291 ProcessID owner(const keyT &key) const override
292 {
293 return me;
294 }
295
297 {
298 return RankReplicated;
299 }
300 };
301
302 /// Places every key on one fixed rank (all ranks agree on the owner).
303 ///
304 /// Moves a container's whole content onto one rank, so a cross-world copy is
305 /// a single fetch. Distribution type stays Distributed; see single_owner().
306 /// \ingroup worlddc
307 template <typename keyT>
309 {
310 private:
312
313 public:
315 ProcessID owner(const keyT & /*key*/) const override { return owner_; }
316 ProcessID single_owner() const override { return owner_; }
317 };
318
319 /// node-replicated map will return the lowest rank on the node as owner
320 ///
321 /// \ingroup worlddc
322 template <typename keyT, typename hashfunT = Hash<keyT>>
325
326 public:
327 /// ctor makes a map of all ranks to their owners (lowest rank on the host)
328 /// calls a fence
329 /// @param[in] world the associated world
330 explicit WorldDCNodeReplicatedPmap(World& world, const std::map<std::string,std::vector<long>> ranks_per_host) {
332 }
333
334 /// owner is the lowest rank on the node, same for all keys
335 ProcessID owner(const keyT &key) const override {
336 return myowner;
337 }
338
340 {
341 return NodeReplicated;
342 }
343 };
344
345 /// check distribution type of WorldContainer -- global communication
346 template <typename dcT>
348 {
349 // assume pmap distribution type is the correct result
350 World& world=dc.get_world();
351 auto result= dc.get_pmap()->distribution_type();
352
353 auto local_size=dc.size();
354 auto global_size=local_size;
355 world.gop.sum(global_size);
356
357 auto number_of_duplicates = [](const std::vector<hashT>& v) {
358 std::unordered_map<hashT, size_t> counts;
359 size_t duplicates = 0;
360 for (const auto& elem : v) {
361 if (++counts[elem] > 1) duplicates++;
362 }
363 return duplicates;
364 };
365
366 // collect all hash vales and determine the number of duplicates
367 std::vector<hashT> all_hashes(local_size);
368 const auto& hashfun=dc.get_hash();
369 int i=0;
370 for (auto it=dc.begin();it!=dc.end();++it,++i) all_hashes[i]=hashfun(it->first);
371 all_hashes=world.gop.concat0(all_hashes);
372 std::size_t ndup=number_of_duplicates(all_hashes);
373 world.gop.broadcast(ndup,0);
374 // print("rank, local, global, duplicates", world.rank(),local_size,global_size,ndup);
375
376 // consistency checks
377 if (result==Distributed) {
378 // all keys should exist only on one process
379 MADNESS_CHECK_THROW(ndup==0,"WorldDC inconsistent -- distributed has duplicates");
380 }
381 else if (result==RankReplicated) {
382 // all keys should exist on all processes
383 std::size_t nrank=world.size();
384 MADNESS_CHECK_THROW(global_size==nrank*local_size,"WorldDC inconsistent");
385 MADNESS_CHECK_THROW(ndup==local_size*(nrank-1),"WorldDC inconsistent - duplicates");
386 }
387 else if (result==NodeReplicated) {
388 // all keys should exist on all nodes, not on all ranks
389 auto ranks_per_host1=ranks_per_host(world);
390 std::vector<int> primary_ranks=primary_ranks_per_host(world,ranks_per_host1);
391 world.gop.broadcast_serializable(primary_ranks,0);
392 world.gop.fence();
393 print("primary_rank_per_host",primary_ranks);
394
395 std::size_t nnodes=primary_ranks.size();
396 bool is_primary=(std::find(primary_ranks.begin(),primary_ranks.end(),world.rank())!=primary_ranks.end());
397
398 if (is_primary) {
399 MADNESS_CHECK_THROW(global_size==(nnodes*local_size),"WorldDC inconsistent - global size");
400 MADNESS_CHECK_THROW(ndup==local_size*(nnodes-1),"WorldDC inconsistent - duplicates");
401 } else {
402 MADNESS_CHECK_THROW(local_size==0,"WorldDC inconsistent -- secondary");
403 }
404 }
405 return result;
406 }
407
408
409 /// Iterator for distributed container wraps the local iterator
410
411 /// \ingroup worlddc
412 template <class internal_iteratorT>
414 {
415 public:
416 typedef typename std::iterator_traits<internal_iteratorT>::iterator_category iterator_category;
417 typedef typename std::iterator_traits<internal_iteratorT>::value_type value_type;
418 typedef typename std::iterator_traits<internal_iteratorT>::difference_type difference_type;
419 typedef typename std::iterator_traits<internal_iteratorT>::pointer pointer;
420 typedef typename std::iterator_traits<internal_iteratorT>::reference reference;
421
422 private:
423 internal_iteratorT it; ///< Iterator from local container
424 // TODO: Convert this to a scoped pointer.
425 mutable value_type *value; ///< holds the remote values
426
427 public:
428 /// Default constructor makes a local uninitialized value
430 : it(), value(nullptr) {}
431
432 /// Initializes from a local iterator
433 explicit WorldContainerIterator(const internal_iteratorT &it)
434 : it(it), value(nullptr) {}
435
436 /// Initializes to cache a remote value
438 : it(), value(nullptr)
439 {
440 value = new value_type(v);
441 }
442
444 : it(), value(nullptr)
445 {
446 copy(other);
447 }
448
449 template <class iteratorT>
451 : it(), value(nullptr)
452 {
453 copy(other);
454 }
455
457 {
458 delete value;
459 }
460
461 /// Assignment
463 {
464 copy(other);
465 return *this;
466 }
467
468 /// Determines if two iterators are identical
469 bool operator==(const WorldContainerIterator &other) const
470 {
471 return (((!is_cached()) && (!other.is_cached())) && it == other.it) ||
472 ((is_cached() && other.is_cached()) && value->first == other.value->first);
473 }
474
475 /// Determines if two iterators are different
476 bool operator!=(const WorldContainerIterator &other) const
477 {
478 return !(*this == other);
479 }
480
481 /// Pre-increment of an iterator (i.e., ++it) --- \em local iterators only
482
483 /// Trying to increment a remote iterator will throw
485 {
487 ++it;
488 return *this;
489 }
490
492 {
495 ++it;
496 return result;
497 }
498
499 /// Iterators dereference to std::pair<const keyT,valueT>
501 {
502 return (is_cached() ? value : it.operator->());
503 }
504
505 /// Iterators dereference to std::pair<const keyT,valueT>
507 {
508 return (is_cached() ? *value : *it);
509 }
510
511 /// Private: (or should be) Returns iterator of internal container
512 const internal_iteratorT &get_internal_iterator() const
513 {
514 return it;
515 }
516
517 /// Returns true if this is non-local or cached value
518 bool is_cached() const
519 {
520 return value != nullptr;
521 }
522
523 template <typename Archive>
524 void serialize(const Archive &)
525 {
526 MADNESS_EXCEPTION("Serializing DC iterator ... why?", false);
527 }
528
529 private:
530 template <class iteratorT>
532
533 template <class iteratorT>
535 {
536 if (static_cast<const void *>(this) != static_cast<const void *>(&other))
537 {
538 delete value;
539 if (other.is_cached())
540 {
541 value = new value_type(*other.value);
542 it = internal_iteratorT();
543 }
544 else
545 {
546 it = other.it;
547 value = nullptr;
548 }
549 }
550 }
551 };
552
553 /// Internal implementation of distributed container to facilitate shallow copy
554
555 /// \ingroup worlddc
556 template <typename keyT, typename valueT, typename hashfunT>
558 : public WorldObject<WorldContainerImpl<keyT, valueT, hashfunT>>,
560#ifndef MADNESS_DISABLE_SHARED_FROM_THIS
561 ,
562 public std::enable_shared_from_this<WorldContainerImpl<keyT, valueT, hashfunT>>
563#endif // MADNESS_DISABLE_SHARED_FROM_THIS
564 {
565 public:
566 typedef typename std::pair<const keyT, valueT> pairT;
567 typedef const pairT const_pairT;
569
571
572 // typedef WorldObject< WorldContainerImpl<keyT, valueT, hashfunT> > worldobjT;
573
582
583 friend class WorldContainer<keyT, valueT, hashfunT>;
584
585 // template <typename containerT, typename datumT>
586 // inline
587 // static
588 // typename containerT::iterator replace(containerT& c, const datumT& d) {
589 // std::pair<typename containerT::iterator,bool> p = c.insert(d);
590 // if (!p.second) p.first->second = d.second; // Who's on first?
591 // return p.first;
592 // }
593
594 private:
595 WorldContainerImpl(); // Inhibit default constructor
596
597 std::shared_ptr<WorldDCPmapInterface<keyT>> pmap; ///< Function/class to map from keys to owning process
598 const ProcessID me; ///< My MPI rank
599 internal_containerT local; ///< Locally owned data
600 std::vector<keyT> *move_list; ///< Tempoary used to record data that needs redistributing
601 std::map<ProcessID, std::vector<keyT>> coalesced_move_; ///< Temporary: keys to move, bucketed by destination (coalesced redistribute)
602
603 /// Handles find request
604 void find_handler(ProcessID requestor, const keyT &key, const RemoteReference<FutureImpl<iterator>> &ref)
605 {
607 if (r == local.end())
608 {
609 // print("find_handler: failure:", key);
610 this->send(requestor, &implT::find_failure_handler, ref);
611 }
612 else
613 {
614 // print("find_handler: success:", key, r->first, r->second);
615 this->send(requestor, &implT::find_success_handler, ref, *r);
616 }
617 }
618
619 /// Handles successful find response
621 {
622 FutureImpl<iterator> *f = ref.get();
623 f->set(iterator(datum));
624 // print("find_success_handler: success:", datum.first, datum.second, f->get()->first, f->get()->second);
625 // Todo: Look at this again.
626 // ref.reset(); // Matching inc() in find() where ref was made
627 }
628
629 /// Handles unsuccessful find response
631 {
632 FutureImpl<iterator> *f = ref.get();
633 f->set(end());
634 // print("find_failure_handler");
635 // Todo: Look at this again.
636 // ref.reset(); // Matching inc() in find() where ref was made
637 }
638
639 public:
641 const std::shared_ptr<WorldDCPmapInterface<keyT>> &pm,
642 const hashfunT &hf)
643 : WorldObject<WorldContainerImpl<keyT, valueT, hashfunT>>(world), pmap(pm), me(world.mpi.rank()), local(5011, hf)
644 {
645 pmap->register_callback(this);
646 }
647
649 {
650 pmap->deregister_callback(this);
651 }
652
653 const std::shared_ptr<WorldDCPmapInterface<keyT>> &get_pmap() const
654 {
655 return pmap;
656 }
657
658 std::shared_ptr<WorldDCPmapInterface<keyT>> &get_pmap()
659 {
660 return pmap;
661 }
662
664 {
665 pmap->deregister_callback(this);
666 pmap.reset(new WorldDCLocalPmap<keyT>(this->get_world()));
667 pmap->register_callback(this);
668 }
669
670 /// replicates this WorldContainer on all ProcessIDs and generates a
671 /// ProcessMap where all nodes are local
672 void replicate(bool fence) {
673 World &world = this->get_world();
674 pmap->deregister_callback(this);
676 pmap->register_callback(this);
677
679 if (fence) world.gop.fence();
680 }
681
682 /// replicates this WorldContainer on all hosts and generates a
683 /// ProcessMap where all nodes are host-local (not rank-local)
684 /// will always fence
685 void replicate_on_hosts(bool fence) {
686 MADNESS_CHECK(fence);
687
688 /// print in rank-order
689// auto oprint = [&](World& world, auto &&... args) {
690// world.gop.fence();
691// for (int r=0; r<world.size(); ++r) {
692// if (r==world.rank()) {
693// std::cout << "rank " << world.rank() << ": ";
694// print(std::forward<decltype(args)>(args)...);
695// }
696// world.gop.fence();
697// }
698// };
699
700 World &world = this->get_world();
701
702 // find primary ranks per host (lowest rank on each host)
703 auto ranks_per_host1=ranks_per_host(world);
704 std::vector<int> primary_ranks=primary_ranks_per_host(world,ranks_per_host1);
705 world.gop.broadcast_serializable(primary_ranks,0);
706 world.gop.fence();
707
708// auto sizes =[&](std::string msg) {
709// world.gop.fence();
710// auto local_size=size();
711// auto global_size=local_size;
712// world.gop.sum(global_size);
713// oprint(world,"rank, local, global",msg, world.rank(),local_size,global_size);
714// world.gop.fence();
715// };
716
717 // change pmap to replicated
718 pmap->deregister_callback(this);
720 pmap->register_callback(this);
721
722 // shortcut: replace pmap and return
723 if (world.size()==1) {
724 // change pmap to node replicated
725 pmap->deregister_callback(this);
726 pmap.reset(new WorldDCNodeReplicatedPmap<keyT>(world,ranks_per_host1));
727 pmap->register_callback(this);
728 return;
729 }
730 world.gop.fence();
731
732 // get a list of all other ranks that are not primary
733 std::vector<int> secondary_ranks;
734 for (int r=0; r<world.size(); ++r) {
735 if (std::find(primary_ranks.begin(),primary_ranks.end(),r)==primary_ranks.end())
736 secondary_ranks.push_back(r);
737 }
738
739 // phase 1: for all ranks send data to the lowest rank on host
740
741 // step 1-2: send data to lowest rank on host (which will become the owner)
742 long myowner = lowest_rank_on_host_of_rank(ranks_per_host1, world.rank());
743 // oprint(world,"my owner, size:", myowner,size());
744 if (world.rank() != myowner) {
745 // send data to myowner
746 for (auto it = begin(); it != end(); ++it) {
747 keyT key = it->first;
748 valueT value = it->second;
749 this->send(myowner,&implT::insert,pairT(key,value));
750 // insert(pairT(key,value)); // this won't work with LocalPmap
751 }
752 // remove all local data after sending
753 // clear();
754 }
755 // need a fence here to make sure send is finished
756 world.gop.fence();
757 // sizes("after step 1, before clear");
758 // world.gop.fence();
759 if (world.rank()!=myowner) clear();
760 world.gop.fence();
761 // sizes("after step 1");
762
763 // change pmap to replicated
764 pmap->deregister_callback(this);
765 pmap.reset(new WorldDCNodeReplicatedPmap<keyT>(world,ranks_per_host1));
766 pmap->register_callback(this);
767
768 // check if this rank is in the primary list
769 bool i_am_in_primary_list=world.rank()==myowner;
770 if (i_am_in_primary_list) {
771
772 // step 2-1: create a world with only the primary ranks and replicate there (see test_world.cc)
773
774 SafeMPI::Group primary_group = world.mpi.comm().Get_group().Incl(primary_ranks.size(), &primary_ranks[0]);
775 SafeMPI::Intracomm comm_primary = world.mpi.comm().Create(primary_group);
776 // step 2-2: replicate in the primary world
777 {
778 World world_primary(comm_primary);
779 // auto ranks_per_host1=ranks_per_host(world_primary);
780 // if (world_primary.rank()==0) {
781 // print("host/rank map in primary world:");
782 // for (auto& p : ranks_per_host1) print(p.first, p.second);
783 // }
784
785 world_primary.gop.fence(); // this fence seems necessary, why??
786 do_replicate(world_primary);
787 world_primary.gop.fence();
788 }
789 } else {
790 // need this to avoid deadlock in MPI_Comm_create (why??)
791 SafeMPI::Group secondary_group = world.mpi.comm().Get_group().Incl(secondary_ranks.size(), &secondary_ranks[0]);
792 SafeMPI::Intracomm comm_secondary = world.mpi.comm().Create(secondary_group);
793 }
794
795 // phase 3: done
796 if (fence) world.gop.fence();
797 // validate_distribution_type(*this);
798 }
799
801 for (ProcessID rank = 0; rank < world.size(); rank++)
802 {
803 if (rank == world.rank())
804 {
805 std::size_t sz = size();
807
808 for (auto it = begin(); it != end(); ++it)
809 {
810 keyT key = it->first;
811 valueT value = it->second;
813 world.gop.broadcast_serializable(value, rank);
814 }
815 }
816 else
817 {
818 size_t sz = 0;
820 for (size_t i = 0; i < sz; i++)
821 {
822 keyT key{};
823 valueT value{};
825 world.gop.broadcast_serializable(value, rank);
826 insert(pairT(key, value));
827 }
828 }
829 }
830 }
831
832 const hashfunT &get_hash() const { return local.get_hash(); }
833
834 bool is_local(const keyT &key) const
835 {
836 return owner(key) == me;
837 }
838
839 ProcessID owner(const keyT &key) const
840 {
841 return pmap->owner(key);
842 }
843
844 bool probe(const keyT &key) const
845 {
846 ProcessID dest = owner(key);
847 if (dest == me)
848 return local.find(key) != local.end();
849 else
850 return false;
851 }
852
853 std::size_t size() const
854 {
855 return local.size();
856 }
857
858 void insert(const pairT &datum)
859 {
860 ProcessID dest = owner(datum.first);
861 if (dest == me)
862 {
863 // Was using iterator ... try accessor ?????
864 accessor acc;
865 // N.B. key might already exist if want to simply replace
866 [[maybe_unused]] auto inserted = local.insert(acc, datum.first);
867 acc->second = datum.second;
868 }
869 else
870 {
871 // Must be send (not task) for sequential consistency (and relies on single-threaded remote server)
872 this->send(dest, &implT::insert, datum);
873 }
874 }
875
876 bool insert_acc(accessor &acc, const keyT &key)
877 {
878 MADNESS_ASSERT(owner(key) == me);
879 return local.insert(acc, key);
880 }
881
882 bool insert_const_acc(const_accessor &acc, const keyT &key)
883 {
884 MADNESS_ASSERT(owner(key) == me);
885 return local.insert(acc, key);
886 }
887
888 /// AM target of the coalesced redistribute: bulk-insert boxes this rank owns
889 /// under the already-adopted new pmap. Keys are disjoint from those this rank
890 /// is concurrently erasing (their new owner != me), so per-bucket locking
891 /// suffices. See redistribute_coalesced_phase2.
892 void insert_batch(const std::vector<pairT> &boxes)
893 {
894 for (const pairT &kv : boxes)
895 {
896 accessor acc;
897 [[maybe_unused]] auto inserted = local.insert(acc, kv.first);
898 acc->second = kv.second;
899 }
900 }
901
902 void clear()
903 {
904 local.clear();
905 }
906
907 void erase(const keyT &key)
908 {
909 ProcessID dest = owner(key);
910 if (dest == me)
911 {
912 [[maybe_unused]] auto erased = local.try_erase(key);
913 MADNESS_ASSERT(erased);
914 }
915 else
916 {
917 void (implT::*eraser)(const keyT &) = &implT::erase;
918 this->send(dest, eraser, key);
919 }
920 }
921
922 template <typename InIter>
923 void erase(InIter it)
924 {
925 MADNESS_ASSERT(!it.is_cached());
926 MADNESS_ASSERT(it != end());
927 erase(it->first);
928 }
929
930 template <typename InIter>
931 void erase(InIter first, InIter last)
932 {
933 InIter it = first;
934 do
935 {
936 first++;
937 erase(it->first);
938 it = first;
939 } while (first != last);
940 }
941
943 {
944 return iterator(local.begin());
945 }
946
948 {
949 return const_iterator(local.begin());
950 }
951
953 {
954 return iterator(local.end());
955 }
956
958 {
959 return const_iterator(local.end());
960 }
961
963 {
964 // Ugliness here to avoid replicating find() and
965 // associated handlers for const. Assumption is that
966 // const and non-const iterators are identical except for
967 // const attribute ... at some point probably need to do
968 // the right thing.
969 Future<iterator> r = const_cast<implT *>(this)->find(key);
970 return *(Future<const_iterator> *)(&r);
971 }
972
974 {
975 ProcessID dest = owner(key);
976 if (dest == me)
977 {
978 return Future<iterator>(iterator(local.find(key)));
979 }
980 else
981 {
982 Future<iterator> result;
983 this->send(dest, &implT::find_handler, me, key, result.remote_ref(this->get_world()));
984 return result;
985 }
986 }
987
988 bool find(accessor &acc, const keyT &key)
989 {
990 if (owner(key) != me)
991 return false;
992 return local.find(acc, key);
993 }
994
995 bool find(const_accessor &acc, const keyT &key) const
996 {
997 if (owner(key) != me)
998 return false;
999 return local.find(acc, key);
1000 }
1001
1002 // Used to forward call to item member function
1003 template <typename memfunT>
1004 MEMFUN_RETURNT(memfunT)
1005 itemfun(const keyT &key, memfunT memfun)
1006 {
1007 accessor acc;
1008 // N.B. key may already exist, this is just to ensure lock is held by acc
1009 [[maybe_unused]] auto inserted = local.insert(acc, key);
1010 return (acc->second.*memfun)();
1011 }
1012
1013 // Used to forward call to item member function
1014 template <typename memfunT, typename arg1T>
1015 MEMFUN_RETURNT(memfunT)
1016 itemfun(const keyT &key, memfunT memfun, const arg1T &arg1)
1017 {
1018 accessor acc;
1019 // N.B. key may already exist, this is just to ensure lock is held by acc
1020 [[maybe_unused]] auto inserted = local.insert(acc, key);
1021 return (acc->second.*memfun)(arg1);
1022 }
1023
1024 // Used to forward call to item member function
1025 template <typename memfunT, typename arg1T, typename arg2T>
1026 MEMFUN_RETURNT(memfunT)
1027 itemfun(const keyT &key, memfunT memfun, const arg1T &arg1, const arg2T &arg2)
1028 {
1029 accessor acc;
1030 // N.B. key may already exist, this is just to ensure lock is held by acc
1031 [[maybe_unused]] auto inserted = local.insert(acc, key);
1032 return (acc->second.*memfun)(arg1, arg2);
1033 }
1034
1035 // Used to forward call to item member function
1036 template <typename memfunT, typename arg1T, typename arg2T, typename arg3T>
1037 MEMFUN_RETURNT(memfunT)
1038 itemfun(const keyT &key, memfunT memfun, const arg1T &arg1, const arg2T &arg2, const arg3T &arg3)
1039 {
1040 accessor acc;
1041 // N.B. key may already exist, this is just to ensure lock is held by acc
1042 [[maybe_unused]] auto inserted = local.insert(acc, key);
1043 return (acc->second.*memfun)(arg1, arg2, arg3);
1044 }
1045
1046 // Used to forward call to item member function
1047 template <typename memfunT, typename arg1T, typename arg2T, typename arg3T, typename arg4T>
1048 MEMFUN_RETURNT(memfunT)
1049 itemfun(const keyT &key, memfunT memfun, const arg1T &arg1, const arg2T &arg2, const arg3T &arg3, const arg4T &arg4)
1050 {
1051 accessor acc;
1052 // N.B. key may already exist, this is just to ensure lock is held by acc
1053 [[maybe_unused]] auto inserted = local.insert(acc, key);
1054 return (acc->second.*memfun)(arg1, arg2, arg3, arg4);
1055 }
1056
1057 // Used to forward call to item member function
1058 template <typename memfunT, typename arg1T, typename arg2T, typename arg3T, typename arg4T, typename arg5T>
1059 MEMFUN_RETURNT(memfunT)
1060 itemfun(const keyT &key, memfunT memfun, const arg1T &arg1, const arg2T &arg2, const arg3T &arg3, const arg4T &arg4, const arg5T &arg5)
1061 {
1062 accessor acc;
1063 // N.B. key may already exist, this is just to ensure lock is held by acc
1064 [[maybe_unused]] auto inserted = local.insert(acc, key);
1065 return (acc->second.*memfun)(arg1, arg2, arg3, arg4, arg5);
1066 }
1067
1068 // Used to forward call to item member function
1069 template <typename memfunT, typename arg1T, typename arg2T, typename arg3T, typename arg4T, typename arg5T, typename arg6T>
1070 MEMFUN_RETURNT(memfunT)
1071 itemfun(const keyT &key, memfunT memfun, const arg1T &arg1, const arg2T &arg2, const arg3T &arg3, const arg4T &arg4, const arg5T &arg5, const arg6T &arg6)
1072 {
1073 accessor acc;
1074 // N.B. key may already exist, this is just to ensure lock is held by acc
1075 [[maybe_unused]] auto inserted = local.insert(acc, key);
1076 return (acc->second.*memfun)(arg1, arg2, arg3, arg4, arg5, arg6);
1077 }
1078
1079 // Used to forward call to item member function
1080 template <typename memfunT, typename arg1T, typename arg2T, typename arg3T, typename arg4T, typename arg5T, typename arg6T, typename arg7T>
1081 MEMFUN_RETURNT(memfunT)
1082 itemfun(const keyT &key, memfunT memfun, const arg1T &arg1, const arg2T &arg2, const arg3T &arg3,
1083 const arg4T &arg4, const arg5T &arg5, const arg6T &arg6, const arg7T &arg7)
1084 {
1085 accessor acc;
1086 // N.B. key may already exist, this is just to ensure lock is held by acc
1087 [[maybe_unused]] auto inserted = local.insert(acc, key);
1088 return (acc->second.*memfun)(arg1, arg2, arg3, arg4, arg5, arg6, arg7);
1089 }
1090
1091 // First phase of redistributions changes pmap and makes list of stuff to move
1092 void redistribute_phase1(const std::shared_ptr<WorldDCPmapInterface<keyT>> &newpmap)
1093 {
1094 pmap = newpmap;
1095 move_list = new std::vector<keyT>();
1096 for (typename internal_containerT::iterator iter = local.begin(); iter != local.end(); ++iter)
1097 {
1098 if (owner(iter->first) != me)
1099 move_list->push_back(iter->first);
1100 }
1101 }
1102
1103 struct P2Op
1104 {
1108 P2Op(const P2Op &p) : impl(p.impl) {}
1109 bool operator()(typename rangeT::iterator &iterator) const
1110 {
1111 typename internal_containerT::iterator iter = impl->local.find(*iterator);
1112 MADNESS_ASSERT(iter != impl->local.end());
1113
1114 // impl->insert(*iter);
1115 impl->task(impl->owner(*iterator), &implT::insert, *iter);
1116
1117 impl->local.erase(iter); // delete local copy of the data
1118 return true;
1119 }
1120 };
1121
1122 // Second phase moves data
1124 {
1125 this->get_world().taskq.for_each(typename P2Op::rangeT(move_list->begin(), move_list->end()), P2Op(this));
1126 // std::vector<keyT>& mvlist = *move_list;
1127 // for (unsigned int i=0; i<move_list->size(); ++i) {
1128 // typename internal_containerT::iterator iter = local.find(mvlist[i]);
1129 // MADNESS_ASSERT(iter != local.end());
1130 // insert(*iter);
1131 // local.erase(iter);
1132 // }
1133 // delete move_list;
1134 }
1135
1136 // Third phase cleans up
1138 {
1139 delete move_list;
1140 }
1141
1142 // --- Coalesced redistribute: like redistribute_phase1/2, but phase2 sends ONE
1143 // bulk AM per (destination, chunk) instead of one AM per box. The caller owns
1144 // the fences: fence, phase1 on all containers, fence, phase2, fence. The middle
1145 // fence is REQUIRED -- phase1 iterates the ConcurrentHashMap and needs a
1146 // quiescent window; phase2 tolerates concurrent insert_batch (disjoint keys).
1147
1148 /// phase1: adopt newpmap (callback swap as in replicate()) and bucket the keys
1149 /// to move by destination. Quiescent window required.
1150 void redistribute_coalesced_phase1(const std::shared_ptr<WorldDCPmapInterface<keyT>> &newpmap)
1151 {
1152 pmap->deregister_callback(this);
1153 pmap = newpmap;
1154 pmap->register_callback(this);
1155 coalesced_move_.clear();
1156 for (typename internal_containerT::iterator iter = local.begin(); iter != local.end(); ++iter)
1157 {
1158 ProcessID d = owner(iter->first); // uses the new pmap
1159 if (d != me)
1160 coalesced_move_[d].push_back(iter->first);
1161 }
1162 }
1163
1164 /// phase2: per destination, chunk the key list (at most cap_boxes per chunk),
1165 /// erase each box after copying it into the batch, send one insert_batch AM
1166 /// per chunk.
1167 void redistribute_coalesced_phase2(std::size_t cap_boxes, bool rotate)
1168 {
1169 if (cap_boxes == 0) cap_boxes = 1;
1170 std::vector<ProcessID> dsts;
1171 dsts.reserve(coalesced_move_.size());
1172 for (const auto &kv : coalesced_move_) dsts.push_back(kv.first);
1173 // rotate: destinations > me first, so ranks don't all hammer dst 0 at once
1174 if (rotate)
1175 std::stable_partition(dsts.begin(), dsts.end(),
1176 [this](ProcessID d) { return d > me; });
1177 for (ProcessID d : dsts)
1178 {
1179 const std::vector<keyT> &keys = coalesced_move_[d];
1180 std::vector<pairT> batch;
1181 batch.reserve(std::min(cap_boxes, keys.size()));
1182 for (std::size_t i = 0; i < keys.size(); ++i)
1183 {
1184 typename internal_containerT::iterator iter = local.find(keys[i]);
1185 if (iter != local.end())
1186 {
1187 batch.push_back(pairT(keys[i], iter->second));
1188 local.erase(iter); // delete local copy of the data
1189 }
1190 if (batch.size() >= cap_boxes || i + 1 == keys.size())
1191 {
1192 if (!batch.empty())
1193 {
1194 this->task(d, &implT::insert_batch, batch); // one bulk AM per chunk
1195 batch.clear();
1196 }
1197 }
1198 }
1199 }
1200 coalesced_move_.clear();
1201 }
1202 };
1203
1204 /// Makes a distributed container with specified attributes
1205
1206 /// \ingroup worlddc
1207 ///
1208 /// There is no communication or syncronization associated with
1209 /// making a new container, but every process must invoke the
1210 /// constructor for each container in the same order. This is so
1211 /// that we can assign each container a unique ID without any
1212 /// communication. Since remotely invoked operations may start
1213 /// happening before local construction, messages on not yet
1214 /// constructed containers are buffered pending construction.
1215 ///
1216 /// Similarly, when a container is destroyed, the actual
1217 /// destruction is deferred until a synchronization point
1218 /// (world.gop.fence()) in order to eliminate the need to fence
1219 /// before destroying every container.
1220 ///
1221 /// The distribution of data between processes is controlled by
1222 /// the process map (Pmap) class. The default is uniform
1223 /// hashing based upon a strong (Bob Jenkins, lookup3) bytewise
1224 /// hash of the key.
1225 ///
1226 /// All operations, including constructors and destructors, are
1227 /// non-blocking and return immediately. If communication occurs
1228 /// it is asynchronous, otherwise operations are local.
1229 template <typename keyT, typename valueT, typename hashfunT = Hash<keyT>>
1231 {
1232 public:
1233 // access keyT and valueT types for serialization
1237 typedef typename implT::pairT pairT;
1238 typedef typename implT::iterator iterator;
1239 typedef typename implT::const_iterator const_iterator;
1240 typedef typename implT::accessor accessor;
1241 typedef typename implT::const_accessor const_accessor;
1244
1245 private:
1246 std::shared_ptr<implT> p;
1247
1248 inline void check_initialized() const
1249 {
1251 }
1252
1253 public:
1254 /// Makes an uninitialized container (no communication)
1255
1256 /// The container is useless until assigned to from a fully
1257 /// constructed container. There is no need to worry about
1258 /// default constructors being executed in order.
1260 : p()
1261 {
1262 }
1263
1264 /// Makes an initialized, empty container with default data distribution (no communication)
1265
1266 /// A unique ID is associated with every distributed container
1267 /// within a world. In order to avoid synchronization when
1268 /// making a container, we have to assume that all processes
1269 /// execute this constructor in the same order (does not apply
1270 /// to the non-initializing, default constructor).
1271 WorldContainer(World &world, bool do_pending = true, const hashfunT &hf = hashfunT())
1272 : p(new implT(world,
1273 std::shared_ptr<WorldDCPmapInterface<keyT>>(new WorldDCDefaultPmap<keyT, hashfunT>(world, hf)),
1274 hf))
1275 {
1276 if (do_pending)
1277 p->process_pending();
1278 }
1279
1280 /// Makes an initialized, empty container (no communication)
1281
1282 /// A unique ID is associated with every distributed container
1283 /// within a world. In order to avoid synchronization when
1284 /// making a container, we have to assume that all processes
1285 /// execute this constructor in the same order (does not apply
1286 /// to the non-initializing, default constructor).
1288 const std::shared_ptr<WorldDCPmapInterface<keyT>> &pmap,
1289 bool do_pending = true,
1290 const hashfunT &hf = hashfunT())
1291 : p(new implT(world, pmap, hf))
1292 {
1293 if (do_pending)
1294 p->process_pending();
1295 }
1296
1297 /// Copy constructor is shallow (no communication)
1298
1299 /// The copy refers to exactly the same container as other
1300 /// which must be initialized.
1302 : p(other.p)
1303 {
1305 }
1306
1307 /// Assignment is shallow (no communication)
1308
1309 /// The copy refers to exactly the same container as other
1310 /// which must be initialized.
1312 {
1313 if (this != &other)
1314 {
1315 other.check_initialized();
1316 p = other.p;
1317 }
1318 return *this;
1319 }
1320
1321 /// return the way data is distributed
1323 if (!p) MADNESS_EXCEPTION("Uninitialized container", false);
1324 return p->get_pmap()->distribution_type();
1325 }
1326
1327 bool is_distributed() const {
1329 }
1330
1331 bool is_replicated() const {
1333 }
1334
1335 bool is_host_replicated() const {
1337 }
1338
1339 /// Returns the world associated with this container
1341 {
1343 return p->get_world();
1344 }
1345
1346 std::shared_ptr<WorldDCPmapInterface<keyT>> &get_impl()
1347 {
1349 return p;
1350 }
1351
1352 /// replicates this WorldContainer on all ProcessIDs
1353 void replicate(bool fence = true)
1354 {
1355 p->replicate(fence);
1356 }
1357
1358 /// replicates this WorldContainer on all hosts (one PID per host)
1359 void replicate_on_hosts(bool fence = true)
1360 {
1361 p->replicate_on_hosts(fence);
1362 }
1363
1364 /// Coalesced redistribute, phase 1: adopt newpmap, bucket the move list.
1365 /// Caller fences before (quiescent window).
1366 void redistribute_coalesced_phase1(const std::shared_ptr<WorldDCPmapInterface<keyT>> &newpmap)
1367 {
1369 p->redistribute_coalesced_phase1(newpmap);
1370 }
1371
1372 /// Coalesced redistribute, phase 2: one bulk AM per (destination, chunk of at
1373 /// most cap_boxes), erase-after-copy. Caller fences after; rotate staggers
1374 /// destinations to reduce incast.
1375 void redistribute_coalesced_phase2(std::size_t cap_boxes, bool rotate = true)
1376 {
1378 p->redistribute_coalesced_phase2(cap_boxes, rotate);
1379 }
1380
1381 /// Inserts/replaces key+value pair (non-blocking communication if key not local)
1382 void replace(const pairT &datum)
1383 {
1385 p->insert(datum);
1386 }
1387
1388 /// Inserts/replaces key+value pair (non-blocking communication if key not local)
1389 void replace(const keyT &key, const valueT &value)
1390 {
1391 replace(pairT(key, value));
1392 }
1393
1394 /// Write access to LOCAL value by key. Returns true if found, false otherwise (always false for remote).
1395 bool find(accessor &acc, const keyT &key)
1396 {
1398 return p->find(acc, key);
1399 }
1400
1401 /// Read access to LOCAL value by key. Returns true if found, false otherwise (always false for remote).
1402 bool find(const_accessor &acc, const keyT &key) const
1403 {
1405 return p->find(acc, key);
1406 }
1407
1408 /// Write access to LOCAL value by key. Returns true if inserted, false if already exists (throws if remote)
1409 bool insert(accessor &acc, const keyT &key)
1410 {
1412 return p->insert_acc(acc, key);
1413 }
1414
1415 /// Read access to LOCAL value by key. Returns true if inserted, false if already exists (throws if remote)
1416 bool insert(const_accessor &acc, const keyT &key)
1417 {
1419 return p->insert_acc(acc, key);
1420 }
1421
1422 /// Inserts pairs (non-blocking communication if key(s) not local)
1423 template <typename input_iterator>
1424 void replace(input_iterator &start, input_iterator &end)
1425 {
1427 using std::placeholders::_1;
1428 std::for_each(start, end, std::bind(this, std::mem_fn(&containerT::insert), _1));
1429 }
1430
1431 /// Returns true if local data is immediately available (no communication)
1432 bool probe(const keyT &key) const
1433 {
1435 return p->probe(key);
1436 }
1437
1438 /// Returns processor that logically owns key (no communication)
1439
1440 /// Local remapping may have changed its physical location, but all
1441 /// operations should forward correctly.
1442 inline ProcessID owner(const keyT &key) const
1443 {
1445 return p->owner(key);
1446 }
1447
1448 /// Returns true if the key maps to the local processor (no communication)
1449 bool is_local(const keyT &key) const
1450 {
1452 return p->is_local(key);
1453 }
1454
1455 /// Returns a future iterator (non-blocking communication if key not local)
1456
1457 /// Like an std::map an iterator "points" to an std::pair<const keyT,valueT>.
1458 ///
1459 /// Refer to Future for info on how to avoid blocking.
1461 { //
1463 return p->find(key);
1464 }
1465
1466 /// Returns a future iterator (non-blocking communication if key not local)
1467
1468 /// Like an std::map an iterator "points" to an std::pair<const keyT,valueT>.
1469 ///
1470 /// Refer to Future for info on how to avoid blocking.
1472 {
1474 return const_cast<const implT *>(p.get())->find(key);
1475 }
1476
1477 /// Returns an iterator to the beginning of the \em local data (no communication)
1479 {
1481 return p->begin();
1482 }
1483
1484 /// Returns an iterator to the beginning of the \em local data (no communication)
1486 {
1488 return const_cast<const implT *>(p.get())->begin();
1489 }
1490
1491 /// Returns an iterator past the end of the \em local data (no communication)
1493 {
1495 return p->end();
1496 }
1497
1498 /// Returns an iterator past the end of the \em local data (no communication)
1500 {
1502 return const_cast<const implT *>(p.get())->end();
1503 }
1504
1505 /// Erases entry from container (non-blocking comm if remote)
1506
1507 /// Missing keys are quietly ignored.
1508 ///
1509 /// Note that erasing an entry may invalidate iterators on the
1510 /// remote end. This is just the same as what happens when
1511 /// using STL iterators on an STL container in a sequential
1512 /// algorithm.
1513 void erase(const keyT &key)
1514 {
1516 p->erase(key);
1517 }
1518
1519 /// Erases entry corresponding to \em local iterator (no communication)
1520 void erase(const iterator &it)
1521 {
1523 p->erase(it);
1524 }
1525
1526 /// Erases range defined by \em local iterators (no communication)
1527 void erase(const iterator &start, const iterator &finish)
1528 {
1530 p->erase(start, finish);
1531 }
1532
1533 /// Clears all \em local data (no communication)
1534
1535 /// Invalidates all iterators
1536 void clear()
1537 {
1539 p->clear();
1540 }
1541
1542 /// Returns the number of \em local entries (no communication)
1543 std::size_t size() const
1544 {
1546 return p->size();
1547 }
1548
1549 /// Returns shared pointer to the process mapping
1550 inline const std::shared_ptr<WorldDCPmapInterface<keyT>> &get_pmap() const
1551 {
1553 return p->get_pmap();
1554 }
1555
1556 /// Returns shared pointer to the process mapping
1558 {
1559 p->reset_pmap_to_local();
1560 }
1561
1562 /// Returns a reference to the hashing functor
1563 const hashfunT &get_hash() const
1564 {
1566 return p->get_hash();
1567 }
1568
1569 /// Process pending messages
1570
1571 /// If the constructor was given \c do_pending=false then you
1572 /// \em must invoke this routine in order to process both
1573 /// prior and future messages.
1574 inline void process_pending()
1575 {
1577 p->process_pending();
1578 }
1579
1580 /// Sends message "resultT memfun()" to item (non-blocking comm if remote)
1581
1582 /// If item does not exist it is made with the default constructor.
1583 ///
1584 /// Future arguments must be ready for remote messages.
1585 ///
1586 /// Returns a future result (Future<void> may be ignored).
1587 ///
1588 /// The method executes with a write lock on the item.
1589 template <typename memfunT>
1590 Future<MEMFUN_RETURNT(memfunT)>
1591 send(const keyT &key, memfunT memfun)
1592 {
1594 MEMFUN_RETURNT(memfunT)
1595 (implT::*itemfun)(const keyT &, memfunT) = &implT::template itemfun<memfunT>;
1596 return p->send(owner(key), itemfun, key, memfun);
1597 }
1598
1599 /// Sends message "resultT memfun(arg1T)" to item (non-blocking comm if remote)
1600
1601 /// If item does not exist it is made with the default constructor.
1602 ///
1603 /// Future arguments must be ready for remote messages.
1604 ///
1605 /// Returns a future result (Future<void> may be ignored).
1606 ///
1607 /// The method executes with a write lock on the item.
1608 template <typename memfunT, typename arg1T>
1610 send(const keyT &key, const memfunT &memfun, const arg1T &arg1)
1611 {
1613 // To work around bug in g++ 4.3.* use static cast as alternative mechanism to force type deduction
1614 MEMFUN_RETURNT(memfunT)
1615 (implT::*itemfun)(const keyT &, memfunT, const arg1T &) = &implT::template itemfun<memfunT, arg1T>;
1616 return p->send(owner(key), itemfun, key, memfun, arg1);
1617 /*return p->send(owner(key),
1618 static_cast<MEMFUN_RETURNT(memfunT)(implT::*)(const keyT&, memfunT, const arg1T&)>(&implT:: template itemfun<memfunT,arg1T>),
1619 key, memfun, arg1);*/
1620 }
1621
1622 /// Sends message "resultT memfun(arg1T,arg2T)" to item (non-blocking comm if remote)
1623
1624 /// If item does not exist it is made with the default constructor.
1625 ///
1626 /// Future arguments must be ready for both local and remote messages.
1627 ///
1628 /// Returns a future result (Future<void> may be ignored).
1629 ///
1630 /// The method executes with a write lock on the item.
1631 template <typename memfunT, typename arg1T, typename arg2T>
1633 send(const keyT &key, memfunT memfun, const arg1T &arg1, const arg2T &arg2)
1634 {
1636 // To work around bug in g++ 4.3.* use static cast as alternative mechanism to force type deduction
1637 MEMFUN_RETURNT(memfunT)
1638 (implT::*itemfun)(const keyT &, memfunT, const arg1T &, const arg2T &) = &implT::template itemfun<memfunT, arg1T, arg2T>;
1639 return p->send(owner(key), itemfun, key, memfun, arg1, arg2);
1640 /*return p->send(owner(key),
1641 static_cast<MEMFUN_RETURNT(memfunT)(implT::*)(const keyT&, memfunT, const arg1T&, const arg2T&)>(&implT:: template itemfun<memfunT,arg1T,arg2T>), key, memfun, arg1, arg2);*/
1642 }
1643
1644 /// Sends message "resultT memfun(arg1T,arg2T,arg3T)" to item (non-blocking comm if remote)
1645
1646 /// If item does not exist it is made with the default constructor.
1647 ///
1648 /// Future arguments must be ready for both local and remote messages.
1649 ///
1650 /// Returns a future result (Future<void> may be ignored).
1651 ///
1652 /// The method executes with a write lock on the item.
1653 template <typename memfunT, typename arg1T, typename arg2T, typename arg3T>
1655 send(const keyT &key, memfunT memfun, const arg1T &arg1, const arg2T &arg2, const arg3T &arg3)
1656 {
1658 MEMFUN_RETURNT(memfunT)
1659 (implT::*itemfun)(const keyT &, memfunT, const arg1T &, const arg2T &, const arg3T &) = &implT::template itemfun<memfunT, arg1T, arg2T, arg3T>;
1660 return p->send(owner(key), itemfun, key, memfun, arg1, arg2, arg3);
1661 }
1662
1663 /// Sends message "resultT memfun(arg1T,arg2T,arg3T,arg4T)" to item (non-blocking comm if remote)
1664
1665 /// If item does not exist it is made with the default constructor.
1666 ///
1667 /// Future arguments must be ready for both local and remote messages.
1668 ///
1669 /// Returns a future result (Future<void> may be ignored).
1670 ///
1671 /// The method executes with a write lock on the item.
1672 template <typename memfunT, typename arg1T, typename arg2T, typename arg3T, typename arg4T>
1674 send(const keyT &key, memfunT memfun, const arg1T &arg1, const arg2T &arg2, const arg3T &arg3, const arg4T &arg4)
1675 {
1677 MEMFUN_RETURNT(memfunT)
1678 (implT::*itemfun)(const keyT &, memfunT, const arg1T &, const arg2T &, const arg3T &, const arg4T &) = &implT::template itemfun<memfunT, arg1T, arg2T, arg3T, arg4T>;
1679 return p->send(owner(key), itemfun, key, memfun, arg1, arg2, arg3, arg4);
1680 }
1681
1682 /// Sends message "resultT memfun(arg1T,arg2T,arg3T,arg4T,arg5T)" to item (non-blocking comm if remote)
1683
1684 /// If item does not exist it is made with the default constructor.
1685 ///
1686 /// Future arguments must be ready for both local and remote messages.
1687 ///
1688 /// Returns a future result (Future<void> may be ignored).
1689 ///
1690 /// The method executes with a write lock on the item.
1691 template <typename memfunT, typename arg1T, typename arg2T, typename arg3T, typename arg4T, typename arg5T>
1693 send(const keyT &key, memfunT memfun, const arg1T &arg1, const arg2T &arg2, const arg3T &arg3, const arg4T &arg4, const arg5T &arg5)
1694 {
1696 MEMFUN_RETURNT(memfunT)
1697 (implT::*itemfun)(const keyT &, memfunT, const arg1T &, const arg2T &, const arg3T &, const arg4T &, const arg5T &) = &implT::template itemfun<memfunT, arg1T, arg2T, arg3T, arg4T, arg5T>;
1698 return p->send(owner(key), itemfun, key, memfun, arg1, arg2, arg3, arg4, arg5);
1699 }
1700
1701 /// Sends message "resultT memfun(arg1T,arg2T,arg3T,arg4T,arg5T,arg6T)" to item (non-blocking comm if remote)
1702
1703 /// If item does not exist it is made with the default constructor.
1704 ///
1705 /// Future arguments must be ready for both local and remote messages.
1706 ///
1707 /// Returns a future result (Future<void> may be ignored).
1708 ///
1709 /// The method executes with a write lock on the item.
1710 template <typename memfunT, typename arg1T, typename arg2T, typename arg3T, typename arg4T, typename arg5T, typename arg6T>
1712 send(const keyT &key, memfunT memfun, const arg1T &arg1, const arg2T &arg2, const arg3T &arg3, const arg4T &arg4, const arg5T &arg5, const arg6T &arg6)
1713 {
1715 MEMFUN_RETURNT(memfunT)
1716 (implT::*itemfun)(const keyT &, memfunT, const arg1T &, const arg2T &, const arg3T &, const arg4T &, const arg5T &, const arg6T &) = &implT::template itemfun<memfunT, arg1T, arg2T, arg3T, arg4T, arg5T, arg6T>;
1717 return p->send(owner(key), itemfun, key, memfun, arg1, arg2, arg3, arg4, arg5, arg6);
1718 }
1719
1720 /// Sends message "resultT memfun(arg1T,arg2T,arg3T,arg4T,arg5T,arg6T,arg7T)" to item (non-blocking comm if remote)
1721
1722 /// If item does not exist it is made with the default constructor.
1723 ///
1724 /// Future arguments must be ready for both local and remote messages.
1725 ///
1726 /// Returns a future result (Future<void> may be ignored).
1727 ///
1728 /// The method executes with a write lock on the item.
1729 template <typename memfunT, typename arg1T, typename arg2T, typename arg3T, typename arg4T, typename arg5T, typename arg6T, typename arg7T>
1731 send(const keyT &key, memfunT memfun, const arg1T &arg1, const arg2T &arg2, const arg3T &arg3, const arg4T &arg4,
1732 const arg5T &arg5, const arg6T &arg6, const arg7T &arg7)
1733 {
1735 MEMFUN_RETURNT(memfunT)
1736 (implT::*itemfun)(const keyT &, memfunT, const arg1T &, const arg2T &, const arg3T &, const arg4T &, const arg5T &, const arg6T &, const arg7T &) = &implT::template itemfun<memfunT, arg1T, arg2T, arg3T, arg4T, arg5T, arg6T, arg7T>;
1737 return p->send(owner(key), itemfun, key, memfun, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
1738 }
1739
1740 /// Sends message "resultT memfun() const" to item (non-blocking comm if remote)
1741
1742 /// The method executes with a write lock on the item.
1743 template <typename memfunT>
1745 send(const keyT &key, memfunT memfun) const
1746 {
1747 return const_cast<containerT *>(this)->send(key, memfun);
1748 }
1749
1750 /// Sends message "resultT memfun(arg1T) const" to item (non-blocking comm if remote)
1751
1752 /// The method executes with a write lock on the item.
1753 template <typename memfunT, typename arg1T>
1755 send(const keyT &key, memfunT memfun, const arg1T &arg1) const
1756 {
1757 return const_cast<containerT *>(this)->send(key, memfun, arg1);
1758 }
1759
1760 /// Sends message "resultT memfun(arg1T,arg2T) const" to item (non-blocking comm if remote)
1761
1762 /// The method executes with a write lock on the item.
1763 template <typename memfunT, typename arg1T, typename arg2T>
1765 send(const keyT &key, memfunT memfun, const arg1T &arg1, const arg2T &arg2) const
1766 {
1767 return const_cast<containerT *>(this)->send(key, memfun, arg1, arg2);
1768 }
1769
1770 /// Sends message "resultT memfun(arg1T,arg2T,arg3T) const" to item (non-blocking comm if remote)
1771
1772 /// The method executes with a write lock on the item.
1773 template <typename memfunT, typename arg1T, typename arg2T, typename arg3T>
1775 send(const keyT &key, memfunT memfun, const arg1T &arg1, const arg2T &arg2, const arg3T &arg3) const
1776 {
1777 return const_cast<containerT *>(this)->send(key, memfun, arg1, arg2, arg3);
1778 }
1779
1780 /// Sends message "resultT memfun(arg1T,arg2T,arg3T,arg4T) const" to item (non-blocking comm if remote)
1781
1782 /// The method executes with a write lock on the item.
1783 template <typename memfunT, typename arg1T, typename arg2T, typename arg3T, typename arg4T>
1785 send(const keyT &key, memfunT memfun, const arg1T &arg1, const arg2T &arg2, const arg3T &arg3, const arg4T &arg4) const
1786 {
1787 return const_cast<containerT *>(this)->send(key, memfun, arg1, arg2, arg3, arg4);
1788 }
1789
1790 /// Sends message "resultT memfun(arg1T,arg2T,arg3T,arg4T,arg5T) const" to item (non-blocking comm if remote)
1791
1792 /// The method executes with a write lock on the item.
1793 template <typename memfunT, typename arg1T, typename arg2T, typename arg3T, typename arg4T, typename arg5T>
1795 send(const keyT &key, memfunT memfun, const arg1T &arg1, const arg2T &arg2, const arg3T &arg3, const arg4T &arg4, const arg5T &arg5) const
1796 {
1797 return const_cast<containerT *>(this)->send(key, memfun, arg1, arg2, arg3, arg4, arg5);
1798 }
1799
1800 /// Sends message "resultT memfun(arg1T,arg2T,arg3T,arg4T,arg5T,arg6T) const" to item (non-blocking comm if remote)
1801
1802 /// The method executes with a write lock on the item.
1803 template <typename memfunT, typename arg1T, typename arg2T, typename arg3T, typename arg4T, typename arg5T, typename arg6T>
1805 send(const keyT &key, memfunT memfun, const arg1T &arg1, const arg2T &arg2, const arg3T &arg3,
1806 const arg4T &arg4, const arg5T &arg5, const arg6T &arg6) const
1807 {
1808 return const_cast<containerT *>(this)->send(key, memfun, arg1, arg2, arg3, arg4, arg5, arg6);
1809 }
1810
1811 /// Sends message "resultT memfun(arg1T,arg2T,arg3T,arg4T,arg5T,arg6T,arg7T) const" to item (non-blocking comm if remote)
1812
1813 /// The method executes with a write lock on the item.
1814 template <typename memfunT, typename arg1T, typename arg2T, typename arg3T, typename arg4T, typename arg5T, typename arg6T, typename arg7T>
1816 send(const keyT &key, memfunT memfun, const arg1T &arg1, const arg2T &arg2, const arg3T &arg3,
1817 const arg4T &arg4, const arg5T &arg5, const arg6T &arg6, const arg7T &arg7) const
1818 {
1819 return const_cast<containerT *>(this)->send(key, memfun, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
1820 }
1821
1822 /// Adds task "resultT memfun()" in process owning item (non-blocking comm if remote)
1823
1824 /// If item does not exist it is made with the default constructor.
1825 ///
1826 /// Future arguments for local tasks can generate dependencies, but for remote
1827 /// tasks all futures must be ready.
1828 ///
1829 /// Returns a future result (Future<void> may be ignored).
1830 ///
1831 /// The method executes with a write lock on the item.
1832 template <typename memfunT>
1834 task(const keyT &key, memfunT memfun, const TaskAttributes &attr = TaskAttributes())
1835 {
1837 MEMFUN_RETURNT(memfunT)
1838 (implT::*itemfun)(const keyT &, memfunT) = &implT::template itemfun<memfunT>;
1839 return p->task(owner(key), itemfun, key, memfun, attr);
1840 }
1841
1842 /// Adds task "resultT memfun(arg1T)" in process owning item (non-blocking comm if remote)
1843
1844 /// If item does not exist it is made with the default constructor.
1845 ///
1846 /// Future arguments for local tasks can generate dependencies, but for remote
1847 /// tasks all futures must be ready.
1848 ///
1849 /// Returns a future result (Future<void> may be ignored).
1850 ///
1851 /// The method executes with a write lock on the item.
1852 template <typename memfunT, typename arg1T>
1854 task(const keyT &key, memfunT memfun, const arg1T &arg1, const TaskAttributes &attr = TaskAttributes())
1855 {
1857 typedef REMFUTURE(arg1T) a1T;
1858 MEMFUN_RETURNT(memfunT)
1859 (implT::*itemfun)(const keyT &, memfunT, const a1T &) = &implT::template itemfun<memfunT, a1T>;
1860 return p->task(owner(key), itemfun, key, memfun, arg1, attr);
1861 }
1862
1863 /// Adds task "resultT memfun(arg1T,arg2T)" in process owning item (non-blocking comm if remote)
1864
1865 /// If item does not exist it is made with the default constructor.
1866 ///
1867 /// Future arguments for local tasks can generate dependencies, but for remote
1868 /// tasks all futures must be ready.
1869 ///
1870 /// Returns a future result (Future<void> may be ignored).
1871 ///
1872 /// The method executes with a write lock on the item.
1873 template <typename memfunT, typename arg1T, typename arg2T>
1875 task(const keyT &key, memfunT memfun, const arg1T &arg1, const arg2T &arg2, const TaskAttributes &attr = TaskAttributes())
1876 {
1878 typedef REMFUTURE(arg1T) a1T;
1879 typedef REMFUTURE(arg2T) a2T;
1880 MEMFUN_RETURNT(memfunT)
1881 (implT::*itemfun)(const keyT &, memfunT, const a1T &, const a2T &) = &implT::template itemfun<memfunT, a1T, a2T>;
1882 return p->task(owner(key), itemfun, key, memfun, arg1, arg2, attr);
1883 }
1884
1885 /// Adds task "resultT memfun(arg1T,arg2T,arg3T)" in process owning item (non-blocking comm if remote)
1886
1887 /// If item does not exist it is made with the default constructor.
1888 ///
1889 /// Future arguments for local tasks can generate dependencies, but for remote
1890 /// tasks all futures must be ready.
1891 ///
1892 /// Returns a future result (Future<void> may be ignored).
1893 ///
1894 /// The method executes with a write lock on the item.
1895 template <typename memfunT, typename arg1T, typename arg2T, typename arg3T>
1897 task(const keyT &key, memfunT memfun, const arg1T &arg1, const arg2T &arg2, const arg3T &arg3, const TaskAttributes &attr = TaskAttributes())
1898 {
1900 typedef REMFUTURE(arg1T) a1T;
1901 typedef REMFUTURE(arg2T) a2T;
1902 typedef REMFUTURE(arg3T) a3T;
1903 MEMFUN_RETURNT(memfunT)
1904 (implT::*itemfun)(const keyT &, memfunT, const a1T &, const a2T &, const a3T &) = &implT::template itemfun<memfunT, a1T, a2T, a3T>;
1905 return p->task(owner(key), itemfun, key, memfun, arg1, arg2, arg3, attr);
1906 }
1907
1908 /// Adds task "resultT memfun(arg1T,arg2T,arg3T,arg4T)" in process owning item (non-blocking comm if remote)
1909
1910 /// If item does not exist it is made with the default constructor.
1911 ///
1912 /// Future arguments for local tasks can generate dependencies, but for remote
1913 /// tasks all futures must be ready.
1914 ///
1915 /// Returns a future result (Future<void> may be ignored).
1916 ///
1917 /// The method executes with a write lock on the item.
1918 template <typename memfunT, typename arg1T, typename arg2T, typename arg3T, typename arg4T>
1920 task(const keyT &key, memfunT memfun, const arg1T &arg1, const arg2T &arg2, const arg3T &arg3, const arg4T &arg4, const TaskAttributes &attr = TaskAttributes())
1921 {
1923 typedef REMFUTURE(arg1T) a1T;
1924 typedef REMFUTURE(arg2T) a2T;
1925 typedef REMFUTURE(arg3T) a3T;
1926 typedef REMFUTURE(arg4T) a4T;
1927 MEMFUN_RETURNT(memfunT)
1928 (implT::*itemfun)(const keyT &, memfunT, const a1T &, const a2T &, const a3T &, const a4T &) = &implT::template itemfun<memfunT, a1T, a2T, a3T, a4T>;
1929 return p->task(owner(key), itemfun, key, memfun, arg1, arg2, arg3, arg4, attr);
1930 }
1931
1932 /// Adds task "resultT memfun(arg1T,arg2T,arg3T,arg4T,arg5T)" in process owning item (non-blocking comm if remote)
1933
1934 /// If item does not exist it is made with the default constructor.
1935 ///
1936 /// Future arguments for local tasks can generate dependencies, but for remote
1937 /// tasks all futures must be ready.
1938 ///
1939 /// Returns a future result (Future<void> may be ignored).
1940 ///
1941 /// The method executes with a write lock on the item.
1942 template <typename memfunT, typename arg1T, typename arg2T, typename arg3T, typename arg4T, typename arg5T>
1944 task(const keyT &key, memfunT memfun, const arg1T &arg1, const arg2T &arg2, const arg3T &arg3, const arg4T &arg4, const arg5T &arg5, const TaskAttributes &attr = TaskAttributes())
1945 {
1947 typedef REMFUTURE(arg1T) a1T;
1948 typedef REMFUTURE(arg2T) a2T;
1949 typedef REMFUTURE(arg3T) a3T;
1950 typedef REMFUTURE(arg4T) a4T;
1951 typedef REMFUTURE(arg5T) a5T;
1952 MEMFUN_RETURNT(memfunT)
1953 (implT::*itemfun)(const keyT &, memfunT, const a1T &, const a2T &, const a3T &, const a4T &, const a5T &) = &implT::template itemfun<memfunT, a1T, a2T, a3T, a4T, a5T>;
1954 return p->task(owner(key), itemfun, key, memfun, arg1, arg2, arg3, arg4, arg5, attr);
1955 }
1956
1957 /// Adds task "resultT memfun(arg1T,arg2T,arg3T,arg4T,arg5T,arg6T)" in process owning item (non-blocking comm if remote)
1958
1959 /// If item does not exist it is made with the default constructor.
1960 ///
1961 /// Future arguments for local tasks can generate dependencies, but for remote
1962 /// tasks all futures must be ready.
1963 ///
1964 /// Returns a future result (Future<void> may be ignored).
1965 ///
1966 /// The method executes with a write lock on the item.
1967 template <typename memfunT, typename arg1T, typename arg2T, typename arg3T, typename arg4T, typename arg5T, typename arg6T>
1969 task(const keyT &key, memfunT memfun, const arg1T &arg1, const arg2T &arg2, const arg3T &arg3, const arg4T &arg4, const arg5T &arg5, const arg6T &arg6, const TaskAttributes &attr = TaskAttributes())
1970 {
1972 typedef REMFUTURE(arg1T) a1T;
1973 typedef REMFUTURE(arg2T) a2T;
1974 typedef REMFUTURE(arg3T) a3T;
1975 typedef REMFUTURE(arg4T) a4T;
1976 typedef REMFUTURE(arg5T) a5T;
1977 typedef REMFUTURE(arg6T) a6T;
1978 MEMFUN_RETURNT(memfunT)
1979 (implT::*itemfun)(const keyT &, memfunT, const a1T &, const a2T &, const a3T &, const a4T &, const a5T &, const a6T &) = &implT::template itemfun<memfunT, a1T, a2T, a3T, a4T, a5T, a6T>;
1980 return p->task(owner(key), itemfun, key, memfun, arg1, arg2, arg3, arg4, arg5, arg6, attr);
1981 }
1982
1983 /// Adds task "resultT memfun(arg1T,arg2T,arg3T,arg4T,arg5T,arg6T,arg7T)" in process owning item (non-blocking comm if remote)
1984
1985 /// If item does not exist it is made with the default constructor.
1986 ///
1987 /// Future arguments for local tasks can generate dependencies, but for remote
1988 /// tasks all futures must be ready.
1989 ///
1990 /// Returns a future result (Future<void> may be ignored).
1991 ///
1992 /// The method executes with a write lock on the item.
1993 template <typename memfunT, typename arg1T, typename arg2T, typename arg3T, typename arg4T, typename arg5T, typename arg6T, typename arg7T>
1995 task(const keyT &key, memfunT memfun, const arg1T &arg1, const arg2T &arg2, const arg3T &arg3, const arg4T &arg4, const arg5T &arg5, const arg6T &arg6, const arg7T &arg7, const TaskAttributes &attr = TaskAttributes())
1996 {
1998 typedef REMFUTURE(arg1T) a1T;
1999 typedef REMFUTURE(arg2T) a2T;
2000 typedef REMFUTURE(arg3T) a3T;
2001 typedef REMFUTURE(arg4T) a4T;
2002 typedef REMFUTURE(arg5T) a5T;
2003 typedef REMFUTURE(arg6T) a6T;
2004 typedef REMFUTURE(arg7T) a7T;
2005 MEMFUN_RETURNT(memfunT)
2006 (implT::*itemfun)(const keyT &, memfunT, const a1T &, const a2T &, const a3T &, const a4T &, const a5T &, const a6T &, const a7T &) = &implT::template itemfun<memfunT, a1T, a2T, a3T, a4T, a5T, a6T, a7T>;
2007 return p->task(owner(key), itemfun, key, memfun, arg1, arg2, arg3, arg4, arg5, arg6, arg7, attr);
2008 }
2009
2010 /// Adds task "resultT memfun() const" in process owning item (non-blocking comm if remote)
2011
2012 /// The method executes with a write lock on the item.
2013 template <typename memfunT>
2015 task(const keyT &key, memfunT memfun, const TaskAttributes &attr = TaskAttributes()) const
2016 {
2017 return const_cast<containerT *>(this)->task(key, memfun, attr);
2018 }
2019
2020 /// Adds task "resultT memfun(arg1T) const" in process owning item (non-blocking comm if remote)
2021
2022 /// The method executes with a write lock on the item.
2023 template <typename memfunT, typename arg1T>
2025 task(const keyT &key, memfunT memfun, const arg1T &arg1, const TaskAttributes &attr = TaskAttributes()) const
2026 {
2027 return const_cast<containerT *>(this)->task(key, memfun, arg1, attr);
2028 }
2029
2030 /// Adds task "resultT memfun(arg1T,arg2T) const" in process owning item (non-blocking comm if remote)
2031
2032 /// The method executes with a write lock on the item.
2033 template <typename memfunT, typename arg1T, typename arg2T>
2035 task(const keyT &key, memfunT memfun, const arg1T &arg1, const arg2T &arg2, const TaskAttributes &attr = TaskAttributes()) const
2036 {
2037 return const_cast<containerT *>(this)->task(key, memfun, arg1, arg2, attr);
2038 }
2039
2040 /// Adds task "resultT memfun(arg1T,arg2T,arg3T) const" in process owning item (non-blocking comm if remote)
2041
2042 /// The method executes with a write lock on the item.
2043 template <typename memfunT, typename arg1T, typename arg2T, typename arg3T>
2045 task(const keyT &key, memfunT memfun, const arg1T &arg1, const arg2T &arg2, const arg3T &arg3, const TaskAttributes &attr = TaskAttributes()) const
2046 {
2047 return const_cast<containerT *>(this)->task(key, memfun, arg1, arg2, arg3, attr);
2048 }
2049
2050 /// Adds task "resultT memfun(arg1T,arg2T,arg3T, arg4T) const" in process owning item (non-blocking comm if remote)
2051
2052 /// The method executes with a write lock on the item.
2053 template <typename memfunT, typename arg1T, typename arg2T, typename arg3T, typename arg4T>
2055 task(const keyT &key, memfunT memfun, const arg1T &arg1, const arg2T &arg2, const arg3T &arg3, const arg4T &arg4, const TaskAttributes &attr = TaskAttributes()) const
2056 {
2057 return const_cast<containerT *>(this)->task(key, memfun, arg1, arg2, arg3, arg4, attr);
2058 }
2059
2060 /// Adds task "resultT memfun(arg1T,arg2T,arg3T,arg4T,arg5T) const" in process owning item (non-blocking comm if remote)
2061
2062 /// The method executes with a write lock on the item.
2063 template <typename memfunT, typename arg1T, typename arg2T, typename arg3T, typename arg4T, typename arg5T>
2065 task(const keyT &key, memfunT memfun, const arg1T &arg1, const arg2T &arg2, const arg3T &arg3, const arg4T &arg4, const arg5T &arg5, const TaskAttributes &attr = TaskAttributes()) const
2066 {
2067 return const_cast<containerT *>(this)->task(key, memfun, arg1, arg2, arg3, arg4, arg5, attr);
2068 }
2069
2070 /// Adds task "resultT memfun(arg1T,arg2T,arg3T,arg4T,arg5T,arg6T) const" in process owning item (non-blocking comm if remote)
2071
2072 /// The method executes with a write lock on the item.
2073 template <typename memfunT, typename arg1T, typename arg2T, typename arg3T, typename arg4T, typename arg5T, typename arg6T>
2075 task(const keyT &key, memfunT memfun, const arg1T &arg1, const arg2T &arg2, const arg3T &arg3, const arg4T &arg4, const arg5T &arg5, const arg6T &arg6, const TaskAttributes &attr = TaskAttributes()) const
2076 {
2077 return const_cast<containerT *>(this)->task(key, memfun, arg1, arg2, arg3, arg4, arg5, arg6, attr);
2078 }
2079
2080 /// Adds task "resultT memfun(arg1T,arg2T,arg3T,arg4T,arg5T,arg6T,arg7T) const" in process owning item (non-blocking comm if remote)
2081
2082 /// The method executes with a write lock on the item.
2083 template <typename memfunT, typename arg1T, typename arg2T, typename arg3T, typename arg4T, typename arg5T, typename arg6T, typename arg7T>
2085 task(const keyT &key, memfunT memfun, const arg1T &arg1, const arg2T &arg2, const arg3T &arg3, const arg4T &arg4, const arg5T &arg5, const arg6T &arg6, const arg7T &arg7, const TaskAttributes &attr = TaskAttributes()) const
2086 {
2087 return const_cast<containerT *>(this)->task(key, memfun, arg1, arg2, arg3, arg4, arg5, arg6, arg7, attr);
2088 }
2089
2090 /// (de)Serialize --- *Local* data only to/from anything *except* Buffer*Archive and Parallel*Archive
2091
2092 /// Advisable for *you* to fence before and after this to ensure consistency
2093 template <typename Archive>
2094 void serialize(const Archive &ar)
2095 {
2096 //
2097 // !! If you change the format of this stream make sure that
2098 // !! the parallel in/out archive below is compatible
2099 //
2100 const long magic = 5881828; // Sitar Indian restaurant in Knoxville
2101 unsigned long count = 0;
2103
2104 if (Archive::is_output_archive)
2105 {
2106 ar & magic;
2107 for (iterator it = begin(); it != end(); ++it)
2108 count++;
2109 ar & count;
2110 for (iterator it = begin(); it != end(); ++it)
2111 ar &*it;
2112 }
2113 else
2114 {
2115 long cookie = 0l;
2116 ar & cookie;
2117 MADNESS_ASSERT(cookie == magic);
2118 ar & count;
2119 while (count--)
2120 {
2121 pairT datum;
2122 ar & datum;
2123 replace(datum);
2124 }
2125 }
2126 }
2127
2128 /// (de)Serialize --- !! ONLY for purpose of interprocess communication
2129
2130 /// This just writes/reads the unique id to/from the Buffer*Archive.
2132 {
2134 ar &static_cast<WorldObject<implT> *>(p.get());
2135 }
2136
2137 /// (de)Serialize --- !! ONLY for purpose of interprocess communication
2138
2139 /// This just writes/reads the unique id to/from the Buffer*Archive.
2141 {
2142 WorldObject<implT> *ptr = nullptr;
2143 ar & ptr;
2144 MADNESS_ASSERT(ptr);
2145
2146#ifdef MADNESS_DISABLE_SHARED_FROM_THIS
2147 p.reset(static_cast<implT *>(ptr), [](implT *p_) -> void{});
2148#else
2149 p = static_cast<implT *>(ptr)->shared_from_this();
2150#endif // MADNESS_DISABLE_SHARED_FROM_THIS
2151 }
2152
2153 /// Returns the associated unique id ... must be initialized
2154 const uniqueidT &id() const
2155 {
2157 return p->id();
2158 }
2159
2160 /// Destructor passes ownership of implementation to world for deferred cleanup
2162 {
2163 detail::deferred_cleanup(p->get_world(), p);
2164 }
2165
2166 friend void swap<>(WorldContainer &, WorldContainer &);
2167 };
2168
2169 /// Swaps the content of two WorldContainer objects. It should be called on all nodes.
2170
2171 /// \ingroup worlddc
2172 template <typename keyT, typename valueT, typename hashfunT>
2174 {
2175 std::swap(dc0.p, dc1.p);
2176 }
2177
2178
2179 namespace archive
2180 {
2181
2182 /// Write container to parallel archive
2183
2184 /// specialization for parallel serialization of a WorldContainer:
2185 /// all threads on each process serialize some values into a buffer, which gets concatenated
2186 /// and finally serialized to localarchive (aka VectorOutputArchive).
2187 template <class keyT, class valueT>
2189 {
2191 {
2192 using localarchiveT = VectorOutputArchive;
2193 const long magic = -5881828; // Sitar Indian restaurant in Knoxville (negative to indicate parallel!)
2194 typedef WorldContainer<keyT, valueT> dcT;
2195 using const_iterator = typename dcT::const_iterator;
2196 int count = t.size(); // Must be INT for MPI and NOT const since we'll do a global sum eventually
2197
2198 // Strategy:
2199 // 1. Serialize local data to a buffer in parallel over threads
2200 // a) Compute the size of the buffer needed by each task
2201 // b) Sum sizes and allocate the buffer of exact sizes needed for all threads
2202 // c) Serialize the data into the buffer in parallel over threads
2203 // 2. Gather all buffers to process 0
2204
2205 World *world = ar.get_world();
2206 world->gop.fence(); // Global fence here
2207
2208 class op_inspector : public TaskInterface
2209 {
2210 const_iterator start, end;
2211 size_t &size;
2212
2213 public:
2214 op_inspector(const_iterator start, const_iterator end, size_t &size)
2215 : start(start), end(end), size(size) {}
2216
2217 using TaskInterface::run;
2218
2219 void run(World &world) override
2220 {
2222 for (const_iterator it = start; it != end; ++it)
2223 bo &*it;
2224 size = bo.size();
2225 }
2226 };
2227
2228 class op_executor : public TaskInterface
2229 {
2230 const_iterator start, end;
2231 unsigned char *buf;
2232 const size_t size;
2233
2234 public:
2235 op_executor(const_iterator start, const_iterator end, unsigned char *buf, size_t size)
2236 : start(start), end(end), buf(buf), size(size) {}
2237
2238 using TaskInterface::run;
2239
2240 void run(World &world) override
2241 {
2242 BufferOutputArchive bo(buf, size);
2243 for (const_iterator it = start; it != end; ++it)
2244 {
2245 bo &*it;
2246 }
2247 MADNESS_CHECK(size == bo.size());
2248 }
2249 };
2250
2251 // No need for LOCAL fence here since only master thread is busy
2252 double wall0 = wall_time();
2253 const size_t ntasks = std::min(size_t(count), std::max(size_t(1), ThreadPool::size()));
2254 size_t local_size = 0;
2255 double wall1 = wall0;
2256 unsigned char* buf = 0;
2257 if (ntasks > 0)
2258 {
2259 const size_t max_items_per_task = (std::max(1, count) - 1) / ntasks + 1;
2260 // Compute the size of the buffer needed by each task
2261 std::vector<const_iterator> starts(ntasks), ends(ntasks);
2262 std::vector<size_t> local_sizes(ntasks);
2263 const_iterator start = t.begin();
2264 size_t nleft = count;
2265 for (size_t taskid = 0; taskid < ntasks; taskid++)
2266 {
2267 const_iterator end = start;
2268 if (taskid == (ntasks - 1))
2269 {
2270 end = t.end();
2271 }
2272 else
2273 {
2274 size_t nitems = std::min(max_items_per_task, nleft);
2275 std::advance(end, max_items_per_task);
2276 nleft -= nitems;
2277 }
2278 starts[taskid] = start;
2279 ends[taskid] = end;
2280 world->taskq.add(new op_inspector(start, end, local_sizes[taskid])); // Be sure to pass iterators by value!!
2281 start = end;
2282 }
2283 world->taskq.fence(); // just need LOCAL fence
2284 wall1 = wall_time();
2285 // if (world->rank() == 0)
2286 // printf("time in op_inspector: %8.4fs\n", wall1 - wall0);
2287 wall0 = wall1;
2288
2289 // total size over all threads
2290 for (size_t taskid = 0; taskid < ntasks; taskid++)
2291 {
2292 local_size += local_sizes[taskid];
2293 // print("taskid",taskid,"size",local_sizes[taskid]);
2294 }
2295
2296 // Allocate the buffer for all threads
2297 buf = new unsigned char[local_size];
2298
2299 // Now execute the serialization
2300 size_t offset = 0;
2301 for (size_t taskid = 0; taskid < ntasks; taskid++)
2302 {
2303 world->taskq.add(new op_executor(starts[taskid], ends[taskid], buf + offset, local_sizes[taskid]));
2304 offset += local_sizes[taskid];
2305 }
2306 world->taskq.fence(); // just need LOCAL fence
2307
2308 wall1 = wall_time();
2309 // if (world->rank() == 0)
2310 // printf("time in op_executor: %8.4fs\n", wall1 - wall0);
2311 wall0 = wall1;
2312 }
2313 // VERify that the serialization worked!!
2314 // {
2315 // BufferInputArchive bi(buf, local_size);
2316 // for (int item=0; item<count; item++) {
2317 // std::pair<keyT, valueT> datum;
2318 // bi & datum;
2319 // print("deserializing",datum.first);
2320 // }
2321 // }
2322
2323 // Gather all buffers to process 0
2324 // first gather all of the sizes and counts to a vector in process 0
2325 const int size = local_size;
2326 std::vector<int> sizes(world->size());
2327 MPI_Gather(&size, 1, MPI_INT, sizes.data(), 1, MPI_INT, 0, world->mpi.comm().Get_mpi_comm());
2328 world->gop.sum(count); // just need total number of elements
2329
2330 // print("time 3",wall_time());
2331 // build the cumulative sum of sizes
2332 std::vector<int> offsets(world->size());
2333 offsets[0] = 0;
2334 for (int i = 1; i < world->size(); ++i)
2335 offsets[i] = offsets[i - 1] + sizes[i - 1];
2336 size_t total_size = offsets.back() + sizes.back();
2337 // if (world->rank() == 0)
2338 // print("total_size", total_size);
2339
2340 // print("time 4",wall_time());
2341 // gather the vector of data v from each process to process 0
2342 unsigned char *all_data = 0;
2343 if (world->rank() == 0)
2344 {
2345 all_data = new unsigned char[total_size];
2346 }
2347 MPI_Gatherv(buf, local_size, MPI_BYTE, all_data, sizes.data(), offsets.data(), MPI_BYTE, 0, world->mpi.comm().Get_mpi_comm());
2348
2349 wall1 = wall_time();
2350 // if (world->rank() == 0)
2351 // printf("time in gather+gatherv: %8.4fs\n", wall1 - wall0);
2352 wall0 = wall1;
2353
2354 delete[] buf;
2355
2356 // print("time 5",wall_time());
2357 if (world->rank() == 0)
2358 {
2359 auto &localar = ar.local_archive();
2360 localar & magic & 1; // 1 client
2361 // localar & t;
2363 localar & -magic &(unsigned long)(count);
2364 localar.store(all_data, total_size);
2366 wall1 = wall_time();
2367 // if (world->rank() == 0)
2368 // printf("time in final copy on node 0: %8.4fs\n", wall1 - wall0);
2369
2370 delete[] all_data;
2371 }
2372 world->gop.fence();
2373 // print("time 6",wall_time());
2374 }
2375 };
2376
2377 /// Write container to parallel archive with optional fence
2378
2379 /// \ingroup worlddc
2380 /// Each node (process) is served by a designated IO node.
2381 /// The IO node has a binary local file archive to which is
2382 /// first written a cookie and the number of servers. The IO
2383 /// node then loops thru all of its clients and in turn tells
2384 /// each to write its data over an MPI stream, which is copied
2385 /// directly to the output file. The stream contents are then
2386 /// cookie, no. of clients, foreach client (usual sequential archive).
2387 ///
2388 /// If ar.dofence() is true (default) fence is invoked before and
2389 /// after the IO. The fence is optional but it is of course
2390 /// necessary to be sure that all updates have completed
2391 /// before doing IO, and that all IO has completed before
2392 /// subsequent modifications. Also, there is always at least
2393 /// some synchronization between a client and its IO server.
2394 template <class keyT, class valueT, class localarchiveT>
2396 {
2398 {
2399 const long magic = -5881828; // Sitar Indian restaurant in Knoxville (negative to indicate parallel!)
2400 typedef WorldContainer<keyT, valueT> dcT;
2401 // typedef typename dcT::const_iterator iterator; // unused?
2402 typedef typename dcT::pairT pairT;
2403 World *world = ar.get_world();
2404 Tag tag = world->mpi.unique_tag();
2405 ProcessID me = world->rank();
2406 if (ar.dofence())
2407 world->gop.fence();
2408 if (ar.is_io_node())
2409 {
2410 auto &localar = ar.local_archive();
2411 localar & magic & ar.num_io_clients();
2412 for (ProcessID p = 0; p < world->size(); ++p)
2413 {
2414 if (p == me)
2415 {
2416 localar & t;
2417 }
2418 else if (ar.io_node(p) == me)
2419 {
2420 world->mpi.Send(int(1), p, tag); // Tell client to start sending
2422 long cookie = 0l;
2423 unsigned long count = 0ul;
2424
2426
2427 source & cookie & count;
2428 localar & cookie & count;
2429 while (count--)
2430 {
2431 pairT datum;
2432 source & datum;
2433 localar & datum;
2434 }
2435
2437 }
2438 }
2439 }
2440 else
2441 {
2442 ProcessID p = ar.my_io_node();
2443 int flag;
2444 world->mpi.Recv(flag, p, tag);
2445 MPIOutputArchive dest(*world, p);
2446 dest & t;
2447 dest.flush();
2448 }
2449 if (ar.dofence())
2450 world->gop.fence();
2451 }
2452 };
2453
2454 template <class keyT, class valueT, class localarchiveT>
2456 {
2457 /// Read container from parallel archive
2458
2459 /// \ingroup worlddc
2460 /// See store method above for format of file content.
2461 /// !!! We presently ASSUME that the number of writers and readers are
2462 /// the same. This is frustrating but not a show stopper since you
2463 /// can always run a separate job to copy to a different number.
2464 ///
2465 /// The IO node simply reads all data and inserts entries.
2467 {
2468 const long magic = -5881828; // Sitar Indian restaurant in Knoxville (negative to indicate parallel!)
2469 // typedef WorldContainer<keyT,valueT> dcT; // unused
2470 // typedef typename dcT::iterator iterator; // unused
2471 // typedef typename dcT::pairT pairT; // unused
2472 World *world = ar.get_world();
2473 if (ar.dofence())
2474 world->gop.fence();
2475 if (ar.is_io_node())
2476 {
2477 long cookie = 0l;
2478 int nclient = 0;
2479 auto &localar = ar.local_archive();
2480 localar & cookie & nclient;
2481 MADNESS_CHECK(cookie == magic);
2482 while (nclient--)
2483 {
2484 localar & t;
2485 }
2486 }
2487 if (ar.dofence())
2488 world->gop.fence();
2489 }
2490 };
2491 }
2492
2493}
2494
2495///@}
2496
2497#endif // MADNESS_WORLD_WORLDDC_H__INCLUDED
Definition safempi.h:435
Group Incl(int n, const int *ranks) const
Definition safempi.h:437
Wrapper around MPI_Comm. Has a shallow copy constructor; use Create(Get_group()) for deep copy.
Definition safempi.h:497
Intracomm Create(Group group) const
Definition safempi.h:616
MPI_Comm & Get_mpi_comm() const
Definition safempi.h:716
int unique_tag()
Returns a unique tag for temporary use (1023<tag<4095)
Definition safempi.h:837
Group Get_group() const
Definition safempi.h:709
Definition worldhashmap.h:396
size_t size() const
Definition worldhashmap.h:560
iterator begin()
Definition worldhashmap.h:571
void erase(const iterator &it)
Definition worldhashmap.h:507
std::pair< iterator, bool > insert(const datumT &datum)
Definition worldhashmap.h:468
const hashfunT & get_hash() const
Definition worldhashmap.h:595
bool try_erase(const keyT &key)
Definition worldhashmap.h:502
iterator end()
Definition worldhashmap.h:583
iterator find(const keyT &key)
Definition worldhashmap.h:524
void clear()
Definition worldhashmap.h:556
Implements the functionality of futures.
Definition future.h:75
T & get(bool dowork=true)
Gets/forces the value, waiting if necessary.
Definition future.h:289
A future is a possibly yet unevaluated value.
Definition future.h:370
remote_refT remote_ref(World &world) const
Returns a structure used to pass references to another process.
Definition future.h:672
Definition worldhashmap.h:330
iterator for hash
Definition worldhashmap.h:188
Range, vaguely a la Intel TBB, to encapsulate a random-access, STL-like start and end iterator with c...
Definition range.h:64
Simple structure used to manage references/pointers to remote instances.
Definition worldref.h:395
Contains attributes of a task.
Definition thread.h:329
All world tasks must be derived from this public interface.
Definition taskfn.h:69
static std::size_t size()
Returns the number of threads in the pool.
Definition thread.h:1419
Internal implementation of distributed container to facilitate shallow copy.
Definition worlddc.h:564
void erase(const keyT &key)
Definition worlddc.h:907
WorldContainerIterator< internal_iteratorT > iterator
Definition worlddc.h:579
const hashfunT & get_hash() const
Definition worlddc.h:832
bool find(const_accessor &acc, const keyT &key) const
Definition worlddc.h:995
internal_containerT::accessor accessor
Definition worlddc.h:576
void find_handler(ProcessID requestor, const keyT &key, const RemoteReference< FutureImpl< iterator > > &ref)
Handles find request.
Definition worlddc.h:604
bool probe(const keyT &key) const
Definition worlddc.h:844
void find_success_handler(const RemoteReference< FutureImpl< iterator > > &ref, const pairT &datum)
Handles successful find response.
Definition worlddc.h:620
std::pair< const keyT, valueT > pairT
Definition worlddc.h:566
bool insert_const_acc(const_accessor &acc, const keyT &key)
Definition worlddc.h:882
void redistribute_coalesced_phase1(const std::shared_ptr< WorldDCPmapInterface< keyT > > &newpmap)
Definition worlddc.h:1150
WorldContainerIterator< internal_const_iteratorT > const_iteratorT
Definition worlddc.h:580
bool find(accessor &acc, const keyT &key)
Definition worlddc.h:988
void redistribute_phase2()
Definition worlddc.h:1123
void insert(const pairT &datum)
Definition worlddc.h:858
WorldContainerIterator< internal_iteratorT > iteratorT
Definition worlddc.h:578
void clear()
Definition worlddc.h:902
bool insert_acc(accessor &acc, const keyT &key)
Definition worlddc.h:876
Future< iterator > find(const keyT &key)
Definition worlddc.h:973
WorldContainerImpl(World &world, const std::shared_ptr< WorldDCPmapInterface< keyT > > &pm, const hashfunT &hf)
Definition worlddc.h:640
void redistribute_coalesced_phase2(std::size_t cap_boxes, bool rotate)
Definition worlddc.h:1167
void reset_pmap_to_local()
Definition worlddc.h:663
itemfun(const keyT &key, memfunT memfun)
Definition worlddc.h:1005
const pairT const_pairT
Definition worlddc.h:567
std::vector< keyT > * move_list
Tempoary used to record data that needs redistributing.
Definition worlddc.h:600
internal_containerT::iterator internal_iteratorT
Definition worlddc.h:574
WorldContainerImpl< keyT, valueT, hashfunT > implT
Definition worlddc.h:568
std::size_t size() const
Definition worlddc.h:853
void redistribute_phase1(const std::shared_ptr< WorldDCPmapInterface< keyT > > &newpmap)
Definition worlddc.h:1092
internal_containerT::const_iterator internal_const_iteratorT
Definition worlddc.h:575
std::shared_ptr< WorldDCPmapInterface< keyT > > pmap
Function/class to map from keys to owning process.
Definition worlddc.h:597
virtual ~WorldContainerImpl()
Definition worlddc.h:648
void do_replicate(World &world)
Definition worlddc.h:800
std::shared_ptr< WorldDCPmapInterface< keyT > > & get_pmap()
Definition worlddc.h:658
internal_containerT local
Locally owned data.
Definition worlddc.h:599
ConcurrentHashMap< keyT, valueT, hashfunT > internal_containerT
Definition worlddc.h:570
void insert_batch(const std::vector< pairT > &boxes)
Definition worlddc.h:892
const_iterator begin() const
Definition worlddc.h:947
void erase(InIter it)
Definition worlddc.h:923
void replicate(bool fence)
Definition worlddc.h:672
const_iterator end() const
Definition worlddc.h:957
bool is_local(const keyT &key) const
Definition worlddc.h:834
void redistribute_phase3()
Definition worlddc.h:1137
void find_failure_handler(const RemoteReference< FutureImpl< iterator > > &ref)
Handles unsuccessful find response.
Definition worlddc.h:630
ProcessID owner(const keyT &key) const
Definition worlddc.h:839
void erase(InIter first, InIter last)
Definition worlddc.h:931
void replicate_on_hosts(bool fence)
Definition worlddc.h:685
const std::shared_ptr< WorldDCPmapInterface< keyT > > & get_pmap() const
Definition worlddc.h:653
iterator begin()
Definition worlddc.h:942
Future< const_iterator > find(const keyT &key) const
Definition worlddc.h:962
const ProcessID me
My MPI rank.
Definition worlddc.h:598
iterator end()
Definition worlddc.h:952
std::map< ProcessID, std::vector< keyT > > coalesced_move_
Temporary: keys to move, bucketed by destination (coalesced redistribute)
Definition worlddc.h:601
WorldContainerIterator< internal_const_iteratorT > const_iterator
Definition worlddc.h:581
internal_containerT::const_accessor const_accessor
Definition worlddc.h:577
Iterator for distributed container wraps the local iterator.
Definition worlddc.h:414
WorldContainerIterator(const WorldContainerIterator &other)
Definition worlddc.h:443
WorldContainerIterator(const internal_iteratorT &it)
Initializes from a local iterator.
Definition worlddc.h:433
WorldContainerIterator & operator++()
Pre-increment of an iterator (i.e., ++it) — local iterators only.
Definition worlddc.h:484
std::iterator_traits< internal_iteratorT >::iterator_category iterator_category
Definition worlddc.h:416
void copy(const WorldContainerIterator< iteratorT > &other)
Definition worlddc.h:534
std::iterator_traits< internal_iteratorT >::pointer pointer
Definition worlddc.h:419
bool operator==(const WorldContainerIterator &other) const
Determines if two iterators are identical.
Definition worlddc.h:469
const internal_iteratorT & get_internal_iterator() const
Private: (or should be) Returns iterator of internal container.
Definition worlddc.h:512
WorldContainerIterator & operator=(const WorldContainerIterator &other)
Assignment.
Definition worlddc.h:462
value_type * value
holds the remote values
Definition worlddc.h:425
bool is_cached() const
Returns true if this is non-local or cached value.
Definition worlddc.h:518
WorldContainerIterator operator++(int)
Definition worlddc.h:491
WorldContainerIterator(const value_type &v)
Initializes to cache a remote value.
Definition worlddc.h:437
pointer operator->() const
Iterators dereference to std::pair<const keyT,valueT>
Definition worlddc.h:500
std::iterator_traits< internal_iteratorT >::reference reference
Definition worlddc.h:420
void serialize(const Archive &)
Definition worlddc.h:524
std::iterator_traits< internal_iteratorT >::value_type value_type
Definition worlddc.h:417
WorldContainerIterator(const WorldContainerIterator< iteratorT > &other)
Definition worlddc.h:450
WorldContainerIterator()
Default constructor makes a local uninitialized value.
Definition worlddc.h:429
internal_iteratorT it
Iterator from local container.
Definition worlddc.h:423
reference operator*() const
Iterators dereference to std::pair<const keyT,valueT>
Definition worlddc.h:506
std::iterator_traits< internal_iteratorT >::difference_type difference_type
Definition worlddc.h:418
bool operator!=(const WorldContainerIterator &other) const
Determines if two iterators are different.
Definition worlddc.h:476
~WorldContainerIterator()
Definition worlddc.h:456
Makes a distributed container with specified attributes.
Definition worlddc.h:1231
void process_pending()
Process pending messages.
Definition worlddc.h:1574
WorldContainer(World &world, bool do_pending=true, const hashfunT &hf=hashfunT())
Makes an initialized, empty container with default data distribution (no communication)
Definition worlddc.h:1271
const hashfunT & get_hash() const
Returns a reference to the hashing functor.
Definition worlddc.h:1563
bool find(accessor &acc, const keyT &key)
Write access to LOCAL value by key. Returns true if found, false otherwise (always false for remote).
Definition worlddc.h:1395
bool probe(const keyT &key) const
Returns true if local data is immediately available (no communication)
Definition worlddc.h:1432
void redistribute_coalesced_phase2(std::size_t cap_boxes, bool rotate=true)
Definition worlddc.h:1375
const_iterator begin() const
Returns an iterator to the beginning of the local data (no communication)
Definition worlddc.h:1485
void replace(const keyT &key, const valueT &value)
Inserts/replaces key+value pair (non-blocking communication if key not local)
Definition worlddc.h:1389
bool insert(const_accessor &acc, const keyT &key)
Read access to LOCAL value by key. Returns true if inserted, false if already exists (throws if remot...
Definition worlddc.h:1416
iterator begin()
Returns an iterator to the beginning of the local data (no communication)
Definition worlddc.h:1478
Future< REMFUTURE(MEMFUN_RETURNT(memfunT))> task(const keyT &key, memfunT memfun, const arg1T &arg1, const arg2T &arg2, const arg3T &arg3, const arg4T &arg4, const arg5T &arg5, const TaskAttributes &attr=TaskAttributes()) const
Adds task "resultT memfun(arg1T,arg2T,arg3T,arg4T,arg5T) const" in process owning item (non-blocking ...
Definition worlddc.h:2065
WorldContainer(World &world, const std::shared_ptr< WorldDCPmapInterface< keyT > > &pmap, bool do_pending=true, const hashfunT &hf=hashfunT())
Makes an initialized, empty container (no communication)
Definition worlddc.h:1287
Future< iterator > find(const keyT &key)
Returns a future iterator (non-blocking communication if key not local)
Definition worlddc.h:1460
Future< REMFUTURE(MEMFUN_RETURNT(memfunT))> send(const keyT &key, memfunT memfun, const arg1T &arg1, const arg2T &arg2, const arg3T &arg3, const arg4T &arg4, const arg5T &arg5, const arg6T &arg6) const
Sends message "resultT memfun(arg1T,arg2T,arg3T,arg4T,arg5T,arg6T) const" to item (non-blocking comm ...
Definition worlddc.h:1805
Future< REMFUTURE(MEMFUN_RETURNT(memfunT))> send(const keyT &key, memfunT memfun, const arg1T &arg1, const arg2T &arg2, const arg3T &arg3, const arg4T &arg4, const arg5T &arg5, const arg6T &arg6, const arg7T &arg7) const
Sends message "resultT memfun(arg1T,arg2T,arg3T,arg4T,arg5T,arg6T,arg7T) const" to item (non-blocking...
Definition worlddc.h:1816
Future< const_iterator > const_futureT
Definition worlddc.h:1243
bool is_replicated() const
Definition worlddc.h:1331
Future< REMFUTURE(MEMFUN_RETURNT(memfunT))> task(const keyT &key, memfunT memfun, const arg1T &arg1, const TaskAttributes &attr=TaskAttributes())
Adds task "resultT memfun(arg1T)" in process owning item (non-blocking comm if remote)
Definition worlddc.h:1854
Future< REMFUTURE(MEMFUN_RETURNT(memfunT))> send(const keyT &key, memfunT memfun, const arg1T &arg1, const arg2T &arg2, const arg3T &arg3, const arg4T &arg4, const arg5T &arg5) const
Sends message "resultT memfun(arg1T,arg2T,arg3T,arg4T,arg5T) const" to item (non-blocking comm if rem...
Definition worlddc.h:1795
ProcessID owner(const keyT &key) const
Returns processor that logically owns key (no communication)
Definition worlddc.h:1442
implT::const_iterator const_iterator
Definition worlddc.h:1239
Future< REMFUTURE(MEMFUN_RETURNT(memfunT))> task(const keyT &key, memfunT memfun, const arg1T &arg1, const arg2T &arg2, const TaskAttributes &attr=TaskAttributes()) const
Adds task "resultT memfun(arg1T,arg2T) const" in process owning item (non-blocking comm if remote)
Definition worlddc.h:2035
Future< REMFUTURE(MEMFUN_RETURNT(memfunT))> task(const keyT &key, memfunT memfun, const TaskAttributes &attr=TaskAttributes()) const
Adds task "resultT memfun() const" in process owning item (non-blocking comm if remote)
Definition worlddc.h:2015
WorldContainer()
Makes an uninitialized container (no communication)
Definition worlddc.h:1259
void serialize(const archive::BufferOutputArchive &ar)
(de)Serialize — !! ONLY for purpose of interprocess communication
Definition worlddc.h:2131
keyT key_type
Definition worlddc.h:1234
Future< REMFUTURE(MEMFUN_RETURNT(memfunT))> send(const keyT &key, memfunT memfun, const arg1T &arg1, const arg2T &arg2, const arg3T &arg3)
Sends message "resultT memfun(arg1T,arg2T,arg3T)" to item (non-blocking comm if remote)
Definition worlddc.h:1655
void replicate(bool fence=true)
replicates this WorldContainer on all ProcessIDs
Definition worlddc.h:1353
virtual ~WorldContainer()
Destructor passes ownership of implementation to world for deferred cleanup.
Definition worlddc.h:2161
void erase(const keyT &key)
Erases entry from container (non-blocking comm if remote)
Definition worlddc.h:1513
Future< REMFUTURE(MEMFUN_RETURNT(memfunT))> send(const keyT &key, memfunT memfun, const arg1T &arg1, const arg2T &arg2, const arg3T &arg3, const arg4T &arg4, const arg5T &arg5)
Sends message "resultT memfun(arg1T,arg2T,arg3T,arg4T,arg5T)" to item (non-blocking comm if remote)
Definition worlddc.h:1693
void reset_pmap_to_local()
Returns shared pointer to the process mapping.
Definition worlddc.h:1557
Future< REMFUTURE(MEMFUN_RETURNT(memfunT))> send(const keyT &key, const memfunT &memfun, const arg1T &arg1)
Sends message "resultT memfun(arg1T)" to item (non-blocking comm if remote)
Definition worlddc.h:1610
const uniqueidT & id() const
Returns the associated unique id ... must be initialized.
Definition worlddc.h:2154
void redistribute_coalesced_phase1(const std::shared_ptr< WorldDCPmapInterface< keyT > > &newpmap)
Definition worlddc.h:1366
Future< REMFUTURE(MEMFUN_RETURNT(memfunT))> task(const keyT &key, memfunT memfun, const arg1T &arg1, const arg2T &arg2, const arg3T &arg3, const arg4T &arg4, const arg5T &arg5, const arg6T &arg6, const arg7T &arg7, const TaskAttributes &attr=TaskAttributes())
Adds task "resultT memfun(arg1T,arg2T,arg3T,arg4T,arg5T,arg6T,arg7T)" in process owning item (non-blo...
Definition worlddc.h:1995
Future< REMFUTURE(MEMFUN_RETURNT(memfunT))> task(const keyT &key, memfunT memfun, const arg1T &arg1, const arg2T &arg2, const TaskAttributes &attr=TaskAttributes())
Adds task "resultT memfun(arg1T,arg2T)" in process owning item (non-blocking comm if remote)
Definition worlddc.h:1875
WorldContainerImpl< keyT, valueT, hashfunT > implT
Definition worlddc.h:1236
Future< REMFUTURE(MEMFUN_RETURNT(memfunT))> send(const keyT &key, memfunT memfun, const arg1T &arg1, const arg2T &arg2) const
Sends message "resultT memfun(arg1T,arg2T) const" to item (non-blocking comm if remote)
Definition worlddc.h:1765
void replace(const pairT &datum)
Inserts/replaces key+value pair (non-blocking communication if key not local)
Definition worlddc.h:1382
Future< REMFUTURE(MEMFUN_RETURNT(memfunT))> task(const keyT &key, memfunT memfun, const arg1T &arg1, const arg2T &arg2, const arg3T &arg3, const TaskAttributes &attr=TaskAttributes()) const
Adds task "resultT memfun(arg1T,arg2T,arg3T) const" in process owning item (non-blocking comm if remo...
Definition worlddc.h:2045
iterator end()
Returns an iterator past the end of the local data (no communication)
Definition worlddc.h:1492
const std::shared_ptr< WorldDCPmapInterface< keyT > > & get_pmap() const
Returns shared pointer to the process mapping.
Definition worlddc.h:1550
std::shared_ptr< WorldDCPmapInterface< keyT > > & get_impl()
Definition worlddc.h:1346
void replace(input_iterator &start, input_iterator &end)
Inserts pairs (non-blocking communication if key(s) not local)
Definition worlddc.h:1424
Future< REMFUTURE(MEMFUN_RETURNT(memfunT))> task(const keyT &key, memfunT memfun, const arg1T &arg1, const TaskAttributes &attr=TaskAttributes()) const
Adds task "resultT memfun(arg1T) const" in process owning item (non-blocking comm if remote)
Definition worlddc.h:2025
bool insert(accessor &acc, const keyT &key)
Write access to LOCAL value by key. Returns true if inserted, false if already exists (throws if remo...
Definition worlddc.h:1409
Future< iterator > futureT
Definition worlddc.h:1242
void erase(const iterator &it)
Erases entry corresponding to local iterator (no communication)
Definition worlddc.h:1520
Future< REMFUTURE(MEMFUN_RETURNT(memfunT))> task(const keyT &key, memfunT memfun, const arg1T &arg1, const arg2T &arg2, const arg3T &arg3, const arg4T &arg4, const TaskAttributes &attr=TaskAttributes()) const
Adds task "resultT memfun(arg1T,arg2T,arg3T, arg4T) const" in process owning item (non-blocking comm ...
Definition worlddc.h:2055
void erase(const iterator &start, const iterator &finish)
Erases range defined by local iterators (no communication)
Definition worlddc.h:1527
Future< REMFUTURE(MEMFUN_RETURNT(memfunT))> send(const keyT &key, memfunT memfun, const arg1T &arg1, const arg2T &arg2, const arg3T &arg3, const arg4T &arg4) const
Sends message "resultT memfun(arg1T,arg2T,arg3T,arg4T) const" to item (non-blocking comm if remote)
Definition worlddc.h:1785
bool is_distributed() const
Definition worlddc.h:1327
WorldContainer(const WorldContainer &other)
Copy constructor is shallow (no communication)
Definition worlddc.h:1301
Future< REMFUTURE(MEMFUN_RETURNT(memfunT))> task(const keyT &key, memfunT memfun, const arg1T &arg1, const arg2T &arg2, const arg3T &arg3, const arg4T &arg4, const arg5T &arg5, const arg6T &arg6, const TaskAttributes &attr=TaskAttributes())
Adds task "resultT memfun(arg1T,arg2T,arg3T,arg4T,arg5T,arg6T)" in process owning item (non-blocking ...
Definition worlddc.h:1969
Future< REMFUTURE(MEMFUN_RETURNT(memfunT))> send(const keyT &key, memfunT memfun, const arg1T &arg1, const arg2T &arg2, const arg3T &arg3, const arg4T &arg4, const arg5T &arg5, const arg6T &arg6, const arg7T &arg7)
Sends message "resultT memfun(arg1T,arg2T,arg3T,arg4T,arg5T,arg6T,arg7T)" to item (non-blocking comm ...
Definition worlddc.h:1731
World & get_world() const
Returns the world associated with this container.
Definition worlddc.h:1340
Future< REMFUTURE(MEMFUN_RETURNT(memfunT))> send(const keyT &key, memfunT memfun) const
Sends message "resultT memfun() const" to item (non-blocking comm if remote)
Definition worlddc.h:1745
implT::iterator iterator
Definition worlddc.h:1238
DistributionType get_distribution_type() const
return the way data is distributed
Definition worlddc.h:1322
implT::pairT pairT
Definition worlddc.h:1237
std::size_t size() const
Returns the number of local entries (no communication)
Definition worlddc.h:1543
containerT & operator=(const containerT &other)
Assignment is shallow (no communication)
Definition worlddc.h:1311
Future< REMFUTURE(MEMFUN_RETURNT(memfunT))> task(const keyT &key, memfunT memfun, const arg1T &arg1, const arg2T &arg2, const arg3T &arg3, const arg4T &arg4, const arg5T &arg5, const TaskAttributes &attr=TaskAttributes())
Adds task "resultT memfun(arg1T,arg2T,arg3T,arg4T,arg5T)" in process owning item (non-blocking comm i...
Definition worlddc.h:1944
bool find(const_accessor &acc, const keyT &key) const
Read access to LOCAL value by key. Returns true if found, false otherwise (always false for remote).
Definition worlddc.h:1402
Future< REMFUTURE(MEMFUN_RETURNT(memfunT))> task(const keyT &key, memfunT memfun, const arg1T &arg1, const arg2T &arg2, const arg3T &arg3, const TaskAttributes &attr=TaskAttributes())
Adds task "resultT memfun(arg1T,arg2T,arg3T)" in process owning item (non-blocking comm if remote)
Definition worlddc.h:1897
Future< REMFUTURE(MEMFUN_RETURNT(memfunT))> send(const keyT &key, memfunT memfun, const arg1T &arg1, const arg2T &arg2, const arg3T &arg3, const arg4T &arg4)
Sends message "resultT memfun(arg1T,arg2T,arg3T,arg4T)" to item (non-blocking comm if remote)
Definition worlddc.h:1674
void serialize(const archive::BufferInputArchive &ar)
(de)Serialize — !! ONLY for purpose of interprocess communication
Definition worlddc.h:2140
Future< REMFUTURE(MEMFUN_RETURNT(memfunT))> task(const keyT &key, memfunT memfun, const TaskAttributes &attr=TaskAttributes())
Adds task "resultT memfun()" in process owning item (non-blocking comm if remote)
Definition worlddc.h:1834
bool is_local(const keyT &key) const
Returns true if the key maps to the local processor (no communication)
Definition worlddc.h:1449
const_iterator end() const
Returns an iterator past the end of the local data (no communication)
Definition worlddc.h:1499
void serialize(const Archive &ar)
(de)Serialize — Local data only to/from anything except Buffer*Archive and Parallel*Archive
Definition worlddc.h:2094
bool is_host_replicated() const
Definition worlddc.h:1335
Future< REMFUTURE(MEMFUN_RETURNT(memfunT))> task(const keyT &key, memfunT memfun, const arg1T &arg1, const arg2T &arg2, const arg3T &arg3, const arg4T &arg4, const arg5T &arg5, const arg6T &arg6, const TaskAttributes &attr=TaskAttributes()) const
Adds task "resultT memfun(arg1T,arg2T,arg3T,arg4T,arg5T,arg6T) const" in process owning item (non-blo...
Definition worlddc.h:2075
void clear()
Clears all local data (no communication)
Definition worlddc.h:1536
Future< REMFUTURE(MEMFUN_RETURNT(memfunT))> task(const keyT &key, memfunT memfun, const arg1T &arg1, const arg2T &arg2, const arg3T &arg3, const arg4T &arg4, const TaskAttributes &attr=TaskAttributes())
Adds task "resultT memfun(arg1T,arg2T,arg3T,arg4T)" in process owning item (non-blocking comm if remo...
Definition worlddc.h:1920
Future< MEMFUN_RETURNT(memfunT)> send(const keyT &key, memfunT memfun)
Sends message "resultT memfun()" to item (non-blocking comm if remote)
Definition worlddc.h:1591
implT::const_accessor const_accessor
Definition worlddc.h:1241
std::shared_ptr< implT > p
Definition worlddc.h:1246
Future< const_iterator > find(const keyT &key) const
Returns a future iterator (non-blocking communication if key not local)
Definition worlddc.h:1471
Future< REMFUTURE(MEMFUN_RETURNT(memfunT))> send(const keyT &key, memfunT memfun, const arg1T &arg1, const arg2T &arg2, const arg3T &arg3) const
Sends message "resultT memfun(arg1T,arg2T,arg3T) const" to item (non-blocking comm if remote)
Definition worlddc.h:1775
Future< REMFUTURE(MEMFUN_RETURNT(memfunT))> send(const keyT &key, memfunT memfun, const arg1T &arg1, const arg2T &arg2, const arg3T &arg3, const arg4T &arg4, const arg5T &arg5, const arg6T &arg6)
Sends message "resultT memfun(arg1T,arg2T,arg3T,arg4T,arg5T,arg6T)" to item (non-blocking comm if rem...
Definition worlddc.h:1712
Future< REMFUTURE(MEMFUN_RETURNT(memfunT))> send(const keyT &key, memfunT memfun, const arg1T &arg1, const arg2T &arg2)
Sends message "resultT memfun(arg1T,arg2T)" to item (non-blocking comm if remote)
Definition worlddc.h:1633
void replicate_on_hosts(bool fence=true)
replicates this WorldContainer on all hosts (one PID per host)
Definition worlddc.h:1359
void check_initialized() const
Definition worlddc.h:1248
WorldContainer< keyT, valueT, hashfunT > containerT
Definition worlddc.h:1235
Future< REMFUTURE(MEMFUN_RETURNT(memfunT))> task(const keyT &key, memfunT memfun, const arg1T &arg1, const arg2T &arg2, const arg3T &arg3, const arg4T &arg4, const arg5T &arg5, const arg6T &arg6, const arg7T &arg7, const TaskAttributes &attr=TaskAttributes()) const
Adds task "resultT memfun(arg1T,arg2T,arg3T,arg4T,arg5T,arg6T,arg7T) const" in process owning item (n...
Definition worlddc.h:2085
Future< REMFUTURE(MEMFUN_RETURNT(memfunT))> send(const keyT &key, memfunT memfun, const arg1T &arg1) const
Sends message "resultT memfun(arg1T) const" to item (non-blocking comm if remote)
Definition worlddc.h:1755
implT::accessor accessor
Definition worlddc.h:1240
Default process map is "random" using madness::hash(key)
Definition worlddc.h:261
ProcessID owner(const keyT &key) const
Maps key to processor.
Definition worlddc.h:272
WorldDCDefaultPmap(World &world, const hashfunT &hf=hashfunT())
Definition worlddc.h:267
const int nproc
Definition worlddc.h:263
hashfunT hashfun
Definition worlddc.h:264
Local process map will always return the current process as owner.
Definition worlddc.h:285
ProcessID owner(const keyT &key) const override
Maps key to processor.
Definition worlddc.h:291
WorldDCLocalPmap(World &world)
Definition worlddc.h:290
ProcessID me
Definition worlddc.h:287
DistributionType distribution_type() const override
by default the map is distributed
Definition worlddc.h:296
Definition worlddc.h:323
DistributionType distribution_type() const override
by default the map is distributed
Definition worlddc.h:339
WorldDCNodeReplicatedPmap(World &world, const std::map< std::string, std::vector< long > > ranks_per_host)
Definition worlddc.h:330
ProcessID myowner
Definition worlddc.h:324
ProcessID owner(const keyT &key) const override
owner is the lowest rank on the node, same for all keys
Definition worlddc.h:335
Interface to be provided by any process map.
Definition worlddc.h:125
void redistribute(World &world, const std::shared_ptr< WorldDCPmapInterface< keyT > > &newpmap)
Invoking this switches all registered objects from this process map to the new one.
Definition worlddc.h:180
virtual DistributionType distribution_type() const
by default the map is distributed
Definition worlddc.h:145
virtual ProcessID single_owner() const
Definition worlddc.h:153
void print_data_sizes(World &world, const std::string msg="") const
Prints size info to std::cout.
Definition worlddc.h:236
std::size_t global_size(World &world) const
Counts global number of entries in all containers associated with this process map.
Definition worlddc.h:213
virtual ProcessID owner(const keyT &key) const =0
Maps key to processor.
void deregister_callback(ptrT ptr)
Deregisters object for receipt of redistribute callbacks.
Definition worlddc.h:169
void register_callback(ptrT ptr)
Registers object for receipt of redistribute callbacks.
Definition worlddc.h:161
virtual void print() const
Definition worlddc.h:142
std::size_t local_size() const
Counts local number of entries in all containers associated with this process map.
Definition worlddc.h:223
std::set< ptrT > ptrs
Definition worlddc.h:131
virtual ~WorldDCPmapInterface()
Definition worlddc.h:140
WorldDCRedistributeInterface< keyT > * ptrT
Definition worlddc.h:127
virtual std::size_t size() const =0
virtual void redistribute_phase1(const std::shared_ptr< WorldDCPmapInterface< keyT > > &newmap)=0
virtual ~WorldDCRedistributeInterface()
Definition worlddc.h:80
Definition worlddc.h:309
WorldDCSingleOwnerPmap(ProcessID owner)
Definition worlddc.h:314
const ProcessID owner_
Definition worlddc.h:311
ProcessID owner(const keyT &) const override
Maps key to processor.
Definition worlddc.h:315
ProcessID single_owner() const override
Definition worlddc.h:316
void broadcast_serializable(objT &obj, ProcessID root)
Broadcast a serializable object.
Definition worldgop.h:774
void fence(bool debug=false)
Synchronizes all processes in communicator AND globally ensures no pending AM or tasks.
Definition worldgop.cc:176
void broadcast(void *buf, size_t nbyte, ProcessID root, bool dowork=true, Tag bcast_tag=-1)
Broadcasts bytes from process root while still processing AM & tasks.
Definition worldgop.cc:188
std::vector< T > concat0(const std::vector< T > &v, size_t bufsz=1024 *1024)
Concatenate an STL vector of serializable stuff onto node 0.
Definition worldgop.h:973
void sum(T *buf, size_t nelem)
Inplace global sum while still processing AM & tasks.
Definition worldgop.h:890
SafeMPI::Intracomm & comm()
Returns the associated SafeMPI communicator.
Definition worldmpi.h:286
void Send(const T *buf, long lenbuf, int dest, int tag=SafeMPI::DEFAULT_SEND_RECV_TAG) const
Send array of lenbuf elements to process dest.
Definition worldmpi.h:347
void Recv(T *buf, long lenbuf, int src, int tag) const
Receive data of up to lenbuf elements from process src.
Definition worldmpi.h:374
Implements most parts of a globally addressable object (via unique ID).
Definition world_object.h:491
detail::task_result_type< memfnT >::futureT send(ProcessID dest, memfnT memfn) const
Definition world_object.h:858
detail::task_result_type< memfnT >::futureT task(ProcessID dest, memfnT memfn, const TaskAttributes &attr=TaskAttributes()) const
Sends task to derived class method returnT (this->*memfn)().
Definition world_object.h:1132
Future< bool > for_each(const rangeT &range, const opT &op)
Apply op(item) on all items in range.
Definition world_task_queue.h:572
void add(TaskInterface *t)
Add a new local task, taking ownership of the pointer.
Definition world_task_queue.h:466
void fence()
Returns after all local tasks have completed.
Definition world_task_queue.h:1384
A parallel world class.
Definition world.h:134
WorldTaskQueue & taskq
Task queue.
Definition world.h:215
ProcessID rank() const
Returns the process rank in this World (same as MPI_Comm_rank()).
Definition world.h:344
WorldMpiInterface & mpi
MPI interface.
Definition world.h:213
ProcessID size() const
Returns the number of processes in this World (same as MPI_Comm_size()).
Definition world.h:354
WorldGopInterface & gop
Global operations.
Definition world.h:216
bool dofence() const
Check if we should fence around a read/write operation.
Definition parallel_archive.h:295
World * get_world() const
Returns a pointer to the world.
Definition parallel_archive.h:130
bool is_io_node() const
Returns true if this node is doing physical I/O.
Definition parallel_archive.h:122
int num_io_clients() const
Returns the number of I/O clients for this node, including self (zero if not an I/O node).
Definition parallel_archive.h:114
ProcessID io_node(ProcessID rank) const
Returns the process doing I/O for given node.
Definition parallel_archive.h:99
ProcessID my_io_node() const
Returns the process doing I/O for this node.
Definition parallel_archive.h:106
Archive & local_archive() const
Returns a reference to the local archive.
Definition parallel_archive.h:248
Wraps an archive around a memory buffer for input.
Definition buffer_archive.h:134
Wraps an archive around a memory buffer for output.
Definition buffer_archive.h:59
std::size_t size() const
Return the amount of data stored (counted) in the buffer.
Definition buffer_archive.h:123
Archive allowing buffering, deserialization of data, and point-to-point communication between process...
Definition mpi_archive.h:180
Archive allowing buffering, serialization of data, and point-to-point communication between processes...
Definition mpi_archive.h:118
void flush() const
Send all data in the buffer to the destination process.
Definition mpi_archive.h:158
An archive for storing local or parallel data, wrapping a BinaryFstreamInputArchive.
Definition parallel_archive.h:366
An archive for storing local or parallel data wrapping a BinaryFstreamOutputArchive.
Definition parallel_archive.h:321
Objects that implement their own parallel archive interface should derive from this class.
Definition parallel_archive.h:58
Wraps an archive around an STL vector for output.
Definition vector_archive.h:55
Class for unique global IDs.
Definition uniqueid.h:53
char * p(char *buf, const char *name, int k, int initial_level, double thresh, int order)
Definition derivatives.cc:72
void run(World &world, ansatzT ansatz, const int nuclear_charge, const commandlineparser &parser, const int nstates)
Definition dirac-hatom.cc:1392
static void load(const ParallelInputArchive< localarchiveT > &ar, WorldContainer< keyT, valueT > &t)
Read container from parallel archive.
Definition worlddc.h:2466
static const double v
Definition hatom_sf_dirac.cc:20
#define MADNESS_CHECK(condition)
Check a condition — even in a release build the condition is always evaluated so it can have side eff...
Definition madness_exception.h:182
#define MADNESS_EXCEPTION(msg, value)
Macro for throwing a MADNESS exception.
Definition madness_exception.h:119
#define MADNESS_ASSERT(condition)
Assert a condition that should be free of side-effects since in release builds this might be a no-op.
Definition madness_exception.h:134
#define MADNESS_CHECK_THROW(condition, msg)
Check a condition — even in a release build the condition is always evaluated so it can have side eff...
Definition madness_exception.h:207
Implements archives to serialize data for MPI.
void deferred_cleanup(World &world, const std::shared_ptr< objT > &p, bool assume_p_is_unique=false)
Defer the cleanup of a shared pointer to the end of the next fence.
Definition deferred_cleanup.h:135
Namespace for all elements and tools of MADNESS.
Definition DFParameters.h:13
DistributionType from_string(std::string type)
Definition worlddc.h:106
std::ostream & operator<<(std::ostream &os, const particle< PDIM > &p)
Definition lowrankfunction.h:401
std::string to_string(const Representation r)
Definition Restart.h:64
DistributionType
some introspection of how data is distributed
Definition worlddc.h:84
@ NodeReplicated
even if there are several ranks per node
Definition worlddc.h:87
@ Distributed
no replication of the container, the container is distributed over the world
Definition worlddc.h:85
@ RankReplicated
replicate the container over all world ranks
Definition worlddc.h:86
std::vector< int > primary_ranks_per_host(World &world, const std::map< std::string, std::vector< long > > &ranks_per_host1)
Definition ranks_and_hosts.cpp:94
DistributionType validate_distribution_type(const dcT &dc)
check distribution type of WorldContainer – global communication
Definition worlddc.h:347
void print(const T &t, const Ts &... ts)
Print items to std::cout (items separated by spaces) and terminate with a new line.
Definition print.h:227
NDIM & f
Definition mra.h:2620
double wall_time()
Returns the wall time in seconds relative to an arbitrary origin.
Definition timers.cc:48
std::string type(const PairType &n)
Definition PNOParameters.h:18
long lowest_rank_on_host_of_rank(const std::map< std::string, std::vector< long > > ranks_per_host1, int rank)
Definition ranks_and_hosts.cpp:81
std::map< std::string, std::vector< long > > ranks_per_host(World &universe)
for each host, return a list of its ranks
Definition ranks_and_hosts.cpp:60
void swap(Function< R, MDIM > &f1, Function< R, MDIM > &f2)
Definition mra.h:2952
Definition mraimpl.h:51
void advance(madness::Hash_private::HashIterator< hashT > &it, const distT &dist)
Definition worldhashmap.h:610
static const double d
Definition nonlinschro.cc:121
Implements ParallelInputArchive and ParallelOutputArchive for parallel serialization of data.
static const double c
Definition relops.cc:10
Definition test_dc.cc:47
Definition worlddc.h:1104
bool operator()(typename rangeT::iterator &iterator) const
Definition worlddc.h:1109
implT * impl
Definition worlddc.h:1105
P2Op(const P2Op &p)
Definition worlddc.h:1108
P2Op(implT *impl)
Definition worlddc.h:1107
Range< typename std::vector< keyT >::const_iterator > rangeT
Definition worlddc.h:1106
World & world
Memoized reference to the world to which this object belongs.
Definition world_object.h:348
World & get_world() const
Definition world_object.h:446
Default load of an object via serialize(ar, t).
Definition archive.h:667
static void postamble_store(const Archive &)
By default there is no postamble.
Definition archive.h:546
static void preamble_store(const Archive &ar)
Serialize a cookie for type checking.
Definition archive.h:536
static void store(const ParallelOutputArchive< VectorOutputArchive > &ar, const WorldContainer< keyT, valueT > &t)
Definition worlddc.h:2190
static void store(const ParallelOutputArchive< localarchiveT > &ar, const WorldContainer< keyT, valueT > &t)
Definition worlddc.h:2397
Default store of an object via serialize(ar, t).
Definition archive.h:612
int MPI_Gatherv(const void *sendbuf, int sendcount, MPI_Datatype sendtype, void *recvbuf, const int recvcounts[], const int[], MPI_Datatype recvtype, int, MPI_Comm)
Definition stubmpi.h:218
#define MPI_INT
Definition stubmpi.h:81
#define MPI_BYTE
Definition stubmpi.h:77
int MPI_Gather(const void *sendbuf, int sendcount, MPI_Datatype sendtype, void *recvbuf, int recvcount, MPI_Datatype recvtype, int root, MPI_Comm comm)
Definition stubmpi.h:233
AtomicInt sum
Definition test_atomicint.cc:46
std::pair< int, double > valueT
Definition test_binsorter.cc:6
int me
Definition test_binsorter.cc:10
const double offset
Definition testfuns.cc:143
double source(const coordT &r)
Definition testperiodic.cc:48
#define REMFUTURE(T)
Macro to determine type of future (by removing wrapping Future template).
Definition type_traits.h:163
#define MEMFUN_RETURNT(MEMFUN)
Macro to make member function type traits easier to use.
Definition type_traits.h:773
Defines and implements WorldObject.
Defines and implements a concurrent hashmap.
int ProcessID
Used to clearly identify process number/rank.
Definition worldtypes.h:43
int Tag
Used to clearly identify message tag/type.
Definition worldtypes.h:44