12 #include "collection.hpp"
16 #include "serialization.hpp"
17 #include "detail/collectives.hpp"
22 #include "detail/block_traits.hpp"
49 typedef std::vector<BaseCommand*> Commands;
52 using Skip = std::function<bool(int, const Master&)>;
58 typedef Collection::Create CreateBlock;
59 typedef Collection::Destroy DestroyBlock;
60 typedef Collection::Save SaveBlock;
61 typedef Collection::Load LoadBlock;
70 using Callback = std::function<void(Block*, const ProxyWithLink&)>;
74 virtual bool unload_incoming(
const Master& master,
int from,
int to,
size_t size)
const =0;
75 virtual bool unload_outgoing(
const Master& master,
int from,
size_t size)
const =0;
83 bool unload_incoming(
const Master&,
int,
int,
size_t sz)
const {
return sz > size; }
84 bool unload_outgoing(
const Master& master,
int from,
size_t sz)
const {
return sz > size*master.outgoing_count(from); }
97 std::shared_ptr<MemoryBuffer> message;
111 struct tags {
enum { queue, piece }; };
113 typedef std::list<InFlightSend> InFlightSendsList;
114 typedef std::map<int, InFlightRecv> InFlightRecvsMap;
115 typedef std::list<int> ToSendList;
116 typedef std::list<Collective> CollectivesList;
117 typedef std::map<int, CollectivesList> CollectivesMap;
122 QueueRecord(
size_t s = 0,
int e = -1): size(s), external(e) {}
127 typedef std::map<int, QueueRecord> InQueueRecords;
128 typedef std::map<int, MemoryBuffer> IncomingQueues;
129 typedef std::map<BlockID, MemoryBuffer> OutgoingQueues;
130 typedef std::map<BlockID, QueueRecord> OutQueueRecords;
133 InQueueRecords records;
134 IncomingQueues queues;
140 OutQueueRecords external_local;
141 OutgoingQueues queues;
143 typedef std::map<int, IncomingQueuesRecords> IncomingQueuesMap;
144 typedef std::map<int, OutgoingQueuesRecord> OutgoingQueuesMap;
148 IncomingQueuesMap map;
151 typedef std::map<int, IncomingRound> IncomingRoundMap;
167 CreateBlock create_ = 0,
168 DestroyBlock destroy_ = 0,
173 blocks_(create_, destroy_, storage,
save, load_),
174 queue_policy_(q_policy),
176 threads_(threads__ == -1 ? static_cast<int>(
thread::hardware_concurrency()) : threads__),
184 ~
Master() { set_immediate(
true); clear();
delete queue_policy_; }
186 inline void destroy(
int i) {
if (blocks_.own()) blocks_.destroy(i); }
188 inline int add(
int gid,
void* b, Link* l);
192 inline void* block(
int i)
const {
return blocks_.find(i); }
193 template<
class Block>
194 Block* block(
int i)
const {
return static_cast<Block*
>(block(i)); }
195 inline Link* link(
int i)
const {
return links_[i]; }
196 inline int loaded_block()
const {
return blocks_.available(); }
198 inline void unload(
int i);
199 inline void load(
int i);
200 void unload(std::vector<int>& loaded) {
for(
unsigned i = 0; i < loaded.size(); ++i) unload(loaded[i]); loaded.clear(); }
201 void unload_all() {
for(
unsigned i = 0; i <
size(); ++i)
if (block(i) != 0) unload(i); }
202 inline bool has_incoming(
int i)
const;
204 inline void unload_queues(
int i);
205 inline void unload_incoming(
int gid);
206 inline void unload_outgoing(
int gid);
207 inline void load_queues(
int i);
208 inline void load_incoming(
int gid);
209 inline void load_outgoing(
int gid);
217 void*
get(
int i) {
return blocks_.get(i); }
219 int gid(
int i)
const {
return gids_[i]; }
221 int lid(
int gid__)
const {
return local(gid__) ? lids_.find(gid__)->second : -1; }
223 bool local(
int gid__)
const {
return lids_.find(gid__) != lids_.end(); }
227 inline void process_collectives();
230 ProxyWithLink proxy(
int i)
const;
233 unsigned int size()
const {
return static_cast<unsigned int>(blocks_.size()); }
234 void* create()
const {
return blocks_.create(); }
237 int limit()
const {
return limit_; }
238 int threads()
const {
return threads_; }
239 int in_memory()
const {
return *blocks_.in_memory().const_access(); }
241 void set_threads(
int threads__) { threads_ = threads__; }
243 CreateBlock creator()
const {
return blocks_.creator(); }
244 DestroyBlock destroyer()
const {
return blocks_.destroyer(); }
245 LoadBlock loader()
const {
return blocks_.loader(); }
246 SaveBlock saver()
const {
return blocks_.saver(); }
249 template<
class Block>
250 void foreach_(
const Callback<Block>& f,
const Skip& s = NeverSkip());
253 void foreach(
const F& f,
const Skip& s = NeverSkip())
255 using Block =
typename detail::block_traits<F>::type;
256 foreach_<Block>(f, s);
259 inline void execute();
261 bool immediate()
const {
return immediate_; }
262 void set_immediate(
bool i) {
if (i && !immediate_) execute(); immediate_ = i; }
266 IncomingQueues& incoming(
int gid__) {
return incoming_[exchange_round_].map[gid__].queues; }
267 OutgoingQueues& outgoing(
int gid__) {
return outgoing_[gid__].queues; }
268 CollectivesList& collectives(
int gid__) {
return collectives_[gid__]; }
269 size_t incoming_count(
int gid__)
const
271 IncomingRoundMap::const_iterator round_it = incoming_.find(exchange_round_);
272 if (round_it == incoming_.end())
274 IncomingQueuesMap::const_iterator queue_it = round_it->second.map.find(gid__);
275 if (queue_it == round_it->second.map.end())
277 return queue_it->second.queues.size();
279 size_t outgoing_count(
int gid__)
const { OutgoingQueuesMap::const_iterator it = outgoing_.find(gid__);
if (it == outgoing_.end())
return 0;
return it->second.queues.size(); }
281 void set_expected(
int expected) { expected_ = expected; }
282 void add_expected(
int i) { expected_ += i; }
283 int expected()
const {
return expected_; }
284 void replace_link(
int i, Link* link__) { expected_ -= links_[i]->size_unique();
delete links_[i]; links_[i] = link__; expected_ += links_[i]->size_unique(); }
292 inline void comm_exchange(ToSendList& to_send,
int out_queues_limit);
295 void cancel_requests();
298 inline void show_incoming_records()
const;
301 std::vector<Link*> links_;
303 std::vector<int> gids_;
304 std::map<int, int> lids_;
306 QueuePolicy* queue_policy_;
310 ExternalStorage* storage_;
314 mpi::communicator comm_;
315 IncomingRoundMap incoming_;
316 OutgoingQueuesMap outgoing_;
317 InFlightSendsList inflight_sends_;
318 InFlightRecvsMap inflight_recvs_;
319 CollectivesMap collectives_;
326 fast_mutex add_mutex_;
329 std::shared_ptr<spd::logger> log = get_logger();
330 stats::Profiler prof;
336 virtual void execute(
void* b,
const ProxyWithLink& cp)
const =0;
337 virtual bool skip(
int i,
const Master& master)
const =0;
340 template<
class Block>
343 Command(Callback<Block> f_,
const Skip& s_):
346 void execute(
void* b,
const ProxyWithLink& cp)
const override { f(static_cast<Block*>(b), cp); }
347 bool skip(
int i,
const Master& m)
const override {
return s(i,m); }
354 {
bool operator()(
int i,
const Master& master)
const {
return !master.has_incoming(i); } };
364 cop_(0) { swap(const_cast<Collective&>(other)); }
367 void init() { cop_->init(); }
368 void swap(
Collective& other) { std::swap(cop_, other.cop_); }
369 void update(
const Collective& other) { cop_->update(*other.cop_); }
371 void copy_from(
Collective& other)
const { cop_->copy_from(*other.cop_); }
372 void result_out(
void* x)
const { cop_->result_out(x); }
374 detail::CollectiveOp* cop_;
387 const std::deque<int>& blocks__,
392 local_limit(local_limit_),
398 master.log->debug(
"Processing with thread: {}", this_thread::get_id());
400 std::vector<int>
local;
403 int cur = (*idx.access())++;
405 if ((
size_t)cur >= blocks.size())
411 if (local.size() == (size_t)local_limit)
412 master.unload(local);
416 master.log->debug(
"Processing block: {}", master.
gid(i));
418 bool skip_block =
true;
419 for (
size_t cmd = 0; cmd < master.commands_.size(); ++cmd)
421 if (!master.commands_[cmd]->skip(i, master))
428 IncomingQueuesMap ¤t_incoming = master.incoming_[master.exchange_round_].map;
431 if (master.block(i) == 0)
432 master.load_queues(i);
434 for (
size_t cmd = 0; cmd < master.commands_.size(); ++cmd)
436 master.commands_[cmd]->execute(0, master.proxy(i));
439 current_incoming[master.
gid(i)].queues.clear();
440 current_incoming[master.
gid(i)].records.clear();
443 if (master.block(i) == 0)
444 master.unload_queues(i);
448 if (master.block(i) == 0)
450 if (local.size() == (size_t)local_limit)
451 master.unload(local);
457 for (
size_t cmd = 0; cmd < master.commands_.size(); ++cmd)
459 master.commands_[cmd]->execute(master.block(i), master.proxy(i));
462 current_incoming[master.
gid(i)].queues.clear();
463 current_incoming[master.
gid(i)].records.clear();
472 static void run(
void* bf) {
static_cast<ProcessBlock*
>(bf)->process(); }
475 const std::deque<int>& blocks;
485 for (
unsigned i = 0; i <
size(); ++i)
498 log->debug(
"Unloading block: {}", gid(i));
508 unload_incoming(gid(i));
509 unload_outgoing(gid(i));
514 unload_incoming(
int gid__)
516 for (IncomingRoundMap::iterator round_itr = incoming_.begin(); round_itr != incoming_.end(); ++round_itr)
518 IncomingQueuesMap::iterator qmap_itr = round_itr->second.map.find(gid__);
519 if (qmap_itr == round_itr->second.map.end())
523 IncomingQueuesRecords& in_qrs = qmap_itr->second;
524 for (InQueueRecords::iterator it = in_qrs.records.begin(); it != in_qrs.records.end(); ++it)
526 QueueRecord& qr = it->second;
527 if (queue_policy_->unload_incoming(*
this, it->first, gid__, qr.size))
529 log->debug(
"Unloading queue: {} <- {}", gid__, it->first);
530 qr.external = storage_->put(in_qrs.queues[it->first]);
538 unload_outgoing(
int gid__)
540 OutgoingQueuesRecord& out_qr = outgoing_[gid__];
542 size_t out_queues_size =
sizeof(size_t);
544 for (OutgoingQueues::iterator it = out_qr.queues.begin(); it != out_qr.queues.end(); ++it)
546 if (it->first.proc == comm_.rank())
continue;
548 out_queues_size +=
sizeof(BlockID);
549 out_queues_size +=
sizeof(size_t);
550 out_queues_size +=
sizeof(size_t);
551 out_queues_size += it->second.size();
554 if (queue_policy_->unload_outgoing(*
this, gid__, out_queues_size -
sizeof(
size_t)))
556 log->debug(
"Unloading outgoing queues: {} -> ...; size = {}\n", gid__, out_queues_size);
557 MemoryBuffer bb; bb.reserve(out_queues_size);
560 for (OutgoingQueues::iterator it = out_qr.queues.begin(); it != out_qr.queues.end();)
562 if (it->first.proc == comm_.rank())
565 if (queue_policy_->unload_incoming(*
this, gid__, it->first.gid, it->second.size()))
567 QueueRecord& qr = out_qr.external_local[it->first];
568 qr.size = it->second.size();
569 qr.external = storage_->put(it->second);
571 out_qr.queues.erase(it++);
579 out_qr.queues.erase(it++);
587 out_qr.external = storage_->put(bb);
595 log->debug(
"Loading block: {}", gid(i));
605 load_incoming(gid(i));
606 load_outgoing(gid(i));
611 load_incoming(
int gid__)
613 IncomingQueuesRecords& in_qrs = incoming_[exchange_round_].map[gid__];
614 for (InQueueRecords::iterator it = in_qrs.records.begin(); it != in_qrs.records.end(); ++it)
616 QueueRecord& qr = it->second;
617 if (qr.external != -1)
619 log->debug(
"Loading queue: {} <- {}", gid__, it->first);
620 storage_->get(qr.external, in_qrs.queues[it->first]);
628 load_outgoing(
int gid__)
632 OutgoingQueuesRecord& out_qr = outgoing_[gid__];
633 if (out_qr.external != -1)
636 storage_->get(out_qr.external, bb);
637 out_qr.external = -1;
641 for (
size_t i = 0; i < count; ++i)
653 {
return ProxyWithLink(Proxy(const_cast<Master*>(
this), gid(i)), block(i), link(i)); }
660 if (*blocks_.in_memory().const_access() == limit_)
667 gids_.push_back(gid__);
669 int lid__ =
static_cast<int>(gids_.size()) - 1;
670 lids_[gid__] = lid__;
671 add_expected(l->size_unique());
680 void* b = blocks_.release(i);
681 delete link(i); links_[i] = 0;
688 has_incoming(
int i)
const
690 const IncomingQueuesRecords& in_qrs =
const_cast<Master&
>(*this).incoming_[exchange_round_].map[gid(i)];
691 for (InQueueRecords::const_iterator it = in_qrs.records.begin(); it != in_qrs.records.end(); ++it)
693 const QueueRecord& qr = it->second;
700 template<
class Block>
703 foreach_(
const Callback<Block>& f,
const Skip& skip)
705 auto scoped = prof.scoped(
"foreach");
718 log->debug(
"Entered execute()");
719 auto scoped = prof.scoped(
"execute");
724 for (
unsigned i = 0; i < size(); ++i)
731 if (commands_.empty())
735 std::deque<int> blocks;
736 for (
unsigned i = 0; i < size(); ++i)
740 blocks.push_front(i);
744 int blocks_per_thread;
747 num_threads = threads_;
748 blocks_per_thread = size();
752 num_threads = std::min(threads_, limit_);
753 blocks_per_thread = limit_/num_threads;
757 critical_resource<int> idx(0);
759 typedef ProcessBlock BlockFunctor;
763 typedef std::pair<thread*, BlockFunctor*> ThreadFunctorPair;
764 typedef std::list<ThreadFunctorPair> ThreadFunctorList;
765 ThreadFunctorList threads;
766 for (
unsigned i = 0; i < (unsigned)num_threads; ++i)
768 BlockFunctor* bf =
new BlockFunctor(*
this, blocks, blocks_per_thread, idx);
769 threads.push_back(ThreadFunctorPair(
new thread(&BlockFunctor::run, bf), bf));
773 for(ThreadFunctorList::iterator it = threads.begin(); it != threads.end(); ++it)
775 thread* t = it->first;
776 BlockFunctor* bf = it->second;
783 BlockFunctor bf(*
this, blocks, blocks_per_thread, idx);
784 BlockFunctor::run(&bf);
788 incoming_[exchange_round_].map.clear();
790 if (limit() != -1 && in_memory() > limit())
791 throw std::runtime_error(fmt::format(
"Fatal: {} blocks in memory, with limit {}", in_memory(), limit()));
794 for (
size_t i = 0; i < commands_.size(); ++i)
803 auto scoped = prof.scoped(
"exchange");
808 log->debug(
"Starting exchange");
811 for (
int i = 0; i < (int)size(); ++i)
813 OutgoingQueues& outgoing_queues = outgoing_[gid(i)].queues;
814 OutQueueRecords& external_local = outgoing_[gid(i)].external_local;
815 if (outgoing_queues.size() < (size_t)link(i)->size())
816 for (
unsigned j = 0; j < (unsigned)link(i)->size(); ++j)
818 if (external_local.find(link(i)->target(j)) == external_local.end())
819 outgoing_queues[link(i)->target(j)];
824 log->debug(
"Finished exchange");
831 template <
typename T>
843 template<
typename T>
struct is_mpi_datatype< diy::detail::VectorWindow<T> > {
typedef true_type type; };
845 template <
typename T>
846 struct mpi_datatype< diy::detail::VectorWindow<T> >
848 typedef diy::detail::VectorWindow<T> VecWin;
849 static MPI_Datatype datatype() {
return get_mpi_datatype<T>(); }
850 static const void* address(
const VecWin& x) {
return x.begin; }
851 static void* address(VecWin& x) {
return x.begin; }
852 static int count(
const VecWin& x) {
return static_cast<int>(x.count); }
862 comm_exchange(ToSendList& to_send,
int out_queues_limit)
864 static const size_t MAX_MPI_MESSAGE_COUNT = INT_MAX;
866 IncomingRound ¤t_incoming = incoming_[exchange_round_];
868 while(inflight_sends_.size() < (size_t)out_queues_limit && !to_send.empty())
870 int from = to_send.front();
873 for (OutQueueRecords::iterator it = outgoing_[from].external_local.begin(); it != outgoing_[from].external_local.end(); ++it)
875 int to = it->first.gid;
877 log->debug(
"Processing local queue: {} <- {} of size {}", to, from, it->second.size);
879 QueueRecord& in_qr = current_incoming.map[to].records[from];
880 bool in_external = block(lid(to)) == 0;
887 in_qr.size = it->second.size;
891 storage_->get(it->second.external, bb);
893 current_incoming.map[to].queues[from].swap(bb);
895 ++current_incoming.received;
897 outgoing_[from].external_local.clear();
899 if (outgoing_[from].external != -1)
903 OutgoingQueues& outgoing = outgoing_[from].queues;
904 for (OutgoingQueues::iterator it = outgoing.begin(); it != outgoing.end(); ++it)
906 BlockID to_proc = it->first;
907 int to = to_proc.gid;
908 int proc = to_proc.proc;
910 log->debug(
"Processing queue: {} <- {} of size {}", to, from, outgoing_[from].queues[to_proc].size());
913 if (proc == comm_.rank())
915 log->debug(
"Moving queue in-place: {} <- {}", to, from);
917 QueueRecord& in_qr = current_incoming.map[to].records[from];
918 bool in_external = block(lid(to)) == 0;
921 log->debug(
"Unloading outgoing directly as incoming: {} <- {}", to, from);
922 MemoryBuffer& bb = it->second;
923 in_qr.size = bb.size();
924 if (queue_policy_->unload_incoming(*
this, from, to, in_qr.size))
925 in_qr.external = storage_->put(bb);
928 MemoryBuffer& in_bb = current_incoming.map[to].queues[from];
935 log->debug(
"Swapping in memory: {} <- {}", to, from);
936 MemoryBuffer& bb = current_incoming.map[to].queues[from];
939 in_qr.size = bb.size();
943 ++current_incoming.received;
947 std::shared_ptr<MemoryBuffer> buffer = std::make_shared<MemoryBuffer>();
948 buffer->swap(it->second);
950 MessageInfo info{from, to, exchange_round_};
951 if (buffer->size() <= (MAX_MPI_MESSAGE_COUNT -
sizeof(info)))
955 inflight_sends_.emplace_back();
956 inflight_sends_.back().info = info;
957 inflight_sends_.back().request = comm_.isend(proc, tags::queue, buffer->buffer);
958 inflight_sends_.back().message = buffer;
962 int npieces =
static_cast<int>((buffer->size() + MAX_MPI_MESSAGE_COUNT - 1)/MAX_MPI_MESSAGE_COUNT);
965 std::shared_ptr<MemoryBuffer> hb = std::make_shared<MemoryBuffer>();
969 inflight_sends_.emplace_back();
970 inflight_sends_.back().info = info;
971 inflight_sends_.back().request = comm_.isend(proc, tags::piece, hb->buffer);
972 inflight_sends_.back().message = hb;
975 size_t msg_buff_idx = 0;
976 for (
int i = 0; i < npieces; ++i, msg_buff_idx += MAX_MPI_MESSAGE_COUNT)
978 int tag = (i == (npieces - 1)) ? tags::queue : tags::piece;
980 detail::VectorWindow<char> window;
981 window.begin = &buffer->buffer[msg_buff_idx];
982 window.count = std::min(MAX_MPI_MESSAGE_COUNT, buffer->size() - msg_buff_idx);
984 inflight_sends_.emplace_back();
985 inflight_sends_.back().info = info;
986 inflight_sends_.back().request = comm_.isend(proc, tag, window);
987 inflight_sends_.back().message = buffer;
997 mpi::optional<mpi::status> ostatus = comm_.iprobe(mpi::any_source, mpi::any_tag);
1000 InFlightRecv &ir = inflight_recvs_[ostatus->source()];
1002 if (ir.info.from == -1)
1005 comm_.recv(ostatus->source(), ostatus->tag(), bb.buffer);
1007 if (ostatus->tag() == tags::piece)
1013 ir.message.buffer.reserve(msg_size);
1018 ir.message.swap(bb);
1023 size_t start_idx = ir.message.buffer.size();
1024 size_t count = ostatus->count<
char>();
1025 ir.message.buffer.resize(start_idx + count);
1027 detail::VectorWindow<char> window;
1028 window.begin = &ir.message.buffer[start_idx];
1029 window.count = count;
1031 comm_.recv(ostatus->source(), ostatus->tag(), window);
1034 if (ostatus->tag() == tags::queue)
1036 size_t size = ir.message.size();
1037 int from = ir.info.from;
1038 int to = ir.info.to;
1041 assert(ir.info.round >= exchange_round_);
1042 IncomingRound *
in = &incoming_[ir.info.round];
1044 bool unload_queue = ((ir.info.round == exchange_round_) ? (block(lid(to)) == 0) : (limit_ != -1)) &&
1045 queue_policy_->unload_incoming(*
this, from, to, size);
1048 log->debug(
"Directly unloading queue {} <- {}", to, from);
1049 external = storage_->put(ir.message);
1053 in->map[to].queues[from].swap(ir.message);
1054 in->map[to].queues[from].reset();
1056 in->map[to].records[from] = QueueRecord(size, external);
1059 ir = InFlightRecv();
1062 ostatus = comm_.iprobe(mpi::any_source, mpi::any_tag);
1071 time_type start = get_time();
1076 incoming_.erase(exchange_round_);
1081 for (OutgoingQueuesMap::iterator it = outgoing_.begin(); it != outgoing_.end(); ++it)
1083 OutgoingQueuesRecord& out = it->second;
1084 if (out.external == -1)
1085 to_send.push_front(it->first);
1087 to_send.push_back(it->first);
1089 log->debug(
"to_send.size(): {}", to_send.size());
1093 int out_queues_limit;
1094 if (limit_ == -1 || size() == 0)
1095 out_queues_limit = static_cast<int>(to_send.size());
1097 out_queues_limit =
static_cast<int>(std::max((
size_t) 1, to_send.size()/size()*limit_));
1101 comm_exchange(to_send, out_queues_limit);
1104 time_type cur = get_time();
1105 if (cur - start > wait*1000)
1107 log->warn(
"Waiting in flush [{}]: {} - {} out of {}",
1108 comm_.rank(), inflight_sends_.size(), incoming_[exchange_round_].received, expected_);
1112 }
while (!inflight_sends_.empty() || incoming_[exchange_round_].received < expected_ || !to_send.empty());
1116 log->debug(
"Done in flush");
1119 process_collectives();
1124 process_collectives()
1126 auto scoped = prof.scoped(
"collectives");
1129 if (collectives_.empty())
1132 typedef CollectivesList::iterator CollectivesIterator;
1133 std::vector<CollectivesIterator> iters;
1134 std::vector<int> gids;
1135 for (CollectivesMap::iterator cur = collectives_.begin(); cur != collectives_.end(); ++cur)
1137 gids.push_back(cur->first);
1138 iters.push_back(cur->second.begin());
1141 while (iters[0] != collectives_.begin()->second.end())
1144 for (
unsigned j = 1; j < iters.size(); ++j)
1147 iters[0]->update(*iters[j]);
1149 iters[0]->global(comm_);
1151 for (
unsigned j = 1; j < iters.size(); ++j)
1153 iters[j]->copy_from(*iters[0]);
1165 bool success =
false;
1166 for (InFlightSendsList::iterator it = inflight_sends_.begin(); it != inflight_sends_.end();)
1168 mpi::optional<mpi::status> ostatus = it->request.test();
1172 it = inflight_sends_.erase(it);
1184 show_incoming_records()
const
1186 for (IncomingRoundMap::const_iterator rounds_itr = incoming_.begin(); rounds_itr != incoming_.end(); ++rounds_itr)
1188 for (IncomingQueuesMap::const_iterator it = rounds_itr->second.map.begin(); it != rounds_itr->second.map.end(); ++it)
1190 const IncomingQueuesRecords& in_qrs = it->second;
1191 for (InQueueRecords::const_iterator cur = in_qrs.records.begin(); cur != in_qrs.records.end(); ++cur)
1193 const QueueRecord& qr = cur->second;
1194 log->info(
"round: {}, {} <- {}: (size,external) = ({},{})",
1196 it->first, cur->first,
1200 for (IncomingQueues::const_iterator cur = in_qrs.queues.begin(); cur != in_qrs.queues.end(); ++cur)
1202 log->info(
"round: {}, {} <- {}: queue.size() = {}",
1204 it->first, cur->first,
1205 const_cast<IncomingQueuesRecords&>(in_qrs).queues[cur->first].size());
Definition: master.hpp:120
Definition: master.hpp:95
void load(BinaryBuffer &bb, T &x)
Loads x from bb by calling diy::Serialization<T>::load(bb,x).
Definition: serialization.hpp:106
void load_back(BinaryBuffer &bb, T &x)
Supports only binary data copying (meant for simple footers).
Definition: serialization.hpp:120
Definition: master.hpp:356
Definition: master.hpp:146
Definition: storage.hpp:38
Definition: proxy.hpp:134
void save(BinaryBuffer &bb, const T &x)
Saves x to bb by calling diy::Serialization<T>::save(bb,x).
Definition: serialization.hpp:102
int gid(int i) const
return gid of the i-th block
Definition: master.hpp:219
Definition: master.hpp:384
unsigned int size() const
return the number of local blocks
Definition: master.hpp:233
int lid(int gid__) const
return the local id of the local block with global id gid, or -1 if not local
Definition: master.hpp:221
Master(mpi::communicator comm, int threads__=1, int limit__=-1, CreateBlock create_=0, DestroyBlock destroy_=0, ExternalStorage *storage=0, SaveBlock save=0, LoadBlock load_=0, QueuePolicy *q_policy=new QueueSizePolicy(4096))
The main DIY object.
Definition: master.hpp:164
void foreach_(const Callback< Block > &f, const Skip &s=NeverSkip())
call f with every block
Definition: master.hpp:703
void in(const RegularLink< Bounds > &link, const Point &p, OutIter out, const Bounds &domain)
Finds the neighbor(s) containing the target point.
Definition: pick.hpp:102
Definition: master.hpp:41
int add(int gid, void *b, Link *l)
add a block
Definition: master.hpp:658
Definition: master.hpp:35
Simple wrapper around MPI_Comm.
Definition: communicator.hpp:8
Communication proxy, used for enqueueing and dequeueing items for future exchange.
Definition: proxy.hpp:8
Definition: serialization.hpp:26
Definition: no-thread.hpp:27
Definition: master.hpp:353
Definition: master.hpp:72
Definition: master.hpp:333
Definition: master.hpp:47
const mpi::communicator & communicator() const
return the MPI communicator
Definition: master.hpp:212
void * release(int i)
release ownership of the block
Definition: master.hpp:678
Definition: request.hpp:5
Definition: master.hpp:136
Definition: master.hpp:55
bool local(int gid__) const
whether the block with global id gid is local
Definition: master.hpp:223
Definition: master.hpp:89
void exchange()
exchange the queues between all the blocks (collective operation)
Definition: master.hpp:801
Definition: master.hpp:104
Move queues out of core if their size exceeds a parameter given in the constructor.
Definition: master.hpp:80
Definition: master.hpp:131
mpi::communicator & communicator()
return the MPI communicator
Definition: master.hpp:214
Definition: no-thread.hpp:9