void extract_kdtree_block(KDTreeBlock* b, const diy::Master::ProxyWithLink& cp, diy::Master& tess_master) { int tess_lid = tess_master.lid(cp.gid()); DBlock* d = (DBlock*) tess_master.block(tess_lid); // assumes all blocks in memory // copy out the particles d->num_particles = d->num_orig_particles = b->points.size(); d->particles = (float *)realloc(d->particles, b->points.size() * 3 * sizeof(float)); for (size_t i = 0; i < d->num_orig_particles; ++i) { d->particles[3*i + 0] = b->points[i][0]; d->particles[3*i + 1] = b->points[i][1]; d->particles[3*i + 2] = b->points[i][2]; } //fprintf(stderr, "[%d]: %d particles copied out\n", cp.gid(), d->num_orig_particles); // steal the link diy::RegularContinuousLink* tess_link = static_cast<diy::RegularContinuousLink*>(tess_master.link(tess_lid)); diy::RegularContinuousLink* kdtree_link = static_cast<diy::RegularContinuousLink*>(cp.link()); tess_link->swap(*kdtree_link); d->box = tess_link->bounds(); for (int i = 0; i < 3; ++i) { d->bounds.min[i] = tess_link->bounds().min[i]; d->bounds.max[i] = tess_link->bounds().max[i]; } delete b; // safe to do since kdtree_master doesn't own the blocks (no create/destroy supplied) }
void print_block(Block* b, const diy::Master::ProxyWithLink& cp, bool verbose) { RCLink* link = static_cast<RCLink*>(cp.link()); fmt::print("{}: [{},{},{}] - [{},{},{}] ({} neighbors): {} points\n", cp.gid(), link->bounds().min[0], link->bounds().min[1], link->bounds().min[2], link->bounds().max[0], link->bounds().max[1], link->bounds().max[2], link->size(), b->points.size()); for (int i = 0; i < link->size(); ++i) { fmt::print(" ({},{},({},{},{})):", link->target(i).gid, link->target(i).proc, link->direction(i)[0], link->direction(i)[1], link->direction(i)[2]); const Bounds& bounds = link->bounds(i); fmt::print(" [{},{},{}] - [{},{},{}]\n", bounds.min[0], bounds.min[1], bounds.min[2], bounds.max[0], bounds.max[1], bounds.max[2]); } if (verbose) for (size_t i = 0; i < b->points.size(); ++i) fmt::print(" {} {} {}\n", b->points[i][0], b->points[i][1], b->points[i][2]); }
void output(void* b_, const diy::Master::ProxyWithLink& cp, void*) { Block* b = static_cast<Block*>(b_); std::cout << cp.gid() << " " << b->average << std::endl; for (int i = 0; i < cp.link()->size(); ++i) std::cout << " " << cp.link()->target(i).gid << " " << cp.link()->target(i).proc << std::endl; }
void verify(Block*, const diy::Master::ProxyWithLink& cp) { for (auto in : *cp.incoming()) { std::int64_t recvd_sum; std::vector<std::int64_t> buffer; cp.dequeue(in.first, buffer); cp.dequeue(in.first, recvd_sum); std::int64_t comp_sum = 0; bool valid_values = true; for (int64_t v : buffer) { if (v < -9 || v > 9) { valid_values = false; break; } comp_sum += v; } CHECK(valid_values == true); CHECK(recvd_sum == comp_sum); } }
void flip_coin(void* b_, const diy::Master::ProxyWithLink& cp, void*) { Block* b = static_cast<Block*>(b_); b->count++; bool done = rand() % 2; //std::cout << cp.gid() << " " << done << " " << b->count << std::endl; cp.collectives()->clear(); cp.all_reduce(done, std::logical_and<bool>()); }
// the rest is optional void show_link(const diy::Master::ProxyWithLink& cp) { diy::RegularLink<Bounds>* link = static_cast<diy::RegularLink<Bounds>*>(cp.link()); std::cout << "Block (" << cp.gid() << "): " << link->core().min[0] << ' ' << link->core().min[1] << ' ' << link->core().min[2] << " - " << link->core().max[0] << ' ' << link->core().max[1] << ' ' << link->core().max[2] << " : " << link->bounds().min[0] << ' ' << link->bounds().min[1] << ' ' << link->bounds().min[2] << " - " << link->bounds().max[0] << ' ' << link->bounds().max[1] << ' ' << link->bounds().max[2] << " : " << link->size() << ' ' //<< std::endl << std::dec << std::endl; }
void local_sum(Block* b, const diy::Master::ProxyWithLink& cp) { std::default_random_engine generator(cp.gid()); std::uniform_int_distribution<std::int64_t> distribution(-9, 9); std::int64_t sum = 0; std::vector<std::int64_t> buffer(b->size); for (auto &v : buffer) { v = distribution(generator); sum += v; } diy::Link* l = cp.link(); for (int i = 0; i < l->size(); ++i) { cp.enqueue(l->target(i), buffer); cp.enqueue(l->target(i), sum); } }
void populate_kdtree_block(DBlock* d, const diy::Master::ProxyWithLink& cp, diy::Master& kdtree_master, bool wrap) { diy::ContinuousBounds domain = d->data_bounds; KDTreeBlock* b = new KDTreeBlock; diy::RegularContinuousLink* l = new diy::RegularContinuousLink(3, domain, domain); kdtree_master.add(cp.gid(), b, l); // copy the particles over b->points.resize(d->num_orig_particles); for (size_t i = 0; i < d->num_orig_particles; ++i) { b->points[i][0] = d->particles[3*i + 0]; b->points[i][1] = d->particles[3*i + 1]; b->points[i][2] = d->particles[3*i + 2]; } }
void min_max(void* b_, const diy::Master::ProxyWithLink& cp, void*) { Block* b = static_cast<Block*>(b_); cp.all_reduce(b->points.size(), diy::mpi::minimum<size_t>()); cp.all_reduce(b->points.size(), diy::mpi::maximum<size_t>()); }
void verify_block(Block* b, const diy::Master::ProxyWithLink& cp, bool wrap, const Bounds& domain) { RCLink* link = static_cast<RCLink*>(cp.link()); for (size_t i = 0; i < b->points.size(); ++i) for (unsigned j = 0; j < DIM; ++j) { INFO("Point " << i << " outside bounds in dimension " << j); CHECK(b->points[i][j] >= link->bounds().min[j]); CHECK(b->points[i][j] <= link->bounds().max[j]); } // verify neighbor bounds for (int i = 0; i < link->size(); ++i) { int nbr_gid = link->target(i).gid; INFO("Checking that bounds in the link match actual remote block bounds for gid = " << nbr_gid); CHECK (link->bounds(i) == b->block_bounds[nbr_gid]); } // verify wrap if (wrap) for (int i = 0; i < link->size(); ++i) { for (unsigned j = 0; j < DIM; ++j) { if (link->wrap(i)[j] == -1) { INFO("Checking wrap matches: " << cp.gid() << " -> " << link->target(i).gid); CHECK(link->bounds().min[j] == domain.min[j]); CHECK(link->bounds(i).max[j] == domain.max[j]); } if (link->wrap(i)[j] == 1) { INFO("Checking wrap matches: " << cp.gid() << " -> " << link->target(i).gid); CHECK(link->bounds().max[j] == domain.max[j]); CHECK(link->bounds(i).min[j] == domain.min[j]); } } } // verify that we intersect everybody in the link for (int i = 0; i < link->size(); ++i) for (unsigned j = 0; j < DIM; ++j) { INFO("Checking neighbor intersection: " << cp.gid() << " -> " << link->target(i).gid); CHECK(intersects(link->bounds(), link->bounds(i), j, wrap, domain)); } // verify that we don't intersect anybody not in the link for (int i = 0; i < (int) b->block_bounds.size(); ++i) { if (i == cp.gid()) continue; unsigned j = 0; for (; j < DIM; ++j) { if (!intersects(link->bounds(), b->block_bounds[i], j, wrap, domain)) break; } if (j == DIM) // intersect { int k = 0; for (; k < link->size(); ++k) { if (link->target(k).gid == i) break; } INFO("Checking whether we intersect a block not in the link: " << cp.gid() << " -/-> " << i); CHECK(k != link->size()); } } }