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;
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);
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
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 bool rank_replication_complete_ = false; ///< True if the last replicate() completed and no reset followed
599 const ProcessID me; ///< My MPI rank
600 internal_containerT local; ///< Locally owned data
601 std::vector<keyT> *move_list; ///< Tempoary used to record data that needs redistributing
602 std::map<ProcessID, std::vector<keyT>> coalesced_move_; ///< Temporary: keys to move, bucketed by destination (coalesced redistribute)
603
604 /// Handles find request
605 void find_handler(ProcessID requestor, const keyT &key, const RemoteReference<FutureImpl<iterator>> &ref)
606 {
608 if (r == local.end())
609 {
610 // print("find_handler: failure:", key);
611 this->send(requestor, &implT::find_failure_handler, ref);
612 }
613 else
614 {
615 // print("find_handler: success:", key, r->first, r->second);
616 this->send(requestor, &implT::find_success_handler, ref, *r);
617 }
618 }
619
620 /// Handles successful find response
622 {
623 FutureImpl<iterator> *f = ref.get();
624 f->set(iterator(datum));
625 // print("find_success_handler: success:", datum.first, datum.second, f->get()->first, f->get()->second);
626 // Todo: Look at this again.
627 // ref.reset(); // Matching inc() in find() where ref was made
628 }
629
630 /// Handles unsuccessful find response
632 {
633 FutureImpl<iterator> *f = ref.get();
634 f->set(end());
635 // print("find_failure_handler");
636 // Todo: Look at this again.
637 // ref.reset(); // Matching inc() in find() where ref was made
638 }
639
640 /// Handles const find request
642 {
644 if (r == local.end())
645 {
646 this->send(requestor, &implT::find_const_failure_handler, ref);
647 }
648 else
649 {
650 this->send(requestor, &implT::find_const_success_handler, ref, *r);
651 }
652 }
653
654 /// Handles successful const find response
656 {
658 f->set(const_iterator(datum));
659 }
660
661 /// Handles unsuccessful const find response
667
668 public:
670 const std::shared_ptr<WorldDCPmapInterface<keyT>> &pm,
671 const hashfunT &hf)
672 : WorldObject<WorldContainerImpl<keyT, valueT, hashfunT>>(world), pmap(pm), me(world.mpi.rank()), local(5011, hf)
673 {
674 pmap->register_callback(this);
675 }
676
678 {
679 pmap->deregister_callback(this);
680 }
681
682 const std::shared_ptr<WorldDCPmapInterface<keyT>> &get_pmap() const
683 {
684 return pmap;
685 }
686
687 std::shared_ptr<WorldDCPmapInterface<keyT>> &get_pmap()
688 {
689 return pmap;
690 }
691
693 {
695 pmap->deregister_callback(this);
696 pmap.reset(new WorldDCLocalPmap<keyT>(this->get_world()));
697 pmap->register_callback(this);
698 }
699
700 /// Replicates this WorldContainer on every ProcessID.
701 ///
702 /// This call is collective, and every rank must call it in the same order.
703 /// If no rank called clear(), reset the pmap, or redistributed after the
704 /// last completed call, this call sends no data. A requested fence still
705 /// occurs. This call does not reconcile replicas, so per-key changes must
706 /// be the same on every rank.
707 ///
708 /// A rank runs queued tasks while it waits in a broadcast. These tasks must
709 /// not change this container until the call returns. If a task erases a key
710 /// on the root, MADNESS_CHECK throws on that rank, and the other ranks wait.
711 void replicate(bool fence) {
712 World &world = this->get_world();
713
714 // clear() is local, so the ranks can disagree about the flag. All ranks
715 // take the fast path only if all ranks agree.
716 int complete = rank_replication_complete_ ? 1 : 0;
718 if (complete) {
719 MADNESS_CHECK(pmap->distribution_type() == RankReplicated);
720 if (fence) world.gop.fence();
721 return;
722 }
723
724 pmap->deregister_callback(this);
726 pmap->register_callback(this);
727
730 if (fence) world.gop.fence();
731 }
732
733 /// Replicates this WorldContainer on all hosts, one ProcessID per host.
734 ///
735 /// The new pmap is host-local, not rank-local. This call always fences.
736 /// Queued tasks must not change this container until the call returns.
737 void replicate_on_hosts(bool fence) {
738 MADNESS_CHECK(fence);
740
741 /// print in rank-order
742// auto oprint = [&](World& world, auto &&... args) {
743// world.gop.fence();
744// for (int r=0; r<world.size(); ++r) {
745// if (r==world.rank()) {
746// std::cout << "rank " << world.rank() << ": ";
747// print(std::forward<decltype(args)>(args)...);
748// }
749// world.gop.fence();
750// }
751// };
752
753 World &world = this->get_world();
754
755 // find primary ranks per host (lowest rank on each host)
759 world.gop.fence();
760
761// auto sizes =[&](std::string msg) {
762// world.gop.fence();
763// auto local_size=size();
764// auto global_size=local_size;
765// world.gop.sum(global_size);
766// oprint(world,"rank, local, global",msg, world.rank(),local_size,global_size);
767// world.gop.fence();
768// };
769
770 // change pmap to replicated
771 pmap->deregister_callback(this);
773 pmap->register_callback(this);
774
775 // shortcut: replace pmap and return
776 if (world.size()==1) {
777 // change pmap to node replicated
778 pmap->deregister_callback(this);
780 pmap->register_callback(this);
781 return;
782 }
783 world.gop.fence();
784
785 // get a list of all other ranks that are not primary
786 std::vector<int> secondary_ranks;
787 for (int r=0; r<world.size(); ++r) {
788 if (std::find(primary_ranks.begin(),primary_ranks.end(),r)==primary_ranks.end())
789 secondary_ranks.push_back(r);
790 }
791
792 // phase 1: for all ranks send data to the lowest rank on host
793
794 // step 1-2: send data to lowest rank on host (which will become the owner)
796 // oprint(world,"my owner, size:", myowner,size());
797 if (world.rank() != myowner) {
798 // send data to myowner
799 for (auto it = begin(); it != end(); ++it) {
800 keyT key = it->first;
801 valueT value = it->second;
802 this->send(myowner,&implT::insert,pairT(key,value));
803 // insert(pairT(key,value)); // this won't work with LocalPmap
804 }
805 // remove all local data after sending
806 // clear();
807 }
808 // need a fence here to make sure send is finished
809 world.gop.fence();
810 // sizes("after step 1, before clear");
811 // world.gop.fence();
812 if (world.rank()!=myowner) clear();
813 world.gop.fence();
814 // sizes("after step 1");
815
816 // change pmap to replicated
817 pmap->deregister_callback(this);
819 pmap->register_callback(this);
820
821 // check if this rank is in the primary list
822 bool i_am_in_primary_list=world.rank()==myowner;
824
825 // step 2-1: create a world with only the primary ranks and replicate there (see test_world.cc)
826
829 // step 2-2: replicate in the primary world
830 {
832 // auto ranks_per_host1=ranks_per_host(world_primary);
833 // if (world_primary.rank()==0) {
834 // print("host/rank map in primary world:");
835 // for (auto& p : ranks_per_host1) print(p.first, p.second);
836 // }
837
838 world_primary.gop.fence(); // this fence seems necessary, why??
840 world_primary.gop.fence();
841 }
842 } else {
843 // need this to avoid deadlock in MPI_Comm_create (why??)
846 }
847
848 // phase 3: done
849 if (fence) world.gop.fence();
850 // validate_distribution_type(*this);
851 }
852
854 // Received entries go to a side buffer, not into local, so each
855 // rank broadcasts only the entries it held on entry and every entry
856 // is sent exactly once. Inserting as we go would make later roots
857 // re-broadcast what they received from earlier ones.
858 std::vector<pairT> received;
859 for (ProcessID rank = 0; rank < world.size(); rank++)
860 {
861 if (rank == world.rank())
862 {
863 std::size_t sz = size();
865
866 for (auto it = begin(); it != end(); ++it)
867 {
868 keyT key = it->first;
869 valueT value = it->second;
871 world.gop.broadcast_serializable(value, rank);
872 }
873 }
874 else
875 {
876 size_t sz = 0;
878 received.reserve(received.size() + sz);
879 for (size_t i = 0; i < sz; i++)
880 {
881 keyT key{};
882 valueT value{};
884 world.gop.broadcast_serializable(value, rank);
885 received.emplace_back(std::move(key), std::move(value));
886 }
887 }
888 }
889 for (auto& datum : received)
890 insert(datum);
891 }
892
893 const hashfunT &get_hash() const { return local.get_hash(); }
894
895 bool is_local(const keyT &key) const
896 {
897 return owner(key) == me;
898 }
899
900 ProcessID owner(const keyT &key) const
901 {
902 return pmap->owner(key);
903 }
904
905 bool probe(const keyT &key) const
906 {
907 ProcessID dest = owner(key);
908 if (dest == me)
909 return local.find(key) != local.end();
910 else
911 return false;
912 }
913
914 std::size_t size() const
915 {
916 return local.size();
917 }
918
919 void insert(const pairT &datum)
920 {
921 ProcessID dest = owner(datum.first);
922 if (dest == me)
923 {
924 // Was using iterator ... try accessor ?????
926 // N.B. key might already exist if want to simply replace
927 [[maybe_unused]] auto inserted = local.insert(acc, datum.first);
928 acc->second = datum.second;
929 }
930 else
931 {
932 // Must be send (not task) for sequential consistency (and relies on single-threaded remote server)
933 this->send(dest, &implT::insert, datum);
934 }
935 }
936
937 bool insert_acc(accessor &acc, const keyT &key)
938 {
939 MADNESS_ASSERT(owner(key) == me);
940 return local.insert(acc, key);
941 }
942
944 {
945 MADNESS_ASSERT(owner(key) == me);
946 return local.insert(acc, key);
947 }
948
949 /// AM target of the coalesced redistribute: bulk-insert boxes this rank owns
950 /// under the already-adopted new pmap. Keys are disjoint from those this rank
951 /// is concurrently erasing (their new owner != me), so per-bucket locking
952 /// suffices. See redistribute_coalesced_phase2.
953 void insert_batch(const std::vector<pairT> &boxes)
954 {
955 for (const pairT &kv : boxes)
956 {
958 [[maybe_unused]] auto inserted = local.insert(acc, kv.first);
959 acc->second = kv.second;
960 }
961 }
962
963 void clear()
964 {
966 local.clear();
967 }
968
969 void erase(const keyT &key)
970 {
971 ProcessID dest = owner(key);
972 if (dest == me)
973 {
974 [[maybe_unused]] auto erased = local.try_erase(key);
976 }
977 else
978 {
979 void (implT::*eraser)(const keyT &) = &implT::erase;
980 this->send(dest, eraser, key);
981 }
982 }
983
984 template <typename InIter>
985 void erase(InIter it)
986 {
987 MADNESS_ASSERT(!it.is_cached());
988 MADNESS_ASSERT(it != end());
989 erase(it->first);
990 }
991
992 template <typename InIter>
994 {
995 InIter it = first;
996 do
997 {
998 first++;
999 erase(it->first);
1000 it = first;
1001 } while (first != last);
1002 }
1003
1005 {
1006 return iterator(local.begin());
1007 }
1008
1010 {
1011 return const_iterator(local.begin());
1012 }
1013
1015 {
1016 return iterator(local.end());
1017 }
1018
1020 {
1021 return const_iterator(local.end());
1022 }
1023
1025 {
1026 ProcessID dest = owner(key);
1027 if (dest == me)
1028 {
1030 }
1031 else
1032 {
1034 this->send(dest, &implT::find_const_handler, me, key, result.remote_ref(this->get_world()));
1035 return result;
1036 }
1037 }
1038
1040 {
1041 ProcessID dest = owner(key);
1042 if (dest == me)
1043 {
1044 return Future<iterator>(iterator(local.find(key)));
1045 }
1046 else
1047 {
1048 Future<iterator> result;
1049 this->send(dest, &implT::find_handler, me, key, result.remote_ref(this->get_world()));
1050 return result;
1051 }
1052 }
1053
1054 bool find(accessor &acc, const keyT &key)
1055 {
1056 if (owner(key) != me)
1057 return false;
1058 return local.find(acc, key);
1059 }
1060
1061 bool find(const_accessor &acc, const keyT &key) const
1062 {
1063 if (owner(key) != me)
1064 return false;
1065 return local.find(acc, key);
1066 }
1067
1068 // Used to forward call to item member function
1069 template <typename memfunT>
1071 itemfun(const keyT &key, memfunT memfun)
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)();
1077 }
1078
1079 // Used to forward call to item member function
1080 template <typename memfunT, typename arg1T>
1082 itemfun(const keyT &key, memfunT memfun, const arg1T &arg1)
1083 {
1084 accessor acc;
1085 // N.B. key may already exist, this is just to ensure lock is held by acc
1086 [[maybe_unused]] auto inserted = local.insert(acc, key);
1087 return (acc->second.*memfun)(arg1);
1088 }
1089
1090 // Used to forward call to item member function
1091 template <typename memfunT, typename arg1T, typename arg2T>
1093 itemfun(const keyT &key, memfunT memfun, const arg1T &arg1, const arg2T &arg2)
1094 {
1095 accessor acc;
1096 // N.B. key may already exist, this is just to ensure lock is held by acc
1097 [[maybe_unused]] auto inserted = local.insert(acc, key);
1098 return (acc->second.*memfun)(arg1, arg2);
1099 }
1100
1101 // Used to forward call to item member function
1102 template <typename memfunT, typename arg1T, typename arg2T, typename arg3T>
1104 itemfun(const keyT &key, memfunT memfun, const arg1T &arg1, const arg2T &arg2, const arg3T &arg3)
1105 {
1106 accessor acc;
1107 // N.B. key may already exist, this is just to ensure lock is held by acc
1108 [[maybe_unused]] auto inserted = local.insert(acc, key);
1109 return (acc->second.*memfun)(arg1, arg2, arg3);
1110 }
1111
1112 // Used to forward call to item member function
1113 template <typename memfunT, typename arg1T, typename arg2T, typename arg3T, typename arg4T>
1115 itemfun(const keyT &key, memfunT memfun, const arg1T &arg1, const arg2T &arg2, const arg3T &arg3, const arg4T &arg4)
1116 {
1117 accessor acc;
1118 // N.B. key may already exist, this is just to ensure lock is held by acc
1119 [[maybe_unused]] auto inserted = local.insert(acc, key);
1120 return (acc->second.*memfun)(arg1, arg2, arg3, arg4);
1121 }
1122
1123 // Used to forward call to item member function
1124 template <typename memfunT, typename arg1T, typename arg2T, typename arg3T, typename arg4T, typename arg5T>
1126 itemfun(const keyT &key, memfunT memfun, const arg1T &arg1, const arg2T &arg2, const arg3T &arg3, const arg4T &arg4, const arg5T &arg5)
1127 {
1128 accessor acc;
1129 // N.B. key may already exist, this is just to ensure lock is held by acc
1130 [[maybe_unused]] auto inserted = local.insert(acc, key);
1131 return (acc->second.*memfun)(arg1, arg2, arg3, arg4, arg5);
1132 }
1133
1134 // Used to forward call to item member function
1135 template <typename memfunT, typename arg1T, typename arg2T, typename arg3T, typename arg4T, typename arg5T, typename arg6T>
1137 itemfun(const keyT &key, memfunT memfun, const arg1T &arg1, const arg2T &arg2, const arg3T &arg3, const arg4T &arg4, const arg5T &arg5, const arg6T &arg6)
1138 {
1139 accessor acc;
1140 // N.B. key may already exist, this is just to ensure lock is held by acc
1141 [[maybe_unused]] auto inserted = local.insert(acc, key);
1142 return (acc->second.*memfun)(arg1, arg2, arg3, arg4, arg5, arg6);
1143 }
1144
1145 // Used to forward call to item member function
1146 template <typename memfunT, typename arg1T, typename arg2T, typename arg3T, typename arg4T, typename arg5T, typename arg6T, typename arg7T>
1148 itemfun(const keyT &key, memfunT memfun, const arg1T &arg1, const arg2T &arg2, const arg3T &arg3,
1149 const arg4T &arg4, const arg5T &arg5, const arg6T &arg6, const arg7T &arg7)
1150 {
1151 accessor acc;
1152 // N.B. key may already exist, this is just to ensure lock is held by acc
1153 [[maybe_unused]] auto inserted = local.insert(acc, key);
1154 return (acc->second.*memfun)(arg1, arg2, arg3, arg4, arg5, arg6, arg7);
1155 }
1156
1157 // First phase of redistributions changes pmap and makes list of stuff to move
1159 {
1161 pmap = newpmap;
1162 move_list = new std::vector<keyT>();
1163 for (typename internal_containerT::iterator iter = local.begin(); iter != local.end(); ++iter)
1164 {
1165 if (owner(iter->first) != me)
1166 move_list->push_back(iter->first);
1167 }
1168 }
1169
1170 struct P2Op
1171 {
1175 P2Op(const P2Op &p) : impl(p.impl) {}
1177 {
1179 MADNESS_ASSERT(iter != impl->local.end());
1180
1181 // impl->insert(*iter);
1182 impl->task(impl->owner(*iterator), &implT::insert, *iter);
1183
1184 impl->local.erase(iter); // delete local copy of the data
1185 return true;
1186 }
1187 };
1188
1189 // Second phase moves data
1191 {
1192 this->get_world().taskq.for_each(typename P2Op::rangeT(move_list->begin(), move_list->end()), P2Op(this));
1193 // std::vector<keyT>& mvlist = *move_list;
1194 // for (unsigned int i=0; i<move_list->size(); ++i) {
1195 // typename internal_containerT::iterator iter = local.find(mvlist[i]);
1196 // MADNESS_ASSERT(iter != local.end());
1197 // insert(*iter);
1198 // local.erase(iter);
1199 // }
1200 // delete move_list;
1201 }
1202
1203 // Third phase cleans up
1205 {
1206 delete move_list;
1207 }
1208
1209 // --- Coalesced redistribute: like redistribute_phase1/2, but phase2 sends ONE
1210 // bulk AM per (destination, chunk) instead of one AM per box. The caller owns
1211 // the fences: fence, phase1 on all containers, fence, phase2, fence. The middle
1212 // fence is REQUIRED -- phase1 iterates the ConcurrentHashMap and needs a
1213 // quiescent window; phase2 tolerates concurrent insert_batch (disjoint keys).
1214
1215 /// phase1: adopt newpmap (callback swap as in replicate()) and bucket the keys
1216 /// to move by destination. Quiescent window required.
1218 {
1220 pmap->deregister_callback(this);
1221 pmap = newpmap;
1222 pmap->register_callback(this);
1223 coalesced_move_.clear();
1224 for (typename internal_containerT::iterator iter = local.begin(); iter != local.end(); ++iter)
1225 {
1226 ProcessID d = owner(iter->first); // uses the new pmap
1227 if (d != me)
1228 coalesced_move_[d].push_back(iter->first);
1229 }
1230 }
1231
1232 /// phase2: per destination, chunk the key list (at most cap_boxes per chunk),
1233 /// erase each box after copying it into the batch, send one insert_batch AM
1234 /// per chunk.
1235 void redistribute_coalesced_phase2(std::size_t cap_boxes, bool rotate)
1236 {
1237 if (cap_boxes == 0) cap_boxes = 1;
1238 std::vector<ProcessID> dsts;
1239 dsts.reserve(coalesced_move_.size());
1240 for (const auto &kv : coalesced_move_) dsts.push_back(kv.first);
1241 // rotate: destinations > me first, so ranks don't all hammer dst 0 at once
1242 if (rotate)
1243 std::stable_partition(dsts.begin(), dsts.end(),
1244 [this](ProcessID d) { return d > me; });
1245 for (ProcessID d : dsts)
1246 {
1247 const std::vector<keyT> &keys = coalesced_move_[d];
1248 std::vector<pairT> batch;
1249 batch.reserve(std::min(cap_boxes, keys.size()));
1250 for (std::size_t i = 0; i < keys.size(); ++i)
1251 {
1252 typename internal_containerT::iterator iter = local.find(keys[i]);
1253 if (iter != local.end())
1254 {
1255 batch.push_back(pairT(keys[i], iter->second));
1256 local.erase(iter); // delete local copy of the data
1257 }
1258 if (batch.size() >= cap_boxes || i + 1 == keys.size())
1259 {
1260 if (!batch.empty())
1261 {
1262 this->task(d, &implT::insert_batch, batch); // one bulk AM per chunk
1263 batch.clear();
1264 }
1265 }
1266 }
1267 }
1268 coalesced_move_.clear();
1269 }
1270 };
1271
1272 /// Makes a distributed container with specified attributes
1273
1274 /// \ingroup worlddc
1275 ///
1276 /// There is no communication or syncronization associated with
1277 /// making a new container, but every process must invoke the
1278 /// constructor for each container in the same order. This is so
1279 /// that we can assign each container a unique ID without any
1280 /// communication. Since remotely invoked operations may start
1281 /// happening before local construction, messages on not yet
1282 /// constructed containers are buffered pending construction.
1283 ///
1284 /// Similarly, when a container is destroyed, the actual
1285 /// destruction is deferred until a synchronization point
1286 /// (world.gop.fence()) in order to eliminate the need to fence
1287 /// before destroying every container.
1288 ///
1289 /// The distribution of data between processes is controlled by
1290 /// the process map (Pmap) class. The default is uniform
1291 /// hashing based upon a strong (Bob Jenkins, lookup3) bytewise
1292 /// hash of the key.
1293 ///
1294 /// All operations, including constructors and destructors, are
1295 /// non-blocking and return immediately. If communication occurs
1296 /// it is asynchronous, otherwise operations are local.
1297 template <typename keyT, typename valueT, typename hashfunT = Hash<keyT>>
1299 {
1300 public:
1301 // access keyT and valueT types for serialization
1305 typedef typename implT::pairT pairT;
1306 typedef typename implT::iterator iterator;
1308 typedef typename implT::accessor accessor;
1312
1313 private:
1314 std::shared_ptr<implT> p;
1315
1316 inline void check_initialized() const
1317 {
1319 }
1320
1321 public:
1322 /// Makes an uninitialized container (no communication)
1323
1324 /// The container is useless until assigned to from a fully
1325 /// constructed container. There is no need to worry about
1326 /// default constructors being executed in order.
1328 : p()
1329 {
1330 }
1331
1332 /// Makes an initialized, empty container with default data distribution (no communication)
1333
1334 /// A unique ID is associated with every distributed container
1335 /// within a world. In order to avoid synchronization when
1336 /// making a container, we have to assume that all processes
1337 /// execute this constructor in the same order (does not apply
1338 /// to the non-initializing, default constructor).
1339 WorldContainer(World &world, bool do_pending = true, const hashfunT &hf = hashfunT())
1340 : p(new implT(world,
1342 hf))
1343 {
1344 if (do_pending)
1345 p->process_pending();
1346 }
1347
1348 /// Makes an initialized, empty container (no communication)
1349
1350 /// A unique ID is associated with every distributed container
1351 /// within a world. In order to avoid synchronization when
1352 /// making a container, we have to assume that all processes
1353 /// execute this constructor in the same order (does not apply
1354 /// to the non-initializing, default constructor).
1356 const std::shared_ptr<WorldDCPmapInterface<keyT>> &pmap,
1357 bool do_pending = true,
1358 const hashfunT &hf = hashfunT())
1359 : p(new implT(world, pmap, hf))
1360 {
1361 if (do_pending)
1362 p->process_pending();
1363 }
1364
1365 /// Copy constructor is shallow (no communication)
1366
1367 /// The copy refers to exactly the same container as other
1368 /// which must be initialized.
1370 : p(other.p)
1371 {
1373 }
1374
1375 /// Assignment is shallow (no communication)
1376
1377 /// The copy refers to exactly the same container as other
1378 /// which must be initialized.
1380 {
1381 if (this != &other)
1382 {
1383 other.check_initialized();
1384 p = other.p;
1385 }
1386 return *this;
1387 }
1388
1389 /// return the way data is distributed
1391 if (!p) MADNESS_EXCEPTION("Uninitialized container", false);
1392 return p->get_pmap()->distribution_type();
1393 }
1394
1395 bool is_distributed() const {
1397 }
1398
1399 bool is_replicated() const {
1401 }
1402
1403 bool is_host_replicated() const {
1405 }
1406
1407 /// Returns the world associated with this container
1409 {
1411 return p->get_world();
1412 }
1413
1414 std::shared_ptr<WorldDCPmapInterface<keyT>> &get_impl()
1415 {
1417 return p;
1418 }
1419
1420 /// Replicates this WorldContainer on all ProcessIDs.
1421 ///
1422 /// This call is collective. Queued tasks must not change this container
1423 /// until the call returns. See WorldContainerImpl::replicate().
1424 void replicate(bool fence = true)
1425 {
1426 p->replicate(fence);
1427 }
1428
1429 /// replicates this WorldContainer on all hosts (one PID per host)
1430 void replicate_on_hosts(bool fence = true)
1431 {
1432 p->replicate_on_hosts(fence);
1433 }
1434
1435 /// Coalesced redistribute, phase 1: adopt newpmap, bucket the move list.
1436 /// Caller fences before (quiescent window).
1438 {
1440 p->redistribute_coalesced_phase1(newpmap);
1441 }
1442
1443 /// Coalesced redistribute, phase 2: one bulk AM per (destination, chunk of at
1444 /// most cap_boxes), erase-after-copy. Caller fences after; rotate staggers
1445 /// destinations to reduce incast.
1446 void redistribute_coalesced_phase2(std::size_t cap_boxes, bool rotate = true)
1447 {
1449 p->redistribute_coalesced_phase2(cap_boxes, rotate);
1450 }
1451
1452 /// Inserts/replaces key+value pair (non-blocking communication if key not local)
1453 void replace(const pairT &datum)
1454 {
1456 p->insert(datum);
1457 }
1458
1459 /// Inserts/replaces key+value pair (non-blocking communication if key not local)
1460 void replace(const keyT &key, const valueT &value)
1461 {
1462 replace(pairT(key, value));
1463 }
1464
1465 /// Write access to LOCAL value by key. Returns true if found, false otherwise (always false for remote).
1466 bool find(accessor &acc, const keyT &key)
1467 {
1469 return p->find(acc, key);
1470 }
1471
1472 /// Read access to LOCAL value by key. Returns true if found, false otherwise (always false for remote).
1473 bool find(const_accessor &acc, const keyT &key) const
1474 {
1476 return p->find(acc, key);
1477 }
1478
1479 /// Write access to LOCAL value by key. Returns true if inserted, false if already exists (throws if remote)
1480 bool insert(accessor &acc, const keyT &key)
1481 {
1483 return p->insert_acc(acc, key);
1484 }
1485
1486 /// Read access to LOCAL value by key. Returns true if inserted, false if already exists (throws if remote)
1487 bool insert(const_accessor &acc, const keyT &key)
1488 {
1490 return p->insert_acc(acc, key);
1491 }
1492
1493 /// Inserts pairs (non-blocking communication if key(s) not local)
1494 template <typename input_iterator>
1496 {
1498 using std::placeholders::_1;
1499 std::for_each(start, end, std::bind(this, std::mem_fn(&containerT::insert), _1));
1500 }
1501
1502 /// Returns true if local data is immediately available (no communication)
1503 bool probe(const keyT &key) const
1504 {
1506 return p->probe(key);
1507 }
1508
1509 /// Returns processor that logically owns key (no communication)
1510
1511 /// Local remapping may have changed its physical location, but all
1512 /// operations should forward correctly.
1513 inline ProcessID owner(const keyT &key) const
1514 {
1516 return p->owner(key);
1517 }
1518
1519 /// Returns true if the key maps to the local processor (no communication)
1520 bool is_local(const keyT &key) const
1521 {
1523 return p->is_local(key);
1524 }
1525
1526 /// Returns a future iterator (non-blocking communication if key not local)
1527
1528 /// Like an std::map an iterator "points" to an std::pair<const keyT,valueT>.
1529 ///
1530 /// Refer to Future for info on how to avoid blocking.
1532 { //
1534 return p->find(key);
1535 }
1536
1537 /// Returns a future iterator (non-blocking communication if key not local)
1538
1539 /// Like an std::map an iterator "points" to an std::pair<const keyT,valueT>.
1540 ///
1541 /// Refer to Future for info on how to avoid blocking.
1543 {
1545 return const_cast<const implT *>(p.get())->find(key);
1546 }
1547
1548 /// Returns an iterator to the beginning of the \em local data (no communication)
1550 {
1552 return p->begin();
1553 }
1554
1555 /// Returns an iterator to the beginning of the \em local data (no communication)
1557 {
1559 return const_cast<const implT *>(p.get())->begin();
1560 }
1561
1562 /// Returns an iterator past the end of the \em local data (no communication)
1564 {
1566 return p->end();
1567 }
1568
1569 /// Returns an iterator past the end of the \em local data (no communication)
1571 {
1573 return const_cast<const implT *>(p.get())->end();
1574 }
1575
1576 /// Erases entry from container (non-blocking comm if remote)
1577
1578 /// Missing keys are quietly ignored.
1579 ///
1580 /// Note that erasing an entry may invalidate iterators on the
1581 /// remote end. This is just the same as what happens when
1582 /// using STL iterators on an STL container in a sequential
1583 /// algorithm.
1584 void erase(const keyT &key)
1585 {
1587 p->erase(key);
1588 }
1589
1590 /// Erases entry corresponding to \em local iterator (no communication)
1591 void erase(const iterator &it)
1592 {
1594 p->erase(it);
1595 }
1596
1597 /// Erases range defined by \em local iterators (no communication)
1598 void erase(const iterator &start, const iterator &finish)
1599 {
1601 p->erase(start, finish);
1602 }
1603
1604 /// Clears all \em local data (no communication)
1605
1606 /// Invalidates all iterators
1607 void clear()
1608 {
1610 p->clear();
1611 }
1612
1613 /// Returns the number of \em local entries (no communication)
1614 std::size_t size() const
1615 {
1617 return p->size();
1618 }
1619
1620 /// Returns shared pointer to the process mapping
1621 inline const std::shared_ptr<WorldDCPmapInterface<keyT>> &get_pmap() const
1622 {
1624 return p->get_pmap();
1625 }
1626
1627 /// Returns shared pointer to the process mapping
1629 {
1630 p->reset_pmap_to_local();
1631 }
1632
1633 /// Returns a reference to the hashing functor
1634 const hashfunT &get_hash() const
1635 {
1637 return p->get_hash();
1638 }
1639
1640 /// Process pending messages
1641
1642 /// If the constructor was given \c do_pending=false then you
1643 /// \em must invoke this routine in order to process both
1644 /// prior and future messages.
1645 inline void process_pending()
1646 {
1648 p->process_pending();
1649 }
1650
1651 /// Sends message "resultT memfun()" to item (non-blocking comm if remote)
1652
1653 /// If item does not exist it is made with the default constructor.
1654 ///
1655 /// Future arguments must be ready for remote messages.
1656 ///
1657 /// Returns a future result (Future<void> may be ignored).
1658 ///
1659 /// The method executes with a write lock on the item.
1660 template <typename memfunT>
1662 send(const keyT &key, memfunT memfun)
1663 {
1666 (implT::*itemfun)(const keyT &, memfunT) = &implT::template itemfun<memfunT>;
1667 return p->send(owner(key), itemfun, key, memfun);
1668 }
1669
1670 /// Sends message "resultT memfun(arg1T)" to item (non-blocking comm if remote)
1671
1672 /// If item does not exist it is made with the default constructor.
1673 ///
1674 /// Future arguments must be ready for remote messages.
1675 ///
1676 /// Returns a future result (Future<void> may be ignored).
1677 ///
1678 /// The method executes with a write lock on the item.
1679 template <typename memfunT, typename arg1T>
1681 send(const keyT &key, const memfunT &memfun, const arg1T &arg1)
1682 {
1684 // To work around bug in g++ 4.3.* use static cast as alternative mechanism to force type deduction
1686 (implT::*itemfun)(const keyT &, memfunT, const arg1T &) = &implT::template itemfun<memfunT, arg1T>;
1687 return p->send(owner(key), itemfun, key, memfun, arg1);
1688 /*return p->send(owner(key),
1689 static_cast<MEMFUN_RETURNT(memfunT)(implT::*)(const keyT&, memfunT, const arg1T&)>(&implT:: template itemfun<memfunT,arg1T>),
1690 key, memfun, arg1);*/
1691 }
1692
1693 /// Sends message "resultT memfun(arg1T,arg2T)" to item (non-blocking comm if remote)
1694
1695 /// If item does not exist it is made with the default constructor.
1696 ///
1697 /// Future arguments must be ready for both local and remote messages.
1698 ///
1699 /// Returns a future result (Future<void> may be ignored).
1700 ///
1701 /// The method executes with a write lock on the item.
1702 template <typename memfunT, typename arg1T, typename arg2T>
1704 send(const keyT &key, memfunT memfun, const arg1T &arg1, const arg2T &arg2)
1705 {
1707 // To work around bug in g++ 4.3.* use static cast as alternative mechanism to force type deduction
1709 (implT::*itemfun)(const keyT &, memfunT, const arg1T &, const arg2T &) = &implT::template itemfun<memfunT, arg1T, arg2T>;
1710 return p->send(owner(key), itemfun, key, memfun, arg1, arg2);
1711 /*return p->send(owner(key),
1712 static_cast<MEMFUN_RETURNT(memfunT)(implT::*)(const keyT&, memfunT, const arg1T&, const arg2T&)>(&implT:: template itemfun<memfunT,arg1T,arg2T>), key, memfun, arg1, arg2);*/
1713 }
1714
1715 /// Sends message "resultT memfun(arg1T,arg2T,arg3T)" to item (non-blocking comm if remote)
1716
1717 /// If item does not exist it is made with the default constructor.
1718 ///
1719 /// Future arguments must be ready for both local and remote messages.
1720 ///
1721 /// Returns a future result (Future<void> may be ignored).
1722 ///
1723 /// The method executes with a write lock on the item.
1724 template <typename memfunT, typename arg1T, typename arg2T, typename arg3T>
1726 send(const keyT &key, memfunT memfun, const arg1T &arg1, const arg2T &arg2, const arg3T &arg3)
1727 {
1730 (implT::*itemfun)(const keyT &, memfunT, const arg1T &, const arg2T &, const arg3T &) = &implT::template itemfun<memfunT, arg1T, arg2T, arg3T>;
1731 return p->send(owner(key), itemfun, key, memfun, arg1, arg2, arg3);
1732 }
1733
1734 /// Sends message "resultT memfun(arg1T,arg2T,arg3T,arg4T)" to item (non-blocking comm if remote)
1735
1736 /// If item does not exist it is made with the default constructor.
1737 ///
1738 /// Future arguments must be ready for both local and remote messages.
1739 ///
1740 /// Returns a future result (Future<void> may be ignored).
1741 ///
1742 /// The method executes with a write lock on the item.
1743 template <typename memfunT, typename arg1T, typename arg2T, typename arg3T, typename arg4T>
1745 send(const keyT &key, memfunT memfun, const arg1T &arg1, const arg2T &arg2, const arg3T &arg3, const arg4T &arg4)
1746 {
1749 (implT::*itemfun)(const keyT &, memfunT, const arg1T &, const arg2T &, const arg3T &, const arg4T &) = &implT::template itemfun<memfunT, arg1T, arg2T, arg3T, arg4T>;
1750 return p->send(owner(key), itemfun, key, memfun, arg1, arg2, arg3, arg4);
1751 }
1752
1753 /// Sends message "resultT memfun(arg1T,arg2T,arg3T,arg4T,arg5T)" to item (non-blocking comm if remote)
1754
1755 /// If item does not exist it is made with the default constructor.
1756 ///
1757 /// Future arguments must be ready for both local and remote messages.
1758 ///
1759 /// Returns a future result (Future<void> may be ignored).
1760 ///
1761 /// The method executes with a write lock on the item.
1762 template <typename memfunT, typename arg1T, typename arg2T, typename arg3T, typename arg4T, typename arg5T>
1764 send(const keyT &key, memfunT memfun, const arg1T &arg1, const arg2T &arg2, const arg3T &arg3, const arg4T &arg4, const arg5T &arg5)
1765 {
1768 (implT::*itemfun)(const keyT &, memfunT, const arg1T &, const arg2T &, const arg3T &, const arg4T &, const arg5T &) = &implT::template itemfun<memfunT, arg1T, arg2T, arg3T, arg4T, arg5T>;
1769 return p->send(owner(key), itemfun, key, memfun, arg1, arg2, arg3, arg4, arg5);
1770 }
1771
1772 /// Sends message "resultT memfun(arg1T,arg2T,arg3T,arg4T,arg5T,arg6T)" to item (non-blocking comm if remote)
1773
1774 /// If item does not exist it is made with the default constructor.
1775 ///
1776 /// Future arguments must be ready for both local and remote messages.
1777 ///
1778 /// Returns a future result (Future<void> may be ignored).
1779 ///
1780 /// The method executes with a write lock on the item.
1781 template <typename memfunT, typename arg1T, typename arg2T, typename arg3T, typename arg4T, typename arg5T, typename arg6T>
1783 send(const keyT &key, memfunT memfun, const arg1T &arg1, const arg2T &arg2, const arg3T &arg3, const arg4T &arg4, const arg5T &arg5, const arg6T &arg6)
1784 {
1787 (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>;
1788 return p->send(owner(key), itemfun, key, memfun, arg1, arg2, arg3, arg4, arg5, arg6);
1789 }
1790
1791 /// Sends message "resultT memfun(arg1T,arg2T,arg3T,arg4T,arg5T,arg6T,arg7T)" to item (non-blocking comm if remote)
1792
1793 /// If item does not exist it is made with the default constructor.
1794 ///
1795 /// Future arguments must be ready for both local and remote messages.
1796 ///
1797 /// Returns a future result (Future<void> may be ignored).
1798 ///
1799 /// The method executes with a write lock on the item.
1800 template <typename memfunT, typename arg1T, typename arg2T, typename arg3T, typename arg4T, typename arg5T, typename arg6T, typename arg7T>
1802 send(const keyT &key, memfunT memfun, const arg1T &arg1, const arg2T &arg2, const arg3T &arg3, const arg4T &arg4,
1803 const arg5T &arg5, const arg6T &arg6, const arg7T &arg7)
1804 {
1807 (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>;
1808 return p->send(owner(key), itemfun, key, memfun, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
1809 }
1810
1811 /// Sends message "resultT memfun() const" to item (non-blocking comm if remote)
1812
1813 /// The method executes with a write lock on the item.
1814 template <typename memfunT>
1816 send(const keyT &key, memfunT memfun) const
1817 {
1818 return const_cast<containerT *>(this)->send(key, memfun);
1819 }
1820
1821 /// Sends message "resultT memfun(arg1T) const" to item (non-blocking comm if remote)
1822
1823 /// The method executes with a write lock on the item.
1824 template <typename memfunT, typename arg1T>
1826 send(const keyT &key, memfunT memfun, const arg1T &arg1) const
1827 {
1828 return const_cast<containerT *>(this)->send(key, memfun, arg1);
1829 }
1830
1831 /// Sends message "resultT memfun(arg1T,arg2T) const" to item (non-blocking comm if remote)
1832
1833 /// The method executes with a write lock on the item.
1834 template <typename memfunT, typename arg1T, typename arg2T>
1836 send(const keyT &key, memfunT memfun, const arg1T &arg1, const arg2T &arg2) const
1837 {
1838 return const_cast<containerT *>(this)->send(key, memfun, arg1, arg2);
1839 }
1840
1841 /// Sends message "resultT memfun(arg1T,arg2T,arg3T) const" to item (non-blocking comm if remote)
1842
1843 /// The method executes with a write lock on the item.
1844 template <typename memfunT, typename arg1T, typename arg2T, typename arg3T>
1846 send(const keyT &key, memfunT memfun, const arg1T &arg1, const arg2T &arg2, const arg3T &arg3) const
1847 {
1848 return const_cast<containerT *>(this)->send(key, memfun, arg1, arg2, arg3);
1849 }
1850
1851 /// Sends message "resultT memfun(arg1T,arg2T,arg3T,arg4T) const" to item (non-blocking comm if remote)
1852
1853 /// The method executes with a write lock on the item.
1854 template <typename memfunT, typename arg1T, typename arg2T, typename arg3T, typename arg4T>
1856 send(const keyT &key, memfunT memfun, const arg1T &arg1, const arg2T &arg2, const arg3T &arg3, const arg4T &arg4) const
1857 {
1858 return const_cast<containerT *>(this)->send(key, memfun, arg1, arg2, arg3, arg4);
1859 }
1860
1861 /// Sends message "resultT memfun(arg1T,arg2T,arg3T,arg4T,arg5T) const" to item (non-blocking comm if remote)
1862
1863 /// The method executes with a write lock on the item.
1864 template <typename memfunT, typename arg1T, typename arg2T, typename arg3T, typename arg4T, typename arg5T>
1866 send(const keyT &key, memfunT memfun, const arg1T &arg1, const arg2T &arg2, const arg3T &arg3, const arg4T &arg4, const arg5T &arg5) const
1867 {
1868 return const_cast<containerT *>(this)->send(key, memfun, arg1, arg2, arg3, arg4, arg5);
1869 }
1870
1871 /// Sends message "resultT memfun(arg1T,arg2T,arg3T,arg4T,arg5T,arg6T) const" to item (non-blocking comm if remote)
1872
1873 /// The method executes with a write lock on the item.
1874 template <typename memfunT, typename arg1T, typename arg2T, typename arg3T, typename arg4T, typename arg5T, typename arg6T>
1876 send(const keyT &key, memfunT memfun, const arg1T &arg1, const arg2T &arg2, const arg3T &arg3,
1877 const arg4T &arg4, const arg5T &arg5, const arg6T &arg6) const
1878 {
1879 return const_cast<containerT *>(this)->send(key, memfun, arg1, arg2, arg3, arg4, arg5, arg6);
1880 }
1881
1882 /// Sends message "resultT memfun(arg1T,arg2T,arg3T,arg4T,arg5T,arg6T,arg7T) const" to item (non-blocking comm if remote)
1883
1884 /// The method executes with a write lock on the item.
1885 template <typename memfunT, typename arg1T, typename arg2T, typename arg3T, typename arg4T, typename arg5T, typename arg6T, typename arg7T>
1887 send(const keyT &key, memfunT memfun, const arg1T &arg1, const arg2T &arg2, const arg3T &arg3,
1888 const arg4T &arg4, const arg5T &arg5, const arg6T &arg6, const arg7T &arg7) const
1889 {
1890 return const_cast<containerT *>(this)->send(key, memfun, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
1891 }
1892
1893 /// Adds task "resultT memfun()" in process owning item (non-blocking comm if remote)
1894
1895 /// If item does not exist it is made with the default constructor.
1896 ///
1897 /// Future arguments for local tasks can generate dependencies, but for remote
1898 /// tasks all futures must be ready.
1899 ///
1900 /// Returns a future result (Future<void> may be ignored).
1901 ///
1902 /// The method executes with a write lock on the item.
1903 template <typename memfunT>
1905 task(const keyT &key, memfunT memfun, const TaskAttributes &attr = TaskAttributes())
1906 {
1909 (implT::*itemfun)(const keyT &, memfunT) = &implT::template itemfun<memfunT>;
1910 return p->task(owner(key), itemfun, key, memfun, attr);
1911 }
1912
1913 /// Adds task "resultT memfun(arg1T)" in process owning item (non-blocking comm if remote)
1914
1915 /// If item does not exist it is made with the default constructor.
1916 ///
1917 /// Future arguments for local tasks can generate dependencies, but for remote
1918 /// tasks all futures must be ready.
1919 ///
1920 /// Returns a future result (Future<void> may be ignored).
1921 ///
1922 /// The method executes with a write lock on the item.
1923 template <typename memfunT, typename arg1T>
1925 task(const keyT &key, memfunT memfun, const arg1T &arg1, const TaskAttributes &attr = TaskAttributes())
1926 {
1928 typedef REMFUTURE(arg1T) a1T;
1930 (implT::*itemfun)(const keyT &, memfunT, const a1T &) = &implT::template itemfun<memfunT, a1T>;
1931 return p->task(owner(key), itemfun, key, memfun, arg1, attr);
1932 }
1933
1934 /// Adds task "resultT memfun(arg1T,arg2T)" in process owning item (non-blocking comm if remote)
1935
1936 /// If item does not exist it is made with the default constructor.
1937 ///
1938 /// Future arguments for local tasks can generate dependencies, but for remote
1939 /// tasks all futures must be ready.
1940 ///
1941 /// Returns a future result (Future<void> may be ignored).
1942 ///
1943 /// The method executes with a write lock on the item.
1944 template <typename memfunT, typename arg1T, typename arg2T>
1946 task(const keyT &key, memfunT memfun, const arg1T &arg1, const arg2T &arg2, const TaskAttributes &attr = TaskAttributes())
1947 {
1949 typedef REMFUTURE(arg1T) a1T;
1950 typedef REMFUTURE(arg2T) a2T;
1952 (implT::*itemfun)(const keyT &, memfunT, const a1T &, const a2T &) = &implT::template itemfun<memfunT, a1T, a2T>;
1953 return p->task(owner(key), itemfun, key, memfun, arg1, arg2, attr);
1954 }
1955
1956 /// Adds task "resultT memfun(arg1T,arg2T,arg3T)" in process owning item (non-blocking comm if remote)
1957
1958 /// If item does not exist it is made with the default constructor.
1959 ///
1960 /// Future arguments for local tasks can generate dependencies, but for remote
1961 /// tasks all futures must be ready.
1962 ///
1963 /// Returns a future result (Future<void> may be ignored).
1964 ///
1965 /// The method executes with a write lock on the item.
1966 template <typename memfunT, typename arg1T, typename arg2T, typename arg3T>
1968 task(const keyT &key, memfunT memfun, const arg1T &arg1, const arg2T &arg2, const arg3T &arg3, const TaskAttributes &attr = TaskAttributes())
1969 {
1971 typedef REMFUTURE(arg1T) a1T;
1972 typedef REMFUTURE(arg2T) a2T;
1973 typedef REMFUTURE(arg3T) a3T;
1975 (implT::*itemfun)(const keyT &, memfunT, const a1T &, const a2T &, const a3T &) = &implT::template itemfun<memfunT, a1T, a2T, a3T>;
1976 return p->task(owner(key), itemfun, key, memfun, arg1, arg2, arg3, attr);
1977 }
1978
1979 /// Adds task "resultT memfun(arg1T,arg2T,arg3T,arg4T)" in process owning item (non-blocking comm if remote)
1980
1981 /// If item does not exist it is made with the default constructor.
1982 ///
1983 /// Future arguments for local tasks can generate dependencies, but for remote
1984 /// tasks all futures must be ready.
1985 ///
1986 /// Returns a future result (Future<void> may be ignored).
1987 ///
1988 /// The method executes with a write lock on the item.
1989 template <typename memfunT, typename arg1T, typename arg2T, typename arg3T, typename arg4T>
1991 task(const keyT &key, memfunT memfun, const arg1T &arg1, const arg2T &arg2, const arg3T &arg3, const arg4T &arg4, const TaskAttributes &attr = TaskAttributes())
1992 {
1994 typedef REMFUTURE(arg1T) a1T;
1995 typedef REMFUTURE(arg2T) a2T;
1996 typedef REMFUTURE(arg3T) a3T;
1997 typedef REMFUTURE(arg4T) a4T;
1999 (implT::*itemfun)(const keyT &, memfunT, const a1T &, const a2T &, const a3T &, const a4T &) = &implT::template itemfun<memfunT, a1T, a2T, a3T, a4T>;
2000 return p->task(owner(key), itemfun, key, memfun, arg1, arg2, arg3, arg4, attr);
2001 }
2002
2003 /// Adds task "resultT memfun(arg1T,arg2T,arg3T,arg4T,arg5T)" in process owning item (non-blocking comm if remote)
2004
2005 /// If item does not exist it is made with the default constructor.
2006 ///
2007 /// Future arguments for local tasks can generate dependencies, but for remote
2008 /// tasks all futures must be ready.
2009 ///
2010 /// Returns a future result (Future<void> may be ignored).
2011 ///
2012 /// The method executes with a write lock on the item.
2013 template <typename memfunT, typename arg1T, typename arg2T, typename arg3T, typename arg4T, typename arg5T>
2015 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())
2016 {
2018 typedef REMFUTURE(arg1T) a1T;
2019 typedef REMFUTURE(arg2T) a2T;
2020 typedef REMFUTURE(arg3T) a3T;
2021 typedef REMFUTURE(arg4T) a4T;
2022 typedef REMFUTURE(arg5T) a5T;
2024 (implT::*itemfun)(const keyT &, memfunT, const a1T &, const a2T &, const a3T &, const a4T &, const a5T &) = &implT::template itemfun<memfunT, a1T, a2T, a3T, a4T, a5T>;
2025 return p->task(owner(key), itemfun, key, memfun, arg1, arg2, arg3, arg4, arg5, attr);
2026 }
2027
2028 /// Adds task "resultT memfun(arg1T,arg2T,arg3T,arg4T,arg5T,arg6T)" in process owning item (non-blocking comm if remote)
2029
2030 /// If item does not exist it is made with the default constructor.
2031 ///
2032 /// Future arguments for local tasks can generate dependencies, but for remote
2033 /// tasks all futures must be ready.
2034 ///
2035 /// Returns a future result (Future<void> may be ignored).
2036 ///
2037 /// The method executes with a write lock on the item.
2038 template <typename memfunT, typename arg1T, typename arg2T, typename arg3T, typename arg4T, typename arg5T, typename arg6T>
2040 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())
2041 {
2043 typedef REMFUTURE(arg1T) a1T;
2044 typedef REMFUTURE(arg2T) a2T;
2045 typedef REMFUTURE(arg3T) a3T;
2046 typedef REMFUTURE(arg4T) a4T;
2047 typedef REMFUTURE(arg5T) a5T;
2048 typedef REMFUTURE(arg6T) a6T;
2050 (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>;
2051 return p->task(owner(key), itemfun, key, memfun, arg1, arg2, arg3, arg4, arg5, arg6, attr);
2052 }
2053
2054 /// Adds task "resultT memfun(arg1T,arg2T,arg3T,arg4T,arg5T,arg6T,arg7T)" in process owning item (non-blocking comm if remote)
2055
2056 /// If item does not exist it is made with the default constructor.
2057 ///
2058 /// Future arguments for local tasks can generate dependencies, but for remote
2059 /// tasks all futures must be ready.
2060 ///
2061 /// Returns a future result (Future<void> may be ignored).
2062 ///
2063 /// The method executes with a write lock on the item.
2064 template <typename memfunT, typename arg1T, typename arg2T, typename arg3T, typename arg4T, typename arg5T, typename arg6T, typename arg7T>
2066 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())
2067 {
2069 typedef REMFUTURE(arg1T) a1T;
2070 typedef REMFUTURE(arg2T) a2T;
2071 typedef REMFUTURE(arg3T) a3T;
2072 typedef REMFUTURE(arg4T) a4T;
2073 typedef REMFUTURE(arg5T) a5T;
2074 typedef REMFUTURE(arg6T) a6T;
2075 typedef REMFUTURE(arg7T) a7T;
2077 (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>;
2078 return p->task(owner(key), itemfun, key, memfun, arg1, arg2, arg3, arg4, arg5, arg6, arg7, attr);
2079 }
2080
2081 /// Adds task "resultT memfun() const" in process owning item (non-blocking comm if remote)
2082
2083 /// The method executes with a write lock on the item.
2084 template <typename memfunT>
2086 task(const keyT &key, memfunT memfun, const TaskAttributes &attr = TaskAttributes()) const
2087 {
2088 return const_cast<containerT *>(this)->task(key, memfun, attr);
2089 }
2090
2091 /// Adds task "resultT memfun(arg1T) const" in process owning item (non-blocking comm if remote)
2092
2093 /// The method executes with a write lock on the item.
2094 template <typename memfunT, typename arg1T>
2096 task(const keyT &key, memfunT memfun, const arg1T &arg1, const TaskAttributes &attr = TaskAttributes()) const
2097 {
2098 return const_cast<containerT *>(this)->task(key, memfun, arg1, attr);
2099 }
2100
2101 /// Adds task "resultT memfun(arg1T,arg2T) const" in process owning item (non-blocking comm if remote)
2102
2103 /// The method executes with a write lock on the item.
2104 template <typename memfunT, typename arg1T, typename arg2T>
2106 task(const keyT &key, memfunT memfun, const arg1T &arg1, const arg2T &arg2, const TaskAttributes &attr = TaskAttributes()) const
2107 {
2108 return const_cast<containerT *>(this)->task(key, memfun, arg1, arg2, attr);
2109 }
2110
2111 /// Adds task "resultT memfun(arg1T,arg2T,arg3T) const" in process owning item (non-blocking comm if remote)
2112
2113 /// The method executes with a write lock on the item.
2114 template <typename memfunT, typename arg1T, typename arg2T, typename arg3T>
2116 task(const keyT &key, memfunT memfun, const arg1T &arg1, const arg2T &arg2, const arg3T &arg3, const TaskAttributes &attr = TaskAttributes()) const
2117 {
2118 return const_cast<containerT *>(this)->task(key, memfun, arg1, arg2, arg3, attr);
2119 }
2120
2121 /// Adds task "resultT memfun(arg1T,arg2T,arg3T, arg4T) const" in process owning item (non-blocking comm if remote)
2122
2123 /// The method executes with a write lock on the item.
2124 template <typename memfunT, typename arg1T, typename arg2T, typename arg3T, typename arg4T>
2126 task(const keyT &key, memfunT memfun, const arg1T &arg1, const arg2T &arg2, const arg3T &arg3, const arg4T &arg4, const TaskAttributes &attr = TaskAttributes()) const
2127 {
2128 return const_cast<containerT *>(this)->task(key, memfun, arg1, arg2, arg3, arg4, attr);
2129 }
2130
2131 /// Adds task "resultT memfun(arg1T,arg2T,arg3T,arg4T,arg5T) const" in process owning item (non-blocking comm if remote)
2132
2133 /// The method executes with a write lock on the item.
2134 template <typename memfunT, typename arg1T, typename arg2T, typename arg3T, typename arg4T, typename arg5T>
2136 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
2137 {
2138 return const_cast<containerT *>(this)->task(key, memfun, arg1, arg2, arg3, arg4, arg5, attr);
2139 }
2140
2141 /// Adds task "resultT memfun(arg1T,arg2T,arg3T,arg4T,arg5T,arg6T) const" in process owning item (non-blocking comm if remote)
2142
2143 /// The method executes with a write lock on the item.
2144 template <typename memfunT, typename arg1T, typename arg2T, typename arg3T, typename arg4T, typename arg5T, typename arg6T>
2146 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
2147 {
2148 return const_cast<containerT *>(this)->task(key, memfun, arg1, arg2, arg3, arg4, arg5, arg6, attr);
2149 }
2150
2151 /// Adds task "resultT memfun(arg1T,arg2T,arg3T,arg4T,arg5T,arg6T,arg7T) const" in process owning item (non-blocking comm if remote)
2152
2153 /// The method executes with a write lock on the item.
2154 template <typename memfunT, typename arg1T, typename arg2T, typename arg3T, typename arg4T, typename arg5T, typename arg6T, typename arg7T>
2156 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
2157 {
2158 return const_cast<containerT *>(this)->task(key, memfun, arg1, arg2, arg3, arg4, arg5, arg6, arg7, attr);
2159 }
2160
2161 /// (de)Serialize --- *Local* data only to/from anything *except* Buffer*Archive and Parallel*Archive
2162
2163 /// Advisable for *you* to fence before and after this to ensure consistency
2164 template <typename Archive>
2165 void serialize(const Archive &ar)
2166 {
2167 //
2168 // !! If you change the format of this stream make sure that
2169 // !! the parallel in/out archive below is compatible
2170 //
2171 const long magic = 5881828; // Sitar Indian restaurant in Knoxville
2172 unsigned long count = 0;
2174
2175 if (Archive::is_output_archive)
2176 {
2177 ar & magic;
2178 for (iterator it = begin(); it != end(); ++it)
2179 count++;
2180 ar & count;
2181 for (iterator it = begin(); it != end(); ++it)
2182 ar &*it;
2183 }
2184 else
2185 {
2186 long cookie = 0l;
2187 ar & cookie;
2188 MADNESS_ASSERT(cookie == magic);
2189 ar & count;
2190 while (count--)
2191 {
2192 pairT datum;
2193 ar & datum;
2194 replace(datum);
2195 }
2196 }
2197 }
2198
2199 /// (de)Serialize --- !! ONLY for purpose of interprocess communication
2200
2201 /// This just writes/reads the unique id to/from the Buffer*Archive.
2203 {
2205 ar &static_cast<WorldObject<implT> *>(p.get());
2206 }
2207
2208 /// (de)Serialize --- !! ONLY for purpose of interprocess communication
2209
2210 /// This just writes/reads the unique id to/from the Buffer*Archive.
2212 {
2213 WorldObject<implT> *ptr = nullptr;
2214 ar & ptr;
2215 MADNESS_ASSERT(ptr);
2216
2217#ifdef MADNESS_DISABLE_SHARED_FROM_THIS
2218 p.reset(static_cast<implT *>(ptr), [](implT *p_) -> void{});
2219#else
2220 p = static_cast<implT *>(ptr)->shared_from_this();
2221#endif // MADNESS_DISABLE_SHARED_FROM_THIS
2222 }
2223
2224 /// Returns the associated unique id ... must be initialized
2225 const uniqueidT &id() const
2226 {
2228 return p->id();
2229 }
2230
2231 /// Destructor passes ownership of implementation to world for deferred cleanup
2233 {
2234 detail::deferred_cleanup(p->get_world(), p);
2235 }
2236
2238 };
2239
2240 /// Swaps the content of two WorldContainer objects. It should be called on all nodes.
2241
2242 /// \ingroup worlddc
2243 template <typename keyT, typename valueT, typename hashfunT>
2248
2249
2250 namespace archive
2251 {
2252
2253 /// Write container to parallel archive
2254
2255 /// specialization for parallel serialization of a WorldContainer:
2256 /// all threads on each process serialize some values into a buffer, which gets concatenated
2257 /// and finally serialized to localarchive (aka VectorOutputArchive).
2258 template <class keyT, class valueT>
2260 {
2262 {
2264 const long magic = -5881828; // Sitar Indian restaurant in Knoxville (negative to indicate parallel!)
2265 typedef WorldContainer<keyT, valueT> dcT;
2266 using const_iterator = typename dcT::const_iterator;
2267 int count = t.size(); // Must be INT for MPI and NOT const since we'll do a global sum eventually
2268
2269 // Strategy:
2270 // 1. Serialize local data to a buffer in parallel over threads
2271 // a) Compute the size of the buffer needed by each task
2272 // b) Sum sizes and allocate the buffer of exact sizes needed for all threads
2273 // c) Serialize the data into the buffer in parallel over threads
2274 // 2. Gather all buffers to process 0
2275
2276 World *world = ar.get_world();
2277 world->gop.fence(); // Global fence here
2278
2279 class op_inspector : public TaskInterface
2280 {
2281 const_iterator start, end;
2282 size_t &size;
2283
2284 public:
2285 op_inspector(const_iterator start, const_iterator end, size_t &size)
2286 : start(start), end(end), size(size) {}
2287
2288 using TaskInterface::run;
2289
2290 void run(World &world) override
2291 {
2293 for (const_iterator it = start; it != end; ++it)
2294 bo &*it;
2295 size = bo.size();
2296 }
2297 };
2298
2299 class op_executor : public TaskInterface
2300 {
2301 const_iterator start, end;
2302 unsigned char *buf;
2303 const size_t size;
2304
2305 public:
2306 op_executor(const_iterator start, const_iterator end, unsigned char *buf, size_t size)
2307 : start(start), end(end), buf(buf), size(size) {}
2308
2309 using TaskInterface::run;
2310
2311 void run(World &world) override
2312 {
2313 BufferOutputArchive bo(buf, size);
2314 for (const_iterator it = start; it != end; ++it)
2315 {
2316 bo &*it;
2317 }
2318 MADNESS_CHECK(size == bo.size());
2319 }
2320 };
2321
2322 // No need for LOCAL fence here since only master thread is busy
2323 double wall0 = wall_time();
2324 const size_t ntasks = std::min(size_t(count), std::max(size_t(1), ThreadPool::size()));
2325 size_t local_size = 0;
2326 double wall1 = wall0;
2327 unsigned char* buf = 0;
2328 if (ntasks > 0)
2329 {
2330 const size_t max_items_per_task = (std::max(1, count) - 1) / ntasks + 1;
2331 // Compute the size of the buffer needed by each task
2332 std::vector<const_iterator> starts(ntasks), ends(ntasks);
2333 std::vector<size_t> local_sizes(ntasks);
2334 const_iterator start = t.begin();
2335 size_t nleft = count;
2336 for (size_t taskid = 0; taskid < ntasks; taskid++)
2337 {
2338 const_iterator end = start;
2339 if (taskid == (ntasks - 1))
2340 {
2341 end = t.end();
2342 }
2343 else
2344 {
2345 size_t nitems = std::min(max_items_per_task, nleft);
2347 nleft -= nitems;
2348 }
2349 starts[taskid] = start;
2350 ends[taskid] = end;
2351 world->taskq.add(new op_inspector(start, end, local_sizes[taskid])); // Be sure to pass iterators by value!!
2352 start = end;
2353 }
2354 world->taskq.fence(); // just need LOCAL fence
2355 wall1 = wall_time();
2356 // if (world->rank() == 0)
2357 // printf("time in op_inspector: %8.4fs\n", wall1 - wall0);
2358 wall0 = wall1;
2359
2360 // total size over all threads
2361 for (size_t taskid = 0; taskid < ntasks; taskid++)
2362 {
2363 local_size += local_sizes[taskid];
2364 // print("taskid",taskid,"size",local_sizes[taskid]);
2365 }
2366
2367 // Allocate the buffer for all threads
2368 buf = new unsigned char[local_size];
2369
2370 // Now execute the serialization
2371 size_t offset = 0;
2372 for (size_t taskid = 0; taskid < ntasks; taskid++)
2373 {
2376 }
2377 world->taskq.fence(); // just need LOCAL fence
2378
2379 wall1 = wall_time();
2380 // if (world->rank() == 0)
2381 // printf("time in op_executor: %8.4fs\n", wall1 - wall0);
2382 wall0 = wall1;
2383 }
2384 // VERify that the serialization worked!!
2385 // {
2386 // BufferInputArchive bi(buf, local_size);
2387 // for (int item=0; item<count; item++) {
2388 // std::pair<keyT, valueT> datum;
2389 // bi & datum;
2390 // print("deserializing",datum.first);
2391 // }
2392 // }
2393
2394 // Gather all buffers to process 0
2395 // first gather all of the sizes and counts to a vector in process 0
2396 const int size = local_size;
2397 std::vector<int> sizes(world->size());
2398 MPI_Gather(&size, 1, MPI_INT, sizes.data(), 1, MPI_INT, 0, world->mpi.comm().Get_mpi_comm());
2399 world->gop.sum(count); // just need total number of elements
2400
2401 // print("time 3",wall_time());
2402 // build the cumulative sum of sizes
2403 std::vector<int> offsets(world->size());
2404 offsets[0] = 0;
2405 for (int i = 1; i < world->size(); ++i)
2406 offsets[i] = offsets[i - 1] + sizes[i - 1];
2407 size_t total_size = offsets.back() + sizes.back();
2408 // if (world->rank() == 0)
2409 // print("total_size", total_size);
2410
2411 // print("time 4",wall_time());
2412 // gather the vector of data v from each process to process 0
2413 unsigned char *all_data = 0;
2414 if (world->rank() == 0)
2415 {
2416 all_data = new unsigned char[total_size];
2417 }
2418 MPI_Gatherv(buf, local_size, MPI_BYTE, all_data, sizes.data(), offsets.data(), MPI_BYTE, 0, world->mpi.comm().Get_mpi_comm());
2419
2420 wall1 = wall_time();
2421 // if (world->rank() == 0)
2422 // printf("time in gather+gatherv: %8.4fs\n", wall1 - wall0);
2423 wall0 = wall1;
2424
2425 delete[] buf;
2426
2427 // print("time 5",wall_time());
2428 if (world->rank() == 0)
2429 {
2430 auto &localar = ar.local_archive();
2431 localar & magic & 1; // 1 client
2432 // localar & t;
2434 localar & -magic &(unsigned long)(count);
2435 localar.store(all_data, total_size);
2437 wall1 = wall_time();
2438 // if (world->rank() == 0)
2439 // printf("time in final copy on node 0: %8.4fs\n", wall1 - wall0);
2440
2441 delete[] all_data;
2442 }
2443 world->gop.fence();
2444 // print("time 6",wall_time());
2445 }
2446 };
2447
2448 /// Write container to parallel archive with optional fence
2449
2450 /// \ingroup worlddc
2451 /// Each node (process) is served by a designated IO node.
2452 /// The IO node has a binary local file archive to which is
2453 /// first written a cookie and the number of servers. The IO
2454 /// node then loops thru all of its clients and in turn tells
2455 /// each to write its data over an MPI stream, which is copied
2456 /// directly to the output file. The stream contents are then
2457 /// cookie, no. of clients, foreach client (usual sequential archive).
2458 ///
2459 /// If ar.dofence() is true (default) fence is invoked before and
2460 /// after the IO. The fence is optional but it is of course
2461 /// necessary to be sure that all updates have completed
2462 /// before doing IO, and that all IO has completed before
2463 /// subsequent modifications. Also, there is always at least
2464 /// some synchronization between a client and its IO server.
2465 template <class keyT, class valueT, class localarchiveT>
2467 {
2469 {
2470 const long magic = -5881828; // Sitar Indian restaurant in Knoxville (negative to indicate parallel!)
2471 typedef WorldContainer<keyT, valueT> dcT;
2472 // typedef typename dcT::const_iterator iterator; // unused?
2473 typedef typename dcT::pairT pairT;
2474 World *world = ar.get_world();
2475 Tag tag = world->mpi.unique_tag();
2476 ProcessID me = world->rank();
2477 if (ar.dofence())
2478 world->gop.fence();
2479 if (ar.is_io_node())
2480 {
2481 auto &localar = ar.local_archive();
2482 localar & magic & ar.num_io_clients();
2483 for (ProcessID p = 0; p < world->size(); ++p)
2484 {
2485 if (p == me)
2486 {
2487 localar & t;
2488 }
2489 else if (ar.io_node(p) == me)
2490 {
2491 world->mpi.Send(int(1), p, tag); // Tell client to start sending
2493 long cookie = 0l;
2494 unsigned long count = 0ul;
2495
2497
2498 source & cookie & count;
2499 localar & cookie & count;
2500 while (count--)
2501 {
2502 pairT datum;
2503 source & datum;
2504 localar & datum;
2505 }
2506
2508 }
2509 }
2510 }
2511 else
2512 {
2513 ProcessID p = ar.my_io_node();
2514 int flag;
2515 world->mpi.Recv(flag, p, tag);
2516 MPIOutputArchive dest(*world, p);
2517 dest & t;
2518 dest.flush();
2519 }
2520 if (ar.dofence())
2521 world->gop.fence();
2522 }
2523 };
2524
2525 template <class keyT, class valueT, class localarchiveT>
2527 {
2528 /// Read container from parallel archive
2529
2530 /// \ingroup worlddc
2531 /// See store method above for format of file content.
2532 /// !!! We presently ASSUME that the number of writers and readers are
2533 /// the same. This is frustrating but not a show stopper since you
2534 /// can always run a separate job to copy to a different number.
2535 ///
2536 /// The IO node simply reads all data and inserts entries.
2538 {
2539 const long magic = -5881828; // Sitar Indian restaurant in Knoxville (negative to indicate parallel!)
2540 // typedef WorldContainer<keyT,valueT> dcT; // unused
2541 // typedef typename dcT::iterator iterator; // unused
2542 // typedef typename dcT::pairT pairT; // unused
2543 World *world = ar.get_world();
2544 if (ar.dofence())
2545 world->gop.fence();
2546 if (ar.is_io_node())
2547 {
2548 long cookie = 0l;
2549 int nclient = 0;
2550 auto &localar = ar.local_archive();
2551 localar & cookie & nclient;
2552 MADNESS_CHECK(cookie == magic);
2553 while (nclient--)
2554 {
2555 localar & t;
2556 }
2557 }
2558 if (ar.dofence())
2559 world->gop.fence();
2560 }
2561 };
2562 }
2563
2564}
2565
2566///@}
2567
2568#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
iteratorT iterator
Alias for the iterator type.
Definition range.h:71
Simple structure used to manage references/pointers to remote instances.
Definition worldref.h:394
Contains attributes of a task.
Definition thread.h:330
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:1460
Internal implementation of distributed container to facilitate shallow copy.
Definition worlddc.h:564
void erase(const keyT &key)
Definition worlddc.h:969
WorldContainerIterator< internal_iteratorT > iterator
Definition worlddc.h:579
const hashfunT & get_hash() const
Definition worlddc.h:893
bool find(const_accessor &acc, const keyT &key) const
Definition worlddc.h:1061
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:605
bool probe(const keyT &key) const
Definition worlddc.h:905
void find_success_handler(const RemoteReference< FutureImpl< iterator > > &ref, const pairT &datum)
Handles successful find response.
Definition worlddc.h:621
std::pair< const keyT, valueT > pairT
Definition worlddc.h:566
bool insert_const_acc(const_accessor &acc, const keyT &key)
Definition worlddc.h:943
void redistribute_coalesced_phase1(const std::shared_ptr< WorldDCPmapInterface< keyT > > &newpmap)
Definition worlddc.h:1217
WorldContainerIterator< internal_const_iteratorT > const_iteratorT
Definition worlddc.h:580
bool find(accessor &acc, const keyT &key)
Definition worlddc.h:1054
void redistribute_phase2()
Definition worlddc.h:1190
void insert(const pairT &datum)
Definition worlddc.h:919
WorldContainerIterator< internal_iteratorT > iteratorT
Definition worlddc.h:578
void clear()
Definition worlddc.h:963
bool insert_acc(accessor &acc, const keyT &key)
Definition worlddc.h:937
void find_const_failure_handler(const RemoteReference< FutureImpl< const_iterator > > &ref)
Handles unsuccessful const find response.
Definition worlddc.h:662
Future< iterator > find(const keyT &key)
Definition worlddc.h:1039
WorldContainerImpl(World &world, const std::shared_ptr< WorldDCPmapInterface< keyT > > &pm, const hashfunT &hf)
Definition worlddc.h:669
void redistribute_coalesced_phase2(std::size_t cap_boxes, bool rotate)
Definition worlddc.h:1235
void reset_pmap_to_local()
Definition worlddc.h:692
itemfun(const keyT &key, memfunT memfun)
Definition worlddc.h:1071
const pairT const_pairT
Definition worlddc.h:567
std::vector< keyT > * move_list
Tempoary used to record data that needs redistributing.
Definition worlddc.h:601
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:914
void redistribute_phase1(const std::shared_ptr< WorldDCPmapInterface< keyT > > &newpmap)
Definition worlddc.h:1158
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:677
void do_replicate(World &world)
Definition worlddc.h:853
std::shared_ptr< WorldDCPmapInterface< keyT > > & get_pmap()
Definition worlddc.h:687
internal_containerT local
Locally owned data.
Definition worlddc.h:600
ConcurrentHashMap< keyT, valueT, hashfunT > internal_containerT
Definition worlddc.h:570
void find_const_success_handler(const RemoteReference< FutureImpl< const_iterator > > &ref, const pairT &datum)
Handles successful const find response.
Definition worlddc.h:655
void insert_batch(const std::vector< pairT > &boxes)
Definition worlddc.h:953
const_iterator begin() const
Definition worlddc.h:1009
void erase(InIter it)
Definition worlddc.h:985
void replicate(bool fence)
Definition worlddc.h:711
const_iterator end() const
Definition worlddc.h:1019
bool is_local(const keyT &key) const
Definition worlddc.h:895
void redistribute_phase3()
Definition worlddc.h:1204
bool rank_replication_complete_
True if the last replicate() completed and no reset followed.
Definition worlddc.h:598
void find_failure_handler(const RemoteReference< FutureImpl< iterator > > &ref)
Handles unsuccessful find response.
Definition worlddc.h:631
ProcessID owner(const keyT &key) const
Definition worlddc.h:900
void erase(InIter first, InIter last)
Definition worlddc.h:993
void find_const_handler(ProcessID requestor, const keyT &key, const RemoteReference< FutureImpl< const_iterator > > &ref)
Handles const find request.
Definition worlddc.h:641
void replicate_on_hosts(bool fence)
Definition worlddc.h:737
const std::shared_ptr< WorldDCPmapInterface< keyT > > & get_pmap() const
Definition worlddc.h:682
iterator begin()
Definition worlddc.h:1004
Future< const_iterator > find(const keyT &key) const
Definition worlddc.h:1024
const ProcessID me
My MPI rank.
Definition worlddc.h:599
iterator end()
Definition worlddc.h:1014
std::map< ProcessID, std::vector< keyT > > coalesced_move_
Temporary: keys to move, bucketed by destination (coalesced redistribute)
Definition worlddc.h:602
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:1299
void process_pending()
Process pending messages.
Definition worlddc.h:1645
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:1339
const hashfunT & get_hash() const
Returns a reference to the hashing functor.
Definition worlddc.h:1634
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:1466
bool probe(const keyT &key) const
Returns true if local data is immediately available (no communication)
Definition worlddc.h:1503
void redistribute_coalesced_phase2(std::size_t cap_boxes, bool rotate=true)
Definition worlddc.h:1446
const_iterator begin() const
Returns an iterator to the beginning of the local data (no communication)
Definition worlddc.h:1556
void replace(const keyT &key, const valueT &value)
Inserts/replaces key+value pair (non-blocking communication if key not local)
Definition worlddc.h:1460
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:1487
iterator begin()
Returns an iterator to the beginning of the local data (no communication)
Definition worlddc.h:1549
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:2136
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:1355
Future< iterator > find(const keyT &key)
Returns a future iterator (non-blocking communication if key not local)
Definition worlddc.h:1531
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:1876
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:1887
Future< const_iterator > const_futureT
Definition worlddc.h:1311
bool is_replicated() const
Definition worlddc.h:1399
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:1925
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:1866
ProcessID owner(const keyT &key) const
Returns processor that logically owns key (no communication)
Definition worlddc.h:1513
implT::const_iterator const_iterator
Definition worlddc.h:1307
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:2106
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:2086
WorldContainer()
Makes an uninitialized container (no communication)
Definition worlddc.h:1327
void serialize(const archive::BufferOutputArchive &ar)
(de)Serialize — !! ONLY for purpose of interprocess communication
Definition worlddc.h:2202
keyT key_type
Definition worlddc.h:1302
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:1726
void replicate(bool fence=true)
Definition worlddc.h:1424
virtual ~WorldContainer()
Destructor passes ownership of implementation to world for deferred cleanup.
Definition worlddc.h:2232
void erase(const keyT &key)
Erases entry from container (non-blocking comm if remote)
Definition worlddc.h:1584
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:1764
void reset_pmap_to_local()
Returns shared pointer to the process mapping.
Definition worlddc.h:1628
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:1681
const uniqueidT & id() const
Returns the associated unique id ... must be initialized.
Definition worlddc.h:2225
void redistribute_coalesced_phase1(const std::shared_ptr< WorldDCPmapInterface< keyT > > &newpmap)
Definition worlddc.h:1437
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:2066
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:1946
WorldContainerImpl< keyT, valueT, hashfunT > implT
Definition worlddc.h:1304
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:1836
void replace(const pairT &datum)
Inserts/replaces key+value pair (non-blocking communication if key not local)
Definition worlddc.h:1453
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:2116
iterator end()
Returns an iterator past the end of the local data (no communication)
Definition worlddc.h:1563
const std::shared_ptr< WorldDCPmapInterface< keyT > > & get_pmap() const
Returns shared pointer to the process mapping.
Definition worlddc.h:1621
std::shared_ptr< WorldDCPmapInterface< keyT > > & get_impl()
Definition worlddc.h:1414
void replace(input_iterator &start, input_iterator &end)
Inserts pairs (non-blocking communication if key(s) not local)
Definition worlddc.h:1495
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:2096
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:1480
Future< iterator > futureT
Definition worlddc.h:1310
void erase(const iterator &it)
Erases entry corresponding to local iterator (no communication)
Definition worlddc.h:1591
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:2126
void erase(const iterator &start, const iterator &finish)
Erases range defined by local iterators (no communication)
Definition worlddc.h:1598
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:1856
bool is_distributed() const
Definition worlddc.h:1395
WorldContainer(const WorldContainer &other)
Copy constructor is shallow (no communication)
Definition worlddc.h:1369
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:2040
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:1802
World & get_world() const
Returns the world associated with this container.
Definition worlddc.h:1408
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:1816
implT::iterator iterator
Definition worlddc.h:1306
DistributionType get_distribution_type() const
return the way data is distributed
Definition worlddc.h:1390
implT::pairT pairT
Definition worlddc.h:1305
std::size_t size() const
Returns the number of local entries (no communication)
Definition worlddc.h:1614
containerT & operator=(const containerT &other)
Assignment is shallow (no communication)
Definition worlddc.h:1379
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:2015
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:1473
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:1968
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:1745
void serialize(const archive::BufferInputArchive &ar)
(de)Serialize — !! ONLY for purpose of interprocess communication
Definition worlddc.h:2211
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:1905
bool is_local(const keyT &key) const
Returns true if the key maps to the local processor (no communication)
Definition worlddc.h:1520
const_iterator end() const
Returns an iterator past the end of the local data (no communication)
Definition worlddc.h:1570
void serialize(const Archive &ar)
(de)Serialize — Local data only to/from anything except Buffer*Archive and Parallel*Archive
Definition worlddc.h:2165
bool is_host_replicated() const
Definition worlddc.h:1403
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:2146
void clear()
Clears all local data (no communication)
Definition worlddc.h:1607
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:1991
Future< MEMFUN_RETURNT(memfunT)> send(const keyT &key, memfunT memfun)
Sends message "resultT memfun()" to item (non-blocking comm if remote)
Definition worlddc.h:1662
implT::const_accessor const_accessor
Definition worlddc.h:1309
std::shared_ptr< implT > p
Definition worlddc.h:1314
Future< const_iterator > find(const keyT &key) const
Returns a future iterator (non-blocking communication if key not local)
Definition worlddc.h:1542
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:1846
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:1783
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:1704
void replicate_on_hosts(bool fence=true)
replicates this WorldContainer on all hosts (one PID per host)
Definition worlddc.h:1430
void check_initialized() const
Definition worlddc.h:1316
WorldContainer< keyT, valueT, hashfunT > containerT
Definition worlddc.h:1303
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:2156
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:1826
implT::accessor accessor
Definition worlddc.h:1308
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:177
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:189
void min(T *buf, size_t nelem)
Inplace global min while still processing AM & tasks.
Definition worldgop.h:896
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:2537
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 DFConvergence.h:9
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:2668
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
static XNonlinearSolver< std::vector< Function< T, NDIM > >, T, vector_function_allocator< T, NDIM > > nonlinear_vector_solver(World &world, const long nvec)
Definition nonlinsol.h:371
void swap(Function< R, MDIM > &f1, Function< R, MDIM > &f2)
Definition mra.h:3000
Definition mraimpl.h:53
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:1171
bool operator()(typename rangeT::iterator &iterator) const
Definition worlddc.h:1176
implT * impl
Definition worlddc.h:1172
P2Op(const P2Op &p)
Definition worlddc.h:1175
P2Op(implT *impl)
Definition worlddc.h:1174
Range< typename std::vector< keyT >::const_iterator > rangeT
Definition worlddc.h:1173
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:2261
static void store(const ParallelOutputArchive< localarchiveT > &ar, const WorldContainer< keyT, valueT > &t)
Definition worlddc.h:2468
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