void test(int n, int k) { int dim = 2; diy::DiscreteBounds global_bounds(dim); global_bounds.min[0] = global_bounds.min[1] = 0; global_bounds.max[0] = global_bounds.min[1] = 1023; diy::RegularDecomposer<diy::DiscreteBounds> decomposer(dim, global_bounds, n); diy::RegularPartners partners(decomposer, k, false); int kvs_product = 1; for (size_t i = 0; i < partners.rounds(); ++i) kvs_product *= partners.size(i); REQUIRE(kvs_product == n); for (int gid = 0; gid < n; ++gid) for (size_t i = 0; i < partners.rounds(); ++i) { std::vector<int> nbr_gids; partners.fill(i, gid, nbr_gids); for (int nbr_gid : nbr_gids) CHECK(nbr_gid <= n); } }
void sort(Master& master, //!< master object const Assigner& assigner, //!< assigner object std::vector<T> Block::* values, //!< all values to sort std::vector<T> Block::* samples, //!< (output) boundaries of blocks size_t num_samples, //!< desired number of samples const Cmp& cmp, //!< comparison function int k = 2, //!< k-ary reduction will be used bool samples_only = false) //!< false: results will be all_to_all exchanged; true: only sort but don't exchange results { bool immediate = master.immediate(); master.set_immediate(false); // NB: although sorter will go out of scope, its member functions sample() // and exchange() will return functors whose copies get saved inside reduce detail::SampleSort<Block,T,Cmp> sorter(values, samples, cmp, num_samples); // swap-reduce to all-gather samples RegularDecomposer<DiscreteBounds> decomposer(1, interval(0,assigner.nblocks()), assigner.nblocks()); RegularSwapPartners partners(decomposer, k); reduce(master, assigner, partners, sorter.sample(), detail::SkipIntermediate(partners.rounds())); // all_to_all to exchange the values if (!samples_only) all_to_all(master, assigner, sorter.exchange(), k); master.set_immediate(immediate); }
int main(int argc, char* argv[]) { diy::mpi::environment env(argc, argv); // diy equivalent of MPI_Init diy::mpi::communicator world; // diy equivalent of MPI communicator int size = 8; // total number of MPI processes int nblocks = 32; // total number of blocks in global domain diy::ContiguousAssigner assigner(size, nblocks); Bounds domain; // global data size domain.min[0] = domain.min[1] = domain.min[2] = 0; domain.max[0] = domain.max[1] = domain.max[2] = 255; int rank = world.rank(); // MPI rank of this process std::cout << "Rank " << rank << ":" << std::endl; diy::Master master(world, 1, // one thread -1, // all blocks in memory &Block::create, &Block::destroy); AddBlock addblock(master); // object for adding new blocks to master // share_face is an n-dim (size 3 in this example) vector of bools // indicating whether faces are shared in each dimension // uninitialized values default to false diy::RegularDecomposer<Bounds>::BoolVector share_face; share_face.push_back(true); // wrap is an n-dim (size 3 in this example) vector of bools // indicating whether boundary conditions are periodic in each dimension // uninitialized values default to false diy::RegularDecomposer<Bounds>::BoolVector wrap; wrap.push_back(true); wrap.push_back(true); // ghosts is an n-dim (size 3 in this example) vector of ints // indicating number of ghost cells per side in each dimension // uninitialized values default to 0 diy::RegularDecomposer<Bounds>::CoordinateVector ghosts; ghosts.push_back(1); ghosts.push_back(2); // either create the regular decomposer and call its decompose function // (having the decomposer available is useful for its other member functions diy::RegularDecomposer<Bounds> decomposer(3, domain, assigner, share_face, wrap, ghosts); decomposer.decompose(rank, addblock); // or combine the two lines above into the following helper function // but the decomposer gets destroyed afterwards // diy::decompose(3, rank, domain, assigner, addblock, share_face, wrap, ghosts); // display the decomposition master.foreach(&Block::show_link); }
//------------------------------------------------------------------------ // DecomposeLongs::DecomposeRange: // Do LONG decomposition on all the nodes in the given range. This must // be done before inserting a range of un-decomposed IR into a block // that has already been decomposed. // // Arguments: // compiler - The compiler context. // blockWeight - The weight of the block into which the range will be // inserted. // range - The range to decompose. // // Return Value: // None. // void DecomposeLongs::DecomposeRange(Compiler* compiler, unsigned blockWeight, LIR::Range& range) { assert(compiler != nullptr); DecomposeLongs decomposer(compiler); decomposer.m_blockWeight = blockWeight; decomposer.m_range = ⦥ decomposer.DecomposeRangeHelper(); }
//---------------------------------------------------------------------------- int ExtractRidges::Main (int, char**) { std::string imageName = Environment::GetPathR("Head.im"); ImageDouble2D image(imageName.c_str()); // Normalize the image values to be in [0,1]. int quantity = image.GetQuantity(); double minValue = image[0], maxValue = minValue; int i; for (i = 1; i < quantity; ++i) { if (image[i] < minValue) { minValue = image[i]; } else if (image[i] > maxValue) { maxValue = image[i]; } } double invRange = 1.0/(maxValue - minValue); for (i = 0; i < quantity; ++i) { image[i] = (image[i] - minValue)*invRange; } // Use first-order centered finite differences to estimate the image // derivatives. The gradient is DF = (df/dx, df/dy) and the Hessian // is D^2F = {{d^2f/dx^2, d^2f/dxdy}, {d^2f/dydx, d^2f/dy^2}}. int xBound = image.GetBound(0); int yBound = image.GetBound(1); int xBoundM1 = xBound - 1; int yBoundM1 = yBound - 1; ImageDouble2D dx(xBound, yBound); ImageDouble2D dy(xBound, yBound); ImageDouble2D dxx(xBound, yBound); ImageDouble2D dxy(xBound, yBound); ImageDouble2D dyy(xBound, yBound); int x, y; for (y = 1; y < yBoundM1; ++y) { for (x = 1; x < xBoundM1; ++x) { dx(x, y) = 0.5*(image(x+1, y) - image(x-1, y)); dy(x, y) = 0.5*(image(x, y+1) - image(x, y-1)); dxx(x, y) = image(x+1, y) - 2.0*image(x, y) + image(x-1, y); dxy(x, y) = 0.25*(image(x+1, y+1) + image(x-1, y-1) - image(x+1, y-1) - image(x-1, y+1)); dyy(x, y) = image(x, y+1) - 2.0*image(x, y) + image(x, y+1); } } dx.Save("dx.im"); dy.Save("dy.im"); dxx.Save("dxx.im"); dxy.Save("dxy.im"); dyy.Save("dyy.im"); // The eigensolver produces eigenvalues a and b and corresponding // eigenvectors U and V: D^2F*U = a*U, D^2F*V = b*V. Define // P = Dot(U,DF) and Q = Dot(V,DF). The classification is as follows. // ridge: P = 0 with a < 0 // valley: Q = 0 with b > 0 ImageDouble2D aImage(xBound, yBound); ImageDouble2D bImage(xBound, yBound); ImageDouble2D pImage(xBound, yBound); ImageDouble2D qImage(xBound, yBound); for (y = 1; y < yBoundM1; ++y) { for (x = 1; x < xBoundM1; ++x) { Vector2d gradient(dx(x, y), dy(x, y)); Matrix2d hessian(dxx(x, y), dxy(x, y), dxy(x, y), dyy(x, y)); EigenDecompositiond decomposer(hessian); decomposer.Solve(true); aImage(x,y) = decomposer.GetEigenvalue(0); bImage(x,y) = decomposer.GetEigenvalue(1); Vector2d u = decomposer.GetEigenvector2(0); Vector2d v = decomposer.GetEigenvector2(1); pImage(x,y) = u.Dot(gradient); qImage(x,y) = v.Dot(gradient); } } aImage.Save("a.im"); bImage.Save("b.im"); pImage.Save("p.im"); qImage.Save("q.im"); // Use a cheap classification of the pixels by testing for sign changes // between neighboring pixels. ImageRGB82D result(xBound, yBound); for (y = 1; y < yBoundM1; ++y) { for (x = 1; x < xBoundM1; ++x) { unsigned char gray = (unsigned char)(255.0f*image(x, y)); double pValue = pImage(x, y); bool isRidge = false; if (pValue*pImage(x-1 ,y) < 0.0 || pValue*pImage(x+1, y) < 0.0 || pValue*pImage(x, y-1) < 0.0 || pValue*pImage(x, y+1) < 0.0) { if (aImage(x, y) < 0.0) { isRidge = true; } } double qValue = qImage(x,y); bool isValley = false; if (qValue*qImage(x-1, y) < 0.0 || qValue*qImage(x+1, y) < 0.0 || qValue*qImage(x, y-1) < 0.0 || qValue*qImage(x, y+1) < 0.0) { if (bImage(x,y) > 0.0) { isValley = true; } } if (isRidge) { if (isValley) { result(x, y) = GetColor24(gray, 0, gray); } else { result(x, y) = GetColor24(gray, 0, 0); } } else if (isValley) { result(x, y) = GetColor24(0, 0, gray); } else { result(x, y) = GetColor24(gray, gray, gray); } } } result.Save("result.im"); return 0; }