void operator()(Block* b, const ReduceProxy& srp, const RegularSwapPartners& partners) const { int k_in = srp.in_link().size(); int k_out = srp.out_link().size(); std::vector<T> samples; if (k_in == 0) { // draw random samples for (size_t i = 0; i < num_samples; ++i) samples.push_back((b->*values)[std::rand() % (b->*values).size()]); } else dequeue_values(samples, srp, false); if (k_out == 0) { // pick subsamples that separate quantiles std::sort(samples.begin(), samples.end(), cmp); std::vector<T> subsamples(srp.nblocks() - 1); int step = samples.size() / srp.nblocks(); // NB: subsamples.size() + 1 for (size_t i = 0; i < subsamples.size(); ++i) subsamples[i] = samples[(i+1)*step]; (b->*dividers).swap(subsamples); } else { for (int i = 0; i < k_out; ++i) { MemoryBuffer& out = srp.outgoing(srp.out_link().target(i)); save(out, &samples[0], samples.size()); } } }
static void dequeue_values(std::vector<T>& v, const ReduceProxy& rp, bool skip_self = true) { auto log = get_logger(); int k_in = rp.in_link().size(); log->trace("dequeue_values(): gid={}, round={}; v.size()={}", rp.gid(), rp.round(), v.size()); if (detail::is_default< Serialization<T> >::value) { // add up sizes size_t sz = 0; size_t end = v.size(); for (int i = 0; i < k_in; ++i) { log->trace(" incoming size from {}: {}", rp.in_link().target(i).gid, sz); if (skip_self && rp.in_link().target(i).gid == rp.gid()) continue; MemoryBuffer& in = rp.incoming(rp.in_link().target(i).gid); sz += in.size() / sizeof(T); } log->trace(" incoming size: {}", sz); v.resize(end + sz); for (int i = 0; i < k_in; ++i) { if (skip_self && rp.in_link().target(i).gid == rp.gid()) continue; MemoryBuffer& in = rp.incoming(rp.in_link().target(i).gid); size_t sz = in.size() / sizeof(T); T* bg = (T*) &in.buffer[0]; std::copy(bg, bg + sz, &v[end]); end += sz; } } else { for (int i = 0; i < k_in; ++i) { if (skip_self && rp.in_link().target(i).gid == rp.gid()) continue; MemoryBuffer& in = rp.incoming(rp.in_link().target(i).gid); while(in) { T x; diy::load(in, x); v.emplace_back(std::move(x)); } } } log->trace(" v.size()={}", v.size()); }
static void dequeue_values(std::vector<T>& v, const ReduceProxy& rp, bool skip_self = true) { int k_in = rp.in_link().size(); //printf("dequeue_values(): gid=%d, round=%d; v.size()=%lu\n", rp.gid(), rp.round(), v.size()); if (detail::is_default< Serialization<T> >::value) { // add up sizes size_t sz = 0; size_t end = v.size(); for (int i = 0; i < k_in; ++i) { //printf(" incoming size from %d: %lu\n", rp.in_link().target(i).gid, sz); if (skip_self && rp.in_link().target(i).gid == rp.gid()) continue; MemoryBuffer& in = rp.incoming(rp.in_link().target(i).gid); sz += in.size() / sizeof(T); } //printf(" incoming size: %lu\n", sz); v.resize(end + sz); for (int i = 0; i < k_in; ++i) { if (skip_self && rp.in_link().target(i).gid == rp.gid()) continue; MemoryBuffer& in = rp.incoming(rp.in_link().target(i).gid); size_t sz = in.size() / sizeof(T); T* bg = (T*) &in.buffer[0]; std::copy(bg, bg + sz, &v[end]); end += sz; } } else { for (int i = 0; i < k_in; ++i) { if (skip_self && rp.in_link().target(i).gid == rp.gid()) continue; MemoryBuffer& in = rp.incoming(rp.in_link().target(i).gid); while(in) { T x; diy::load(in, x); #if __cplusplus > 199711L // C++11 v.emplace_back(std::move(x)); #else v.push_back(x); #endif } } } //printf(" v.size()=%lu\n", v.size()); }
void operator()(void* b, const ReduceProxy& srp, const RegularSwapPartners& partners) const { int k_in = srp.in_link().size(); int k_out = srp.out_link().size(); if (k_in == 0 && k_out == 0) // special case of a single block { ReduceProxy all_srp_out(srp, srp.block(), 0, srp.assigner(), empty_link, all_neighbors_link); ReduceProxy all_srp_in (srp, srp.block(), 1, srp.assigner(), all_neighbors_link, empty_link); op(b, all_srp_out); MemoryBuffer& in_queue = all_srp_in.incoming(all_srp_in.in_link().target(0).gid); in_queue.swap(all_srp_out.outgoing(all_srp_out.out_link().target(0))); in_queue.reset(); op(b, all_srp_in); return; } if (k_in == 0) // initial round { ReduceProxy all_srp(srp, srp.block(), 0, srp.assigner(), empty_link, all_neighbors_link); op(b, all_srp); Master::OutgoingQueues all_queues; all_queues.swap(*all_srp.outgoing()); // clears out the queues and stores them locally // enqueue outgoing int group = all_srp.out_link().size() / k_out; for (int i = 0; i < k_out; ++i) { std::pair<int,int> range(i*group, (i+1)*group); srp.enqueue(srp.out_link().target(i), range); for (int j = i*group; j < (i+1)*group; ++j) { int from = srp.gid(); int to = all_srp.out_link().target(j).gid; srp.enqueue(srp.out_link().target(i), std::make_pair(from, to)); srp.enqueue(srp.out_link().target(i), all_queues[all_srp.out_link().target(j)]); } } } else if (k_out == 0) // final round { // dequeue incoming + reorder into the correct order ReduceProxy all_srp(srp, srp.block(), 1, srp.assigner(), all_neighbors_link, empty_link); Master::IncomingQueues all_incoming; all_incoming.swap(*srp.incoming()); std::pair<int, int> range; // all the ranges should be the same for (int i = 0; i < k_in; ++i) { int gid_in = srp.in_link().target(i).gid; MemoryBuffer& in = all_incoming[gid_in]; load(in, range); while(in) { std::pair<int, int> from_to; load(in, from_to); load(in, all_srp.incoming(from_to.first)); all_srp.incoming(from_to.first).reset(); } } op(b, all_srp); } else // intermediate round: reshuffle queues { // add up buffer sizes std::vector<size_t> sizes_out(k_out, sizeof(std::pair<int,int>)); std::pair<int, int> range; // all the ranges should be the same for (int i = 0; i < k_in; ++i) { MemoryBuffer& in = srp.incoming(srp.in_link().target(i).gid); load(in, range); int group = (range.second - range.first)/k_out; std::pair<int, int> from_to; size_t s; while(in) { diy::load(in, from_to); diy::load(in, s); int j = (from_to.second - range.first) / group; sizes_out[j] += s + sizeof(size_t) + sizeof(std::pair<int,int>); in.skip(s); } in.reset(); } // reserve outgoing buffers of correct size int group = (range.second - range.first)/k_out; for (int i = 0; i < k_out; ++i) { MemoryBuffer& out = srp.outgoing(srp.out_link().target(i)); out.reserve(sizes_out[i]); std::pair<int, int> out_range; out_range.first = range.first + group*i; out_range.second = range.first + group*(i+1); save(out, out_range); } // re-direct the queues for (int i = 0; i < k_in; ++i) { MemoryBuffer& in = srp.incoming(srp.in_link().target(i).gid); std::pair<int, int> range; load(in, range); std::pair<int, int> from_to; while(in) { load(in, from_to); int j = (from_to.second - range.first) / group; MemoryBuffer& out = srp.outgoing(srp.out_link().target(j)); save(out, from_to); MemoryBuffer::copy(in, out); } } } }