diff options
author | Erik Schnetter <schnetter@cct.lsu.edu> | 2008-06-20 16:29:06 -0500 |
---|---|---|
committer | Erik Schnetter <schnetter@cct.lsu.edu> | 2008-06-20 16:29:06 -0500 |
commit | 524d06d84dafb55891c11aa17e06a2c3fe5de04b (patch) | |
tree | aafef820f474ba6db0a512a8823016e77fab8555 /Carpet/Carpet/src/Recompose.cc | |
parent | 75fd27a919102bedabc592b8b00ff60ec0af1204 (diff) |
Introduce a tree data structure to speed up domain decomposition
Introduce a tree data structure "fulltree", which decomposes a single,
rectangular region into a tree of non-overlapping, rectangular sub-regions.
Move the processor decomposition from the regridding thorns into Carpet.
Create such trees during processor decomposition.
Store these trees with the grid hierarchy.
Diffstat (limited to 'Carpet/Carpet/src/Recompose.cc')
-rw-r--r-- | Carpet/Carpet/src/Recompose.cc | 326 |
1 files changed, 185 insertions, 141 deletions
diff --git a/Carpet/Carpet/src/Recompose.cc b/Carpet/Carpet/src/Recompose.cc index 9bd7d4066..204542f02 100644 --- a/Carpet/Carpet/src/Recompose.cc +++ b/Carpet/Carpet/src/Recompose.cc @@ -60,12 +60,14 @@ namespace Carpet { static void - SplitRegionsMaps_Automatic_Recursively (bvect const & dims, - int const nprocs, - region_t const & reg, + SplitRegionsMaps_Automatic_Recursively (bvect const & dims, + int const firstproc, + int const nprocs, + region_t & superreg, vector<region_t> & newregs); static void SplitRegions_AsSpecified (cGH const * cctkGH, + vector<region_t> & superregs, vector<region_t> & regs); @@ -124,6 +126,8 @@ namespace Carpet { { DECLARE_CCTK_PARAMETERS; + Checkpoint ("Regridding level %d...", reflevel); + assert (is_level_mode()); bool const have_regrid = CCTK_IsFunctionAliased ("Carpet_Regrid"); @@ -155,37 +159,40 @@ namespace Carpet { BEGIN_MAP_LOOP(cctkGH, CCTK_GF) { - gh::mregs regsss = vhh.at(map)->regions; + gh::rregs superregss = vhh.at(map)->superregions; + gh::mregs regsss; // Check whether to recompose CCTK_INT const do_recompose = - Carpet_Regrid (cctkGH, & regsss, force_recompose); + Carpet_Regrid (cctkGH, & superregss, & regsss, force_recompose); assert (do_recompose >= 0); did_change = did_change or do_recompose; if (do_recompose) { - RegridMap (cctkGH, map, regsss); + RegridMap (cctkGH, map, superregss, regsss); } } END_MAP_LOOP; } else { + vector<gh::rregs> superregsss (maps); vector<gh::mregs> regssss (maps); BEGIN_MAP_LOOP(cctkGH, CCTK_GF) { - regssss.at(map) = vhh.at(map)->regions; + superregsss.at(map) = vhh.at(map)->superregions; } END_MAP_LOOP; // Check whether to recompose CCTK_INT const do_recompose = - Carpet_RegridMaps (cctkGH, & regssss, force_recompose); + Carpet_RegridMaps (cctkGH, & superregsss, & regssss, force_recompose); assert (do_recompose >= 0); did_change = did_change or do_recompose; if (do_recompose) { BEGIN_MAP_LOOP(cctkGH, CCTK_GF) { + gh::rregs const & superregss = superregsss.at(map); gh::mregs const & regsss = regssss.at(map); - RegridMap (cctkGH, map, regsss); + RegridMap (cctkGH, map, superregss, regsss); } END_MAP_LOOP; } @@ -209,6 +216,7 @@ namespace Carpet { void RegridMap (cGH const * const cctkGH, int const m, + gh::rregs const & superregss, gh::mregs const & regsss) { DECLARE_CCTK_PARAMETERS; @@ -221,13 +229,15 @@ namespace Carpet { // not change // Regrid - vhh.at(m)->regrid (regsss); + vhh.at(m)->regrid (superregss, regsss); // Write grid structure to file OutputGridStructure (cctkGH, m, regsss); OutputGridCoordinates (cctkGH, m, regsss); - if (verbose) OutputGrids (cctkGH, m, * vhh.at(m), * vdd.at(m)); + if (verbose or veryverbose) { + OutputGrids (cctkGH, m, * vhh.at(m), * vdd.at(m)); + } Waypoint ("Done regridding map %d.", m); } @@ -717,18 +727,20 @@ namespace Carpet { // SplitRegions_AlongZ for grid arrays) void SplitRegions (cGH const * const cctkGH, + vector<region_t> & superregs, vector<region_t> & regs) { DECLARE_CCTK_PARAMETERS; + assert (regs.empty()); if (CCTK_EQUALS (processor_topology, "along-z")) { - SplitRegions_AlongZ (cctkGH, regs); + SplitRegions_AlongZ (cctkGH, superregs, regs); } else if (CCTK_EQUALS (processor_topology, "along-dir")) { - SplitRegions_AlongDir (cctkGH, regs, split_direction); + SplitRegions_AlongDir (cctkGH, superregs, regs, split_direction); } else if (CCTK_EQUALS (processor_topology, "automatic")) { - SplitRegions_Automatic (cctkGH, regs); + SplitRegions_Automatic (cctkGH, superregs, regs); } else if (CCTK_EQUALS (processor_topology, "manual")) { - SplitRegions_AsSpecified (cctkGH, regs); + SplitRegions_AsSpecified (cctkGH, superregs, regs); } else { assert (0); } @@ -835,29 +847,38 @@ namespace Carpet { void SplitRegions_AlongZ (cGH const * const cctkGH, + vector<region_t> & superregs, vector<region_t> & regs) { - SplitRegions_AlongDir (cctkGH, regs, dim - 1); + assert (regs.empty()); + SplitRegions_AlongDir (cctkGH, superregs, regs, dim - 1); } void SplitRegions_AlongDir (cGH const * const cctkGH, + vector<region_t> & superregs, vector<region_t> & regs, int const dir) { + assert (regs.empty()); + // Something to do? - if (regs.size() == 0) { + if (superregs.size() == 0) { return; } const int nprocs = CCTK_nProcs (cctkGH); - assert (regs.size() == 1); + assert (superregs.size() == 1); + regs = superregs; if (nprocs == 1) { regs.at(0).processor = 0; + pseudoregion_t const preg (regs.at(0).extent, regs.at(0).processor); + assert (superregs.at(0).processors == NULL); + superregs.at(0).processors = new ipfulltree (preg); return; } @@ -870,6 +891,8 @@ namespace Carpet { const b2vect obnd0 = reg0.outer_boundaries; regs.resize (nprocs); + vector<int> bounds (nprocs+1); + vector<ipfulltree *> subtrees (nprocs); for (int c=0; c<nprocs; ++c) { ivect cstr = rstr0; ivect clb = rlb0; @@ -892,7 +915,14 @@ namespace Carpet { obnd[0][dir] &= clb[dir] == rlb0[dir]; obnd[1][dir] &= cub[dir] == rub0[dir]; proc = c; + pseudoregion_t const preg (reg.extent, c); + bounds.at(c) = reg.extent.lower()[dir]; + subtrees.at(c) = new ipfulltree (preg); } + bounds.at(nprocs) = rub0[dir] + rstr0[dir]; + + assert (superregs.at(0).processors == NULL); + superregs.at(0).processors = new ipfulltree (dir, bounds, subtrees); for (int c=0; c<(int)regs.size(); ++c) { assert (regs.at(c).processor == c); @@ -903,10 +933,15 @@ namespace Carpet { void SplitRegions_Automatic (cGH const * const cctkGH, + vector<region_t> & superregs, vector<region_t> & regs) { - vector<vector<region_t> > regss (1, regs); - SplitRegionsMaps_Automatic (cctkGH, regss); + assert (regs.empty()); + vector<vector<region_t> > superregss (1, superregs); + vector<vector<region_t> > regss (1); + SplitRegionsMaps_Automatic (cctkGH, superregss, regss); + assert (superregss.size() == 1); + superregs = regss.at(0); assert (regss.size() == 1); regs = regss.at(0); } @@ -915,20 +950,23 @@ namespace Carpet { static void SplitRegions_AsSpecified (cGH const * const cctkGH, + vector<region_t> & superregs, vector<region_t> & regs) { DECLARE_CCTK_PARAMETERS; + assert (regs.empty()); + // Something to do? - if (regs.size() == 0) { + if (superregs.size() == 0) { return; } const int nprocs = CCTK_nProcs (cctkGH); - assert (regs.size() == 1); + assert (superregs.size() == 1); - region_t const & reg0 = regs.at(0); + region_t const & reg0 = superregs.at(0); const ivect rstr0 = reg0.extent.stride(); const ivect rlb0 = reg0.extent.lower(); const ivect rub0 = reg0.extent.upper() + rstr0; @@ -956,9 +994,17 @@ namespace Carpet { const ivect rem = glonp % nprocs_dir; const ivect step = locnp * cstr; assert (dim==3); + + vector<int> boundsz(nprocs_dir[2]); + vector<ipfulltree *> subtreesz(nprocs_dir[2]+1); for (int k=0; k<nprocs_dir[2]; ++k) { + vector<int> boundsy(nprocs_dir[2]); + vector<ipfulltree *> subtreesy(nprocs_dir[2]+1); for (int j=0; j<nprocs_dir[1]; ++j) { + vector<int> boundsx(nprocs_dir[2]); + vector<ipfulltree *> subtreesx(nprocs_dir[2]+1); for (int i=0; i<nprocs_dir[0]; ++i) { + const int c = i + nprocs_dir[0] * (j + nprocs_dir[1] * k); const ivect ipos (i, j, k); ivect clb = rlb0 + step * ipos; @@ -988,9 +1034,20 @@ namespace Carpet { obnd[0] &= clb == rlb0; obnd[1] &= cub == rub0; proc = c; + + pseudoregion_t preg (reg.extent, c); + subtreesx.at(i) = new ipfulltree (preg); } + boundsx.at(nprocs_dir[0]) = rub0[0] + rstr0[0]; + subtreesy.at(j) = new ipfulltree (0, boundsx, subtreesx); } + boundsy.at(nprocs_dir[1]) = rub0[1] + rstr0[1]; + subtreesz.at(k) = new ipfulltree (1, boundsy, subtreesy); } + boundsz.at(nprocs_dir[2]) = rub0[2] + rstr0[2]; + + assert (superregs.at(0).processors == NULL); + superregs.at(0).processors = new ipfulltree (2, boundsz, subtreesz); for (int c=0; c<(int)regs.size(); ++c) { assert (regs.at(c).processor == c); @@ -1003,21 +1060,26 @@ namespace Carpet { // SplitRegions_AlongZ for grid arrays) void SplitRegionsMaps (cGH const * const cctkGH, + vector<vector<region_t> > & superregss, vector<vector<region_t> > & regss) { DECLARE_CCTK_PARAMETERS; + assert (regss.size() == superregss.size()); + for (size_t m=0; m<regss.size(); ++m) { + assert (regss.AT(m).empty()); + } if (CCTK_EQUALS (processor_topology, "along-z")) { assert (0); -// SplitRegionsMaps_AlongZ (cctkGH, regss); +// SplitRegionsMaps_AlongZ (cctkGH, superregss, regss); } else if (CCTK_EQUALS (processor_topology, "along-dir")) { assert (0); -// SplitRegionsMaps_AlongDir (cctkGH, regss, split_direction); +// SplitRegionsMaps_AlongDir (cctkGH, superregss, regss, split_direction); } else if (CCTK_EQUALS (processor_topology, "automatic")) { - SplitRegionsMaps_Automatic (cctkGH, regss); + SplitRegionsMaps_Automatic (cctkGH, superregss, regss); } else if (CCTK_EQUALS (processor_topology, "manual")) { assert (0); -// SplitRegionsMaps_AsSpecified (cctkGH, regss); +// SplitRegionsMaps_AsSpecified (cctkGH, superregss, regss); } else { assert (0); } @@ -1026,9 +1088,10 @@ namespace Carpet { static void - SplitRegionsMaps_Automatic_Recursively (bvect const & dims, - int const nprocs, - region_t const & reg, + SplitRegionsMaps_Automatic_Recursively (bvect const & dims, + int const firstproc, + int const nprocs, + region_t & superreg, vector<region_t> & newregs) { if (DEBUG) cout << "SRMAR enter" << endl; @@ -1046,7 +1109,11 @@ namespace Carpet { assert (nprocs == 1); // Return argument - newregs.push_back (reg); + region_t newreg = superreg; + newreg.processor = firstproc; + newregs.push_back (newreg); + pseudoregion_t const preg (newreg.extent, newreg.processor); + superreg.processors = new ipfulltree (preg); // Check postcondition assert (newregs.size() == oldsize + nprocs); @@ -1056,19 +1123,21 @@ namespace Carpet { } // Special case - if (reg.extent.empty()) { + if (superreg.extent.empty()) { if (DEBUG) cout << "SRMAR empty" << endl; // Create a new region - region_t newreg (reg); - newreg.outer_boundaries = b2vect(false); + region_t newreg (superreg); + newreg.outer_boundaries = b2vect(false); if (DEBUG) cout << "SRMAR newreg " << newreg << endl; // Store for (int p=0; p<nprocs; ++p) { - newreg.processor = reg.processor + p; + newreg.processor = firstproc + p; newregs.push_back (newreg); } + // Do not set any superreg.processors information + // TODO: Maybe create an empty tree for this? // Check postcondition assert (newregs.size() == oldsize + nprocs); @@ -1078,10 +1147,10 @@ namespace Carpet { } // Calculate cost factors - rvect rcost = cost (reg); + rvect rcost = cost (superreg); CCTK_REAL const rfact = pow (nprocs / prod(rcost), CCTK_REAL(1)/dim); rcost *= rfact; - assert (abs (prod (rcost) - nprocs) < 1.0e-6); + assert (abs (prod (rcost) - nprocs) <= 1.0e-6); if (DEBUG) cout << "SRMA shapes " << rcost << endl; // Choose a direction @@ -1134,7 +1203,8 @@ namespace Carpet { // Split the region vector<int> mynpoints(nslices); - int const npoints = (reg.extent.shape() / reg.extent.stride())[mydim]; + int const npoints = + (superreg.extent.shape() / superreg.extent.stride())[mydim]; // Keep track of how many points and processors we have left to // distribute @@ -1155,16 +1225,18 @@ namespace Carpet { // Create the regions and recurse if (DEBUG) cout << "SRMAR " << mydim << ": create bboxes" << endl; - ivect lo = reg.extent.lower(); - ivect up = reg.extent.upper(); - ivect const str = reg.extent.stride(); - int p = reg.processor; + ivect lo = superreg.extent.lower(); + ivect up = superreg.extent.upper(); + ivect const str = superreg.extent.stride(); + int p = firstproc; + vector<int> bounds (nslices+1); + vector<ipfulltree *> subtrees (nslices); for (int n=0; n<nslices; ++n) { if (DEBUG) cout << "SRMAR " << mydim << " n " << n << endl; // Create a new region up[mydim] = lo[mydim] + (mynpoints.at(n) - 1) * str[mydim]; - b2vect newob (reg.outer_boundaries); + b2vect newob (superreg.outer_boundaries); if (n > 0) { newob[0][mydim] = false; } @@ -1172,23 +1244,33 @@ namespace Carpet { up[mydim] = lo[mydim] + (mynpoints.at(n) - 1) * str[mydim]; newob[1][mydim] = false; } - region_t newreg (reg); + region_t newreg (superreg); newreg.extent = ibbox(lo, up, str); - newreg.outer_boundaries = newob; - newreg.processor = p; + newreg.outer_boundaries = newob; if (DEBUG) cout << "SRMAR " << mydim << " newreg " << newreg << endl; // Recurse + bounds.at(n) = lo[mydim]; SplitRegionsMaps_Automatic_Recursively - (newdims, mynprocs.at(n), newreg, newregs); + (newdims, p, mynprocs.at(n), newreg, newregs); if (DEBUG) cout << "SRMAR " << mydim << " newregs " << newregs << endl; + assert (newreg.processors != NULL); + subtrees.at(n) = newreg.processors; + newreg.processors = NULL; + newreg.processor = p; + // Next slice lo[mydim] = up[mydim] + str[mydim]; p += mynprocs.at(n); } - assert (up[mydim] == reg.extent.upper()[mydim]); - assert (p == reg.processor + nprocs); + assert (up[mydim] == superreg.extent.upper()[mydim]); + assert (p == firstproc + nprocs); + bounds.at(nslices) = up[mydim] + str[mydim]; + + // Create tree + assert (superreg.processors == NULL); + superreg.processors = new ipfulltree (mydim, bounds, subtrees); // Check postcondition assert (newregs.size() == oldsize + nprocs); @@ -1200,14 +1282,15 @@ namespace Carpet { void SplitRegionsMaps_Automatic (cGH const * const cctkGH, + vector<vector<region_t> > & superregss, vector<vector<region_t> > & regss) { if (DEBUG) cout << "SRMA enter" << endl; - int const nmaps = regss.size(); + int const nmaps = superregss.size(); int nregs = 0; for (int m=0; m<nmaps; ++m) { - nregs += regss.at(m).size(); + nregs += superregss.at(m).size(); } if (DEBUG) cout << "SRMA nregs " << nregs << endl; @@ -1217,84 +1300,12 @@ namespace Carpet { } // Collect slices - vector<region_t> regs; + vector<region_t> superregs; { -#if 0 - regs.resize (nregs); - int r=0; for (int m=0; m<nmaps; ++m) { - for (int c=0; c<int(regss.at(m).size()); ++c, ++r) { - regs.at(r) = regss.at(m).at(c); - regs.at(r).map = m; - regs.at(r).processor = -1; - } + combine_regions (superregss.at(m), superregs); } - assert (r == nregs); -#endif - for (int m=0; m<nmaps; ++m) { - ibset comps; - ibset cobnds[2][dim]; - for (size_t c=0; c<regss.at(m).size(); ++c) { - region_t const & reg = regss.at(m).at(c); - comps += reg.extent; - for (int f = 0; f < 2; ++ f) { - for (int d = 0; d < dim; ++ d) { - if (reg.outer_boundaries[f][d]) { - ibbox bnd = reg.extent; - ivect lo = bnd.lower(); - ivect up = bnd.upper(); - if (f==0) { - up[d] = lo[d]; - } else { - lo[d] = up[d]; - } - bnd = ibbox (lo, up, bnd.stride()); - cobnds[f][d] += bnd; - } - } - } - } - comps.normalize(); - for (int f = 0; f < 2; ++ f) { - for (int d = 0; d < dim; ++ d) { - cobnds[f][d].normalize(); - } - } - size_t const needsize = regs.size() + comps.setsize(); - if (regs.capacity() < needsize) { - regs.reserve (1000 + 2 * needsize); - } - for (ibset::const_iterator ci = comps.begin(); ci != comps.end(); ++ ci) - { - ibbox const & c = * ci; - b2vect obnds; - for (int f = 0; f < 2; ++ f) { - for (int d = 0; d < dim; ++ d) { - obnds[f][d] = cobnds[f][d].intersects (c); - if (obnds[f][d]) { - ivect lo = c.lower(); - ivect up = c.upper(); - if (f) lo[d]=up[d]; else up[d]=lo[d]; - ibbox const cbnds (lo, up, c.stride()); - if (not ((cobnds[f][d] & ibset(c)) == ibset(cbnds))) { - cout << "cobnds[f][d] = " << cobnds[f][d] << endl - << "ibset(c) = " << ibset(c) << endl - << "(cobnds[f][d] & ibset(c)) = " << (cobnds[f][d] & ibset(c)) << endl - << "ibset(cbnds) = " << ibset(cbnds) << endl; - } - assert ((cobnds[f][d] & ibset(c)) == ibset(cbnds)); - } - } - } - region_t reg; - reg.extent = c; - reg.outer_boundaries = obnds; - reg.map = m; - reg.processor = -1; - regs.push_back (reg); - } - } // for m - nregs = regs.size(); + nregs = superregs.size(); // If the last region was removed, add a new empty region again. // A set of regions (corresponding to a refinement level or a @@ -1307,8 +1318,8 @@ namespace Carpet { reg.outer_boundaries = b2vect (bvect (true), bvect (true)); reg.map = 0; reg.processor = -1; - regs.push_back (reg); - nregs = regs.size(); + superregs.push_back (reg); + nregs = superregs.size(); } } @@ -1326,7 +1337,7 @@ namespace Carpet { if (DEBUG) cout << "SRMA: distributing processors to regions" << endl; vector<CCTK_REAL> mycosts(nregs); for (int r=0; r<nregs; ++r) { - mycosts.at(r) = prod (cost (regs.at(r))); + mycosts.at(r) = prod (cost (superregs.at(r))); } int nregs_left = newnregs; vector<int> mynprocs(nregs); @@ -1361,34 +1372,61 @@ namespace Carpet { vector<region_t> newregs; newregs.reserve (newnregs); for (int r=0, p=0; r<nregs; p+=mynprocs.at(r), ++r) { - regs.at(r).processor = p; - if (DEBUG) cout << "SRMA reg[" << r << "] " << regs.at(r) << endl; + if (DEBUG) cout << "SRMA superreg[" << r << "] " << superregs.at(r) << endl; bvect const dims = false; SplitRegionsMaps_Automatic_Recursively - (dims, mynprocs.at(r), regs.at(r), newregs); + (dims, p, mynprocs.at(r), superregs.at(r), newregs); } // for r if (DEBUG) cout << "SRMA newregs " << newregs << endl; assert (int(newregs.size()) == newnregs); + // Count components per map + vector<int> myncomps(nmaps, 0); + for (int r=0; r<newnregs; ++r) { + int const m = newregs.at(r).map; + assert (m>=0 and m<nmaps); + ++ myncomps.at(m); + } + vector<int> mynregs(nmaps, 0); + for (int r=0; r<nregs; ++r) { + int const m = superregs.at(r).map; + assert (m>=0 and m<nmaps); + ++ mynregs.at(m); + } + // Convert virtual to real processors for (int r=0; r<newnregs; ++r) { newregs.at(r).processor /= ncomps; assert (newregs.at(r).processor >= 0 and newregs.at(r).processor < nprocs); } + { + vector<int> tmpncomps(nmaps, 0); + for (int r=0; r<nregs; ++r) { + int const m = superregs.at(r).map; + ipfulltree * const regf = superregs.at(r).processors; + assert (regf != NULL); + for (ipfulltree::iterator + fti = regf->begin(); fti != regf->end(); ++ fti) + { + pseudoregion_t & preg = (* fti).payload(); + preg.component = tmpncomps.at(m)++; + // preg.processor /= ncomps; + } + } + for (int m=0; m<nmaps; ++m) { + assert (tmpncomps.at(m) == myncomps.at(m)); + } + } // Distribute regions - // Count components per map - vector<int> myncomps(nmaps); - for (int r=0; r<newnregs; ++r) { - int const m = newregs.at(r).map; - assert (m>=0 and m<nmaps); - ++ myncomps.at(m); - } // Allocate regions + assert ((int)regss.size() == nmaps); for (int m=0; m<nmaps; ++m) { - regss.at(m).resize (0); + assert (regss.at(m).empty()); regss.at(m).reserve (myncomps.at(m)); + superregss.at(m).clear(); + superregss.at(m).reserve (mynregs.at(m)); } // Assign regions for (int r=0; r<newnregs; ++r) { @@ -1396,9 +1434,15 @@ namespace Carpet { assert (m>=0 and m<nmaps); regss.at(m).push_back (newregs.at(r)); } + for (int r=0; r<nregs; ++r) { + int const m = superregs.at(r).map; + assert (m>=0 and m<nmaps); + superregss.at(m).push_back (superregs.at(r)); + } // Check sizes for (int m=0; m<nmaps; ++m) { assert (int(regss.at(m).size()) == myncomps.at(m)); + assert (int(superregss.at(m).size()) == mynregs.at(m)); } if (DEBUG) cout << "SRMA exit" << endl; @@ -1477,7 +1521,7 @@ namespace Carpet { void MakeMultigridBoxes (cGH const * const cctkGH, int const m, - vector<vector<region_t> > const & regss, + vector<vector<region_t> > const & regss, vector<vector<vector<region_t> > > & regsss) { regsss.resize (mglevels); |