From c1ee5f93752b6627f168c1cf87496207ad2adff0 Mon Sep 17 00:00:00 2001 From: Berk Hess Date: Wed, 25 Sep 2019 11:42:29 +0200 Subject: [PATCH] Use gmx::Range in domdec Renamed gmx_domdec_ns_ranges_t to DDPairInteractionRanges and made it use gmx::Range. This is now used in an std::vector in gmx_domdec_zones_t. Note: more refactoring should be done in gmx_domdec_zones_t. Change-Id: Iff61096ee8ce1e45a998a905fd56e0c2f43fa319 --- src/gromacs/domdec/domdec.cpp | 43 ++++++++++---------- src/gromacs/domdec/domdec_struct.h | 52 +++++++++++++------------ src/gromacs/domdec/domdec_topology.cpp | 41 +++++++++---------- src/gromacs/domdec/partition.cpp | 54 ++++++++++++++------------ src/gromacs/nbnxm/pairlist.cpp | 24 +++++------- 5 files changed, 108 insertions(+), 106 deletions(-) diff --git a/src/gromacs/domdec/domdec.cpp b/src/gromacs/domdec/domdec.cpp index f3365e11a3..84e3b898eb 100644 --- a/src/gromacs/domdec/domdec.cpp +++ b/src/gromacs/domdec/domdec.cpp @@ -1233,10 +1233,9 @@ static void make_load_communicators(gmx_domdec_t gmx_unused *dd) /*! \brief Sets up the relation between neighboring domains and zones */ static void setup_neighbor_relations(gmx_domdec_t *dd) { - int d, dim, i, j, m; + int d, dim, m; ivec tmp, s; gmx_domdec_zones_t *zones; - gmx_domdec_ns_ranges_t *izone; GMX_ASSERT((dd->ndim >= 0) && (dd->ndim <= DIM), "Must have valid number of dimensions for DD"); for (d = 0; d < dd->ndim; d++) @@ -1263,7 +1262,7 @@ static void setup_neighbor_relations(gmx_domdec_t *dd) zones = &dd->comm->zones; - for (i = 0; i < nzone; i++) + for (int i = 0; i < nzone; i++) { m = 0; clear_ivec(zones->shift[i]); @@ -1274,7 +1273,7 @@ static void setup_neighbor_relations(gmx_domdec_t *dd) } zones->n = nzone; - for (i = 0; i < nzone; i++) + for (int i = 0; i < nzone; i++) { for (d = 0; d < DIM; d++) { @@ -1289,44 +1288,48 @@ static void setup_neighbor_relations(gmx_domdec_t *dd) } } } - zones->nizone = nizone; - for (i = 0; i < zones->nizone; i++) + for (int iZoneIndex = 0; iZoneIndex < nizone; iZoneIndex++) { - assert(ddNonbondedZonePairRanges[i][0] == i); + GMX_RELEASE_ASSERT(ddNonbondedZonePairRanges[iZoneIndex][0] == iZoneIndex, + "The first element for each ddNonbondedZonePairRanges should match its index"); - izone = &zones->izone[i]; + DDPairInteractionRanges iZone; + iZone.iZoneIndex = iZoneIndex; /* dd_zp3 is for 3D decomposition, for fewer dimensions use only * j-zones up to nzone. */ - izone->j0 = std::min(ddNonbondedZonePairRanges[i][1], nzone); - izone->j1 = std::min(ddNonbondedZonePairRanges[i][2], nzone); + iZone.jZoneRange = + gmx::Range(std::min(ddNonbondedZonePairRanges[iZoneIndex][1], nzone), + std::min(ddNonbondedZonePairRanges[iZoneIndex][2], nzone)); for (dim = 0; dim < DIM; dim++) { if (dd->nc[dim] == 1) { /* All shifts should be allowed */ - izone->shift0[dim] = -1; - izone->shift1[dim] = 1; + iZone.shift0[dim] = -1; + iZone.shift1[dim] = 1; } else { /* Determine the min/max j-zone shift wrt the i-zone */ - izone->shift0[dim] = 1; - izone->shift1[dim] = -1; - for (j = izone->j0; j < izone->j1; j++) + iZone.shift0[dim] = 1; + iZone.shift1[dim] = -1; + for (int jZone : iZone.jZoneRange) { - int shift_diff = zones->shift[j][dim] - zones->shift[i][dim]; - if (shift_diff < izone->shift0[dim]) + int shift_diff = zones->shift[jZone][dim] - zones->shift[iZoneIndex][dim]; + if (shift_diff < iZone.shift0[dim]) { - izone->shift0[dim] = shift_diff; + iZone.shift0[dim] = shift_diff; } - if (shift_diff > izone->shift1[dim]) + if (shift_diff > iZone.shift1[dim]) { - izone->shift1[dim] = shift_diff; + iZone.shift1[dim] = shift_diff; } } } } + + zones->iZones.push_back(iZone); } if (!isDlbDisabled(dd->comm)) diff --git a/src/gromacs/domdec/domdec_struct.h b/src/gromacs/domdec/domdec_struct.h index c80e6687df..c2be7bc66e 100644 --- a/src/gromacs/domdec/domdec_struct.h +++ b/src/gromacs/domdec/domdec_struct.h @@ -47,6 +47,7 @@ #include +#include #include #include @@ -54,6 +55,7 @@ #include "gromacs/topology/block.h" #include "gromacs/utility/basedefinitions.h" #include "gromacs/utility/gmxmpi.h" +#include "gromacs/utility/range.h" #include "gromacs/utility/real.h" //! Max number of zones in domain decomposition @@ -77,22 +79,24 @@ class LocalAtomSetManager; class GpuHaloExchange; } -typedef struct { - /* j-zone start */ - int j0 = 0; - /* j-zone end */ - int j1 = 0; - /* i-charge-group end */ - int cg1 = 0; - /* j-charge-group start */ - int jcg0 = 0; - /* j-charge-group end */ - int jcg1 = 0; - /* Minimum shifts to consider */ - ivec shift0 = { }; - /* Maximum shifts to consider */ - ivec shift1 = { }; -} gmx_domdec_ns_ranges_t; +/*! \internal + * \brief Pair interaction zone and atom range for an i-zone + */ +struct DDPairInteractionRanges +{ + //! The index of this i-zone in the i-zone list + int iZoneIndex = -1; + //! The range of j-zones + gmx::Range jZoneRange; + //! The i-atom range + gmx::Range iAtomRange; + //! The j-atom range + gmx::Range jAtomRange; + //! Minimum shifts to consider + ivec shift0 = { }; + //! Maximum shifts to consider + ivec shift1 = { }; +}; typedef struct { /* Zone lower corner in triclinic coordinates */ @@ -107,19 +111,17 @@ typedef struct { struct gmx_domdec_zones_t { /* The number of zones including the home zone */ - int n = 0; + int n = 0; /* The shift of the zones with respect to the home zone */ - ivec shift[DD_MAXZONE] = { }; + ivec shift[DD_MAXZONE] = { }; /* The charge group boundaries for the zones */ - int cg_range[DD_MAXZONE+1] = { }; - /* The number of neighbor search zones with i-particles */ - int nizone = 0; - /* The neighbor search charge group ranges for each i-zone */ - gmx_domdec_ns_ranges_t izone[DD_MAXIZONE]; + int cg_range[DD_MAXZONE+1] = { }; + /* The pair interaction zone and atom ranges per each i-zone */ + std::vector iZones; /* Boundaries of the zones */ - gmx_domdec_zone_size_t size[DD_MAXZONE]; + gmx_domdec_zone_size_t size[DD_MAXZONE]; /* The cg density of the home zone */ - real dens_zone0 = 0; + real dens_zone0 = 0; }; struct gmx_ddbox_t { diff --git a/src/gromacs/domdec/domdec_topology.cpp b/src/gromacs/domdec/domdec_topology.cpp index d27b2033c8..3df773af05 100644 --- a/src/gromacs/domdec/domdec_topology.cpp +++ b/src/gromacs/domdec/domdec_topology.cpp @@ -1126,9 +1126,9 @@ check_assign_interactions_atom(int i, int i_gl, gmx_bool bBCheck, int *nbonded_local) { - int j; + gmx::ArrayRef iZones = zones->iZones; - j = ind_start; + int j = ind_start; while (j < ind_end) { t_iatom tiatoms[1 + MAXATOMLIST]; @@ -1203,14 +1203,12 @@ check_assign_interactions_atom(int i, int i_gl, kz -= zones->n; } /* Check zone interaction assignments */ - bUse = ((iz < zones->nizone && + bUse = ((iz < iZones.ssize() && iz <= kz && - kz >= zones->izone[iz].j0 && - kz < zones->izone[iz].j1) || - (kz < zones->nizone && + iZones[iz].jZoneRange.isInRange(kz)) || + (kz < iZones.ssize() && iz > kz && - iz >= zones->izone[kz].j0 && - iz < zones->izone[kz].j1)); + iZones[kz].jZoneRange.isInRange(iz))); if (bUse) { GMX_ASSERT(ftype != F_CONSTR || (iz == 0 && kz == 0), @@ -1425,9 +1423,7 @@ static void make_exclusions_zone(gmx_domdec_t *dd, gmx_domdec_zones_t *zones, const gmx_ga2la_t &ga2la = *dd->ga2la; - /* Extract the j-atom range */ - const gmx::Range jRange(zones->izone[iz].jcg0, - zones->izone[iz].jcg1); + const auto &jAtomRange = zones->iZones[iz].jAtomRange; n_excl_at_max = dd->reverse_top->n_excl_at_max; @@ -1470,7 +1466,7 @@ static void make_exclusions_zone(gmx_domdec_t *dd, gmx_domdec_zones_t *zones, * the number of exclusions in the list, which in turn * can speed up the pair list construction a bit. */ - if (jRange.isInRange(jEntry->la)) + if (jAtomRange.isInRange(jEntry->la)) { lexcls->a[n++] = jEntry->la; } @@ -1523,10 +1519,11 @@ static void check_alloc_index(t_blocka *ba, int nindex_max) } /*! \brief Ensure that we have enough space for exclusion storate in \p lexcls */ -static void check_exclusions_alloc(gmx_domdec_t *dd, gmx_domdec_zones_t *zones, - t_blocka *lexcls) +static void check_exclusions_alloc(const gmx_domdec_t *dd, + const gmx_domdec_zones_t *zones, + t_blocka *lexcls) { - const int nr = zones->izone[zones->nizone - 1].cg1; + const int nr = zones->iZones.back().iAtomRange.end(); check_alloc_index(lexcls, nr); @@ -1540,8 +1537,8 @@ static void check_exclusions_alloc(gmx_domdec_t *dd, gmx_domdec_zones_t *zones, static void finish_local_exclusions(gmx_domdec_t *dd, gmx_domdec_zones_t *zones, t_blocka *lexcls) { - const gmx::Range nonhomeIzonesAtomRange(zones->izone[0].cg1, - zones->izone[zones->nizone - 1].cg1); + const gmx::Range nonhomeIzonesAtomRange(zones->iZones[0].iAtomRange.end(), + zones->iZones.back().iAtomRange.end()); if (!dd->haveExclusions) { @@ -1588,7 +1585,7 @@ static int make_local_bondeds_excls(gmx_domdec_t *dd, t_blocka *lexcls, int *excl_count) { int nzone_bondeds, nzone_excl; - int izone, cg0, cg1; + int cg0, cg1; real rc2; int nbonded_local; gmx_reverse_top_t *rt; @@ -1608,7 +1605,7 @@ static int make_local_bondeds_excls(gmx_domdec_t *dd, if (dd->haveExclusions) { /* We only use exclusions from i-zones to i- and j-zones */ - nzone_excl = zones->nizone; + nzone_excl = zones->iZones.size(); } else { @@ -1630,7 +1627,7 @@ static int make_local_bondeds_excls(gmx_domdec_t *dd, lexcls->nra = 0; *excl_count = 0; - for (izone = 0; izone < nzone_bondeds; izone++) + for (int izone = 0; izone < nzone_bondeds; izone++) { cg0 = zones->cg_range[izone]; cg1 = zones->cg_range[izone + 1]; @@ -1717,9 +1714,9 @@ static int make_local_bondeds_excls(gmx_domdec_t *dd, /* Some zones might not have exclusions, but some code still needs to * loop over the index, so we set the indices here. */ - for (izone = nzone_excl; izone < zones->nizone; izone++) + for (size_t iZone = nzone_excl; iZone < zones->iZones.size(); iZone++) { - set_no_exclusions_zone(zones, izone, lexcls); + set_no_exclusions_zone(zones, iZone, lexcls); } finish_local_exclusions(dd, zones, lexcls); diff --git a/src/gromacs/domdec/partition.cpp b/src/gromacs/domdec/partition.cpp index f076b2e2a2..918f57c915 100644 --- a/src/gromacs/domdec/partition.cpp +++ b/src/gromacs/domdec/partition.cpp @@ -1460,7 +1460,6 @@ set_dd_corners(const gmx_domdec_t *dd, { const gmx_domdec_comm_t *comm; const gmx_domdec_zones_t *zones; - int i, j; comm = dd->comm; @@ -1498,22 +1497,23 @@ set_dd_corners(const gmx_domdec_t *dd, if (dd->ndim >= 3) { dim2 = dd->dim[2]; - for (j = 0; j < 4; j++) + for (int j = 0; j < 4; j++) { c->c[2][j] = comm->cell_x0[dim2]; } if (isDlbOn(dd->comm)) { /* Use the maximum of the i-cells that see a j-cell */ - for (i = 0; i < zones->nizone; i++) + for (const auto &iZone : zones->iZones) { - for (j = zones->izone[i].j0; j < zones->izone[i].j1; j++) + const int iZoneIndex = iZone.iZoneIndex; + for (int jZone : iZone.jZoneRange) { - if (j >= 4) + if (jZone >= 4) { - c->c[2][j-4] = - std::max(c->c[2][j-4], - comm->zone_d2[zones->shift[i][dim0]][zones->shift[i][dim1]].mch0); + c->c[2][jZone - 4] = + std::max(c->c[2][jZone - 4], + comm->zone_d2[zones->shift[iZoneIndex][dim0]][zones->shift[iZoneIndex][dim1]].mch0); } } } @@ -1521,9 +1521,9 @@ set_dd_corners(const gmx_domdec_t *dd, { /* For the multi-body distance we need the maximum */ c->bc[2] = comm->cell_x0[dim2]; - for (i = 0; i < 2; i++) + for (int i = 0; i < 2; i++) { - for (j = 0; j < 2; j++) + for (int j = 0; j < 2; j++) { c->bc[2] = std::max(c->bc[2], comm->zone_d2[i][j].p1_0); } @@ -2187,13 +2187,12 @@ static void setup_dd_communication(gmx_domdec_t *dd, //! Set boundaries for the charge group range. static void set_cg_boundaries(gmx_domdec_zones_t *zones) { - int c; - - for (c = 0; c < zones->nizone; c++) + for (auto &iZone : zones->iZones) { - zones->izone[c].cg1 = zones->cg_range[c+1]; - zones->izone[c].jcg0 = zones->cg_range[zones->izone[c].j0]; - zones->izone[c].jcg1 = zones->cg_range[zones->izone[c].j1]; + iZone.iAtomRange = gmx::Range(0, zones->cg_range[iZone.iZoneIndex + 1]); + iZone.jAtomRange = + gmx::Range(zones->cg_range[iZone.jZoneRange.begin()], + zones->cg_range[iZone.jZoneRange.end()]); } } @@ -2221,7 +2220,7 @@ static void set_zones_size(gmx_domdec_t *dd, gmx_domdec_comm_t *comm; gmx_domdec_zones_t *zones; gmx_bool bDistMB; - int z, zi, d, dim; + int z, d, dim; real rcs, rcmbs; int i, j; real vol; @@ -2315,7 +2314,7 @@ static void set_zones_size(gmx_domdec_t *dd, if (bDistMB) { - for (zi = 0; zi < zones->nizone; zi++) + for (size_t zi = 0; zi < zones->iZones.size(); zi++) { if (zones->shift[zi][dim] == 0) { @@ -2335,18 +2334,25 @@ static void set_zones_size(gmx_domdec_t *dd, /* Loop over the i-zones to set the upper limit of each * j-zone they see. */ - for (zi = 0; zi < zones->nizone; zi++) + for (const auto &iZone : zones->iZones) { + const int zi = iZone.iZoneIndex; if (zones->shift[zi][dim] == 0) { /* We should only use zones up to zone_end */ - int jZoneEnd = std::min(zones->izone[zi].j1, zone_end); - for (z = zones->izone[zi].j0; z < jZoneEnd; z++) + const auto &jZoneRangeFull = iZone.jZoneRange; + if (zone_end <= *jZoneRangeFull.begin()) + { + continue; + } + const gmx::Range jZoneRange(*jZoneRangeFull.begin(), + std::min(*jZoneRangeFull.end(), zone_end)); + for (int jZone : jZoneRange) { - if (zones->shift[z][dim] > 0) + if (zones->shift[jZone][dim] > 0) { - zones->size[z].x1[dim] = std::max(zones->size[z].x1[dim], - zones->size[zi].x1[dim]+rcs); + zones->size[jZone].x1[dim] = std::max(zones->size[jZone].x1[dim], + zones->size[zi].x1[dim]+rcs); } } } diff --git a/src/gromacs/nbnxm/pairlist.cpp b/src/gromacs/nbnxm/pairlist.cpp index 9474185f07..ff60f43398 100644 --- a/src/gromacs/nbnxm/pairlist.cpp +++ b/src/gromacs/nbnxm/pairlist.cpp @@ -4005,7 +4005,7 @@ PairlistSet::constructPairlists(const Nbnxm::GridSet &gridSet, } else { - nzi = gridSet.domainSetup().zones->nizone; + nzi = gridSet.domainSetup().zones->iZones.size(); } if (!isCpuType_ && minimumIlistCountForGpuBalancing > 0) @@ -4048,29 +4048,23 @@ PairlistSet::constructPairlists(const Nbnxm::GridSet &gridSet, } const Grid &iGrid = gridSet.grids()[zi]; - int zj0; - int zj1; + Range jZoneRange; if (locality_ == InteractionLocality::Local) { - zj0 = 0; - zj1 = 1; + jZoneRange = Range(0, 1); } else { - zj0 = ddZones->izone[zi].j0; - zj1 = ddZones->izone[zi].j1; - if (zi == 0) - { - zj0++; - } + jZoneRange = Range(ddZones->iZones[zi].jZoneRange.begin() + (zi == 0 ? 1 : 0), + ddZones->iZones[zi].jZoneRange.end()); } - for (int zj = zj0; zj < zj1; zj++) + for (int jZone : jZoneRange) { - const Grid &jGrid = gridSet.grids()[zj]; + const Grid &jGrid = gridSet.grids()[jZone]; if (debug) { - fprintf(debug, "ns search grid %d vs %d\n", zi, zj); + fprintf(debug, "ns search grid %d vs %d\n", zi, jZone); } searchCycleCounting->start(enbsCCsearch); @@ -4090,7 +4084,7 @@ PairlistSet::constructPairlists(const Nbnxm::GridSet &gridSet, /* Re-init the thread-local work flag data before making * the first list (not an elegant conditional). */ - if (nbat->bUseBufferFlags && ((zi == 0 && zj == 0))) + if (nbat->bUseBufferFlags && (zi == 0 && jZone == 0)) { init_buffer_flags(&searchWork[th].buffer_flags, nbat->numAtoms()); } -- 2.22.0