};
enum {
- edlbAUTO, edlbNO, edlbYES, edlbNR
+ edlbsOffForever, /* DLB is off and will never be turned on */
+ edlbsOffCanTurnOn, /* DLB is off and will turn on with imbalance */
+ edlbsOffTemporarilyLocked, /* DLB is off and temporarily can not turn on */
+ edlbsOn, /* DLB is on and will stay on forever */
+ edlbsNR
};
-const char *edlb_names[edlbNR] = { "auto", "no", "yes" };
+/* Allowed DLB state transitions:
+ * edlbsOffCanTurnOn -> edlbsOn
+ * edlbsOffCanTurnOn -> edlbsOffForever
+ * edlbsOffCanTurnOn -> edlbsOffTemporarilyLocked
+ * edlbsOffTemporarilyLocked -> edlbsOffCanTurnOn
+ */
+
+const char *edlbs_names[edlbsNR] = { "off", "auto", "locked", "on" };
typedef struct
{
t_blocka *cglink;
char *bLocalCG;
- /* The DLB option */
- int eDLB;
- /* Is eDLB=edlbAUTO locked such that we currently can't turn it on? */
- gmx_bool bDLB_locked;
- /* With eDLB=edlbAUTO, should we check if to DLB on at the next DD? */
+ /* The DLB state, possible values are defined above */
+ int dlbState;
+ /* With dlbState=edlbsOffCanTurnOn, should we check if to DLB on at the next DD? */
gmx_bool bCheckWhetherToTurnDlbOn;
- /* Are we actually using DLB? */
- gmx_bool bDynLoadBal;
/* Cell sizes for static load balancing, first index cartesian */
real **slb_frac;
return &dd->comm->cgs_gl;
}
+static bool dlbIsOn(const gmx_domdec_comm_t *comm)
+{
+ return (comm->dlbState == edlbsOn);
+}
+
static void vec_rvec_init(vec_rvec_t *v)
{
v->nalloc = 0;
dim = dd->dim[d];
shift0[dim] = zones->izone[izone].shift0[dim];
shift1[dim] = zones->izone[izone].shift1[dim];
- if (dd->comm->tric_dir[dim] || (dd->bGridJump && d > 0))
+ if (dd->comm->tric_dir[dim] || (dlbIsOn(dd->comm) && d > 0))
{
/* A conservative approach, this can be optimized */
shift0[dim] -= 1;
}
}
- if (!comm->bDynLoadBal)
+ if (!dlbIsOn(comm))
{
copy_rvec(cellsize_min, comm->cellsize_min);
}
copy_rvec(comm->cell_x0, comm->old_cell_x0);
copy_rvec(comm->cell_x1, comm->old_cell_x1);
- if (comm->bDynLoadBal)
+ if (dlbIsOn(comm))
{
if (DDMASTER(dd))
{
/* Without PBC we don't have restrictions on the outer cells */
if (!(dim >= ddbox->npbcdim &&
(dd->ci[dim] == 0 || dd->ci[dim] == dd->nc[dim] - 1)) &&
- comm->bDynLoadBal &&
+ dlbIsOn(comm) &&
(comm->cell_x1[dim] - comm->cell_x0[dim])*ddbox->skew_fac[dim] <
comm->cellsize_min[dim])
{
}
}
- if ((dd->bGridJump && dd->ndim > 1) || ddbox->nboundeddim < DIM)
+ if ((dlbIsOn(dd->comm) && dd->ndim > 1) || ddbox->nboundeddim < DIM)
{
/* Communicate the boundaries and update cell_ns_x0/1 */
dd_move_cellx(dd, ddbox, cell_ns_x0, cell_ns_x1);
- if (dd->bGridJump && dd->ndim > 1)
+ if (dlbIsOn(dd->comm) && dd->ndim > 1)
{
check_grid_jump(step, dd, dd->comm->cutoff, ddbox, TRUE);
}
/* Check which direction this cg should go */
for (d2 = d+1; (d2 < dd->ndim && mc == -1); d2++)
{
- if (dd->bGridJump)
+ if (dlbIsOn(dd->comm))
{
/* The cell boundaries for dimension d2 are not equal
* for each cell row of the lower dimension(s),
(dd->ci[dd->dim[d+1]] == 0 && dd->ci[dd->dim[dd->ndim-1]] == 0))
{
load = &comm->load[d];
- if (dd->bGridJump)
+ if (dlbIsOn(dd->comm))
{
cell_frac = comm->cell_f1[d] - comm->cell_f0[d];
}
{
sbuf[pos++] = dd_force_load(comm);
sbuf[pos++] = sbuf[0];
- if (dd->bGridJump)
+ if (dlbIsOn(dd->comm))
{
sbuf[pos++] = sbuf[0];
sbuf[pos++] = cell_frac;
{
sbuf[pos++] = comm->load[d+1].sum;
sbuf[pos++] = comm->load[d+1].max;
- if (dd->bGridJump)
+ if (dlbIsOn(dd->comm))
{
sbuf[pos++] = comm->load[d+1].sum_m;
sbuf[pos++] = comm->load[d+1].cvol_min*cell_frac;
if (dd->ci[dim] == dd->master_ci[dim])
{
/* We are the root, process this row */
- if (comm->bDynLoadBal)
+ if (dlbIsOn(comm))
{
root = comm->root[d];
}
load->sum += load->load[pos++];
load->max = std::max(load->max, load->load[pos]);
pos++;
- if (dd->bGridJump)
+ if (dlbIsOn(dd->comm))
{
if (root->bLimited)
{
pos++;
}
}
- if (comm->bDynLoadBal && root->bLimited)
+ if (dlbIsOn(comm) && root->bLimited)
{
load->sum_m *= dd->nc[dim];
load->flags |= (1<<d);
comm->load_step += comm->cycl[ddCyclStep];
comm->load_sum += comm->load[0].sum;
comm->load_max += comm->load[0].max;
- if (comm->bDynLoadBal)
+ if (dlbIsOn(comm))
{
for (d = 0; d < dd->ndim; d++)
{
fprintf(stderr, "%s", buf);
}
bLim = FALSE;
- if (comm->bDynLoadBal)
+ if (dlbIsOn(comm))
{
sprintf(buf, " Steps where the load balancing was limited by -rdd, -rcon and/or -dds:");
for (d = 0; d < dd->ndim; d++)
sprintf(buf,
"NOTE: %.1f %% of the available CPU time was lost due to load imbalance\n"
" in the domain decomposition.\n", lossf*100);
- if (!comm->bDynLoadBal)
+ if (!dlbIsOn(comm))
{
sprintf(buf+strlen(buf), " You might want to use dynamic load balancing (option -dlb.)\n");
}
fprintf(fplog, "\n");
}
fprintf(fplog, "DD step %s", gmx_step_str(step, buf));
- if (dd->comm->bDynLoadBal)
+ if (dlbIsOn(dd->comm))
{
fprintf(fplog, " vol min/aver %5.3f%c",
dd_vol_min(dd), flags ? '!' : ' ');
static void dd_print_load_verbose(gmx_domdec_t *dd)
{
- if (dd->comm->bDynLoadBal)
+ if (dlbIsOn(dd->comm))
{
fprintf(stderr, "vol %4.2f%c ",
dd_vol_min(dd), dd_load_flags(dd) ? '!' : ' ');
if (bPartOfGroup)
{
dd->comm->mpi_comm_load[dim_ind] = c_row;
- if (dd->comm->eDLB != edlbNO)
+ if (dd->comm->dlbState != edlbsOffForever)
{
if (dd->ci[dim] == dd->master_ci[dim])
{
}
}
- if (dd->comm->eDLB != edlbNO)
+ if (dd->comm->dlbState != edlbsOffForever)
{
snew(dd->comm->root, dd->ndim);
}
const char *dlb_opt, gmx_bool bRecordLoad,
unsigned long Flags, t_inputrec *ir)
{
- int eDLB = -1;
+ int dlbState = -1;
char buf[STRLEN];
switch (dlb_opt[0])
{
- case 'a': eDLB = edlbAUTO; break;
- case 'n': eDLB = edlbNO; break;
- case 'y': eDLB = edlbYES; break;
+ case 'a': dlbState = edlbsOffCanTurnOn; break;
+ case 'n': dlbState = edlbsOffForever; break;
+ case 'y': dlbState = edlbsOn; break;
default: gmx_incons("Unknown dlb_opt");
}
if (Flags & MD_RERUN)
{
- return edlbNO;
+ return edlbsOffForever;
}
if (!EI_DYNAMICS(ir->eI))
{
- if (eDLB == edlbYES)
+ if (dlbState == edlbsOn)
{
sprintf(buf, "NOTE: dynamic load balancing is only supported with dynamics, not with integrator '%s'\n", EI(ir->eI));
dd_warning(cr, fplog, buf);
}
- return edlbNO;
+ return edlbsOffForever;
}
if (!bRecordLoad)
{
dd_warning(cr, fplog, "NOTE: Cycle counting is not supported on this architecture, will not use dynamic load balancing\n");
- return edlbNO;
+ return edlbsOffForever;
}
if (Flags & MD_REPRODUCIBLE)
{
- switch (eDLB)
+ switch (dlbState)
{
- case edlbNO:
+ case edlbsOffForever:
break;
- case edlbAUTO:
+ case edlbsOffCanTurnOn:
dd_warning(cr, fplog, "NOTE: reproducibility requested, will not use dynamic load balancing\n");
- eDLB = edlbNO;
+ dlbState = edlbsOffForever;
break;
- case edlbYES:
+ case edlbsOn:
dd_warning(cr, fplog, "WARNING: reproducibility requested with dynamic load balancing, the simulation will NOT be binary reproducible\n");
break;
default:
- gmx_fatal(FARGS, "Death horror: undefined case (%d) for load balancing choice", eDLB);
+ gmx_fatal(FARGS, "Death horror: undefined case (%d) for load balancing choice", dlbState);
break;
}
}
- return eDLB;
+ return dlbState;
}
static void set_dd_dim(FILE *fplog, gmx_domdec_t *dd)
/* Initialize to GPU share count to 0, might change later */
comm->nrank_gpu_shared = 0;
- comm->eDLB = check_dlb_support(fplog, cr, dlb_opt, comm->bRecordLoad, Flags, ir);
- comm->bDLB_locked = FALSE;
+ comm->dlbState = check_dlb_support(fplog, cr, dlb_opt, comm->bRecordLoad, Flags, ir);
comm->bCheckWhetherToTurnDlbOn = TRUE;
- comm->bDynLoadBal = (comm->eDLB == edlbYES);
if (fplog)
{
- fprintf(fplog, "Dynamic load balancing: %s\n", edlb_names[comm->eDLB]);
+ fprintf(fplog, "Dynamic load balancing: %s\n",
+ edlbs_names[comm->dlbState]);
}
- dd->bGridJump = comm->bDynLoadBal;
comm->bPMELoadBalDLBLimits = FALSE;
if (comm->nstSortCG)
/* We need to choose the optimal DD grid and possibly PME nodes */
limit = dd_choose_grid(fplog, cr, dd, ir, mtop, box, ddbox,
- comm->eDLB != edlbNO, dlb_scale,
+ comm->dlbState != edlbsOffForever, dlb_scale,
comm->cellsize_limit, comm->cutoff,
comm->bInterCGBondeds);
bC = (dd->bInterCGcons && rconstr > r_bonded_limit);
sprintf(buf, "Change the number of ranks or mdrun option %s%s%s",
!bC ? "-rdd" : "-rcon",
- comm->eDLB != edlbNO ? " or -dds" : "",
+ comm->dlbState != edlbsOffForever ? " or -dds" : "",
bC ? " or your LINCS settings" : "");
gmx_fatal_collective(FARGS, cr, NULL,
*npme_y = comm->npmenodes_y;
snew(comm->slb_frac, DIM);
- if (comm->eDLB == edlbNO)
+ if (comm->dlbState == edlbsOffForever)
{
comm->slb_frac[XX] = get_slb_frac(fplog, "x", dd->nc[XX], sizex);
comm->slb_frac[YY] = get_slb_frac(fplog, "y", dd->nc[YY], sizey);
if (comm->bInterCGBondeds && comm->cutoff_mbody == 0)
{
- if (comm->bBondComm || comm->eDLB != edlbNO)
+ if (comm->bBondComm || comm->dlbState != edlbsOffForever)
{
/* Set the bonded communication distance to halfway
* the minimum and the maximum,
*/
acs = average_cellsize_min(dd, ddbox);
comm->cutoff_mbody = 0.5*(r_bonded + acs);
- if (comm->eDLB != edlbNO)
+ if (comm->dlbState != edlbsOffForever)
{
/* Check if this does not limit the scaling */
comm->cutoff_mbody = std::min(comm->cutoff_mbody, dlb_scale*acs);
dd_warning(cr, fplog, "NOTE: the minimum cell size is smaller than 1.05 times the cell size limit, will not turn on dynamic load balancing\n");
/* Change DLB from "auto" to "no". */
- comm->eDLB = edlbNO;
+ comm->dlbState = edlbsOffForever;
return;
}
dd_warning(cr, fplog, "NOTE: Turning on dynamic load balancing\n");
- comm->bDynLoadBal = TRUE;
- dd->bGridJump = TRUE;
+ comm->dlbState = edlbsOn;
set_dlb_limits(dd);
std::max(comm->cutoff, comm->cutoff_mbody));
fprintf(fplog, "%40s %-7s %6.3f nm\n",
"multi-body bonded interactions", "(-rdd)",
- (comm->bBondComm || dd->bGridJump) ? comm->cutoff_mbody : std::min(comm->cutoff, limit));
+ (comm->bBondComm || dlbIsOn(dd->comm)) ? comm->cutoff_mbody : std::min(comm->cutoff, limit));
}
if (dd->vsite_comm)
{
{
comm->cutoff_mbody = std::min(comm->cutoff, comm->cellsize_limit);
}
- if (comm->bDynLoadBal)
+ if (dlbIsOn(comm))
{
set_dlb_limits(dd);
}
{
fprintf(debug, "The DD cut-off is %f\n", comm->cutoff);
}
- if (comm->eDLB != edlbNO)
+ if (comm->dlbState != edlbsOffForever)
{
set_cell_limits_dlb(dd, dlb_scale, ir, ddbox);
}
- print_dd_settings(fplog, dd, ir, comm->bDynLoadBal, dlb_scale, ddbox);
- if (comm->eDLB == edlbAUTO)
+ print_dd_settings(fplog, dd, ir, dlbIsOn(comm), dlb_scale, ddbox);
+ if (comm->dlbState == edlbsOffCanTurnOn)
{
if (fplog)
{
np = 1 + (int)(cutoff_req*inv_cell_size*ddbox.skew_fac[dim]);
- if (dd->comm->eDLB != edlbNO && dim < ddbox.npbcdim &&
+ if (dd->comm->dlbState != edlbsOffForever && dim < ddbox.npbcdim &&
dd->comm->cd[d].np_dlb > 0)
{
if (np > dd->comm->cd[d].np_dlb)
}
}
- if (dd->comm->eDLB != edlbNO)
+ if (dd->comm->dlbState != edlbsOffForever)
{
/* If DLB is not active yet, we don't need to check the grid jumps.
* Actually we shouldn't, because then the grid jump data is not set.
*/
- if (dd->comm->bDynLoadBal &&
+ if (dlbIsOn(dd->comm) &&
check_grid_jump(0, dd, cutoff_req, &ddbox, FALSE))
{
LocallyLimited = 1;
*/
static void dd_dlb_set_should_check_whether_to_turn_dlb_on(gmx_domdec_t *dd, gmx_bool bValue)
{
- if (dd->comm->eDLB == edlbAUTO)
+ if (dd->comm->dlbState == edlbsOffCanTurnOn)
{
- assert(!dd_dlb_is_locked(dd));
-
dd->comm->bCheckWhetherToTurnDlbOn = bValue;
}
}
{
const int nddp_chk_dlb = 100;
- if (dd->comm->eDLB != edlbAUTO || dd_dlb_is_locked(dd))
+ if (dd->comm->dlbState != edlbsOffCanTurnOn)
{
return FALSE;
}
gmx_bool dd_dlb_is_on(const gmx_domdec_t *dd)
{
- return dd->comm->bDynLoadBal;
+ return (dd->comm->dlbState == edlbsOn);
}
gmx_bool dd_dlb_is_locked(const gmx_domdec_t *dd)
{
- return dd->comm->bDLB_locked;
+ return (dd->comm->dlbState == edlbsOffTemporarilyLocked);
}
void dd_dlb_lock(gmx_domdec_t *dd)
{
/* We can only lock the DLB when it is set to auto, otherwise don't do anything */
- if (dd->comm->eDLB == edlbAUTO)
+ if (dd->comm->dlbState == edlbsOffCanTurnOn)
{
- dd->comm->bDLB_locked = TRUE;
+ dd->comm->dlbState = edlbsOffTemporarilyLocked;
}
}
void dd_dlb_unlock(gmx_domdec_t *dd)
{
/* We can only lock the DLB when it is set to auto, otherwise don't do anything */
- if (dd->comm->eDLB == edlbAUTO)
+ if (dd->comm->dlbState == edlbsOffTemporarilyLocked)
{
- dd->comm->bDLB_locked = FALSE;
- dd_dlb_set_should_check_whether_to_turn_dlb_on(dd, !dd->comm->bDynLoadBal);
+ dd->comm->dlbState = edlbsOffCanTurnOn;
+ dd_dlb_set_should_check_whether_to_turn_dlb_on(dd, TRUE);
}
}
c->c[1][0] = comm->cell_x0[dim1];
/* All rows can see this row */
c->c[1][1] = comm->cell_x0[dim1];
- if (dd->bGridJump)
+ if (dlbIsOn(dd->comm))
{
c->c[1][1] = std::max(comm->cell_x0[dim1], comm->zone_d1[1].mch0);
if (bDistMB)
{
c->c[2][j] = comm->cell_x0[dim2];
}
- if (dd->bGridJump)
+ if (dlbIsOn(dd->comm))
{
/* Use the maximum of the i-cells that see a j-cell */
for (i = 0; i < zones->nizone; i++)
*/
c->cr1[0] = comm->cell_x1[dim1];
c->cr1[3] = comm->cell_x1[dim1];
- if (dd->bGridJump)
+ if (dlbIsOn(dd->comm))
{
c->cr1[0] = std::max(comm->cell_x1[dim1], comm->zone_d1[1].mch1);
if (bDistMB)
bBondComm = comm->bBondComm;
/* Do we need to determine extra distances for multi-body bondeds? */
- bDistMB = (comm->bInterCGMultiBody && dd->bGridJump && dd->ndim > 1);
+ bDistMB = (comm->bInterCGMultiBody && dlbIsOn(dd->comm) && dd->ndim > 1);
/* Do we need to determine extra distances for only two-body bondeds? */
bDist2B = (bBondComm && !bDistMB);
zones = &comm->zones;
/* Do we need to determine extra distances for multi-body bondeds? */
- bDistMB = (comm->bInterCGMultiBody && dd->bGridJump && dd->ndim > 1);
+ bDistMB = (comm->bInterCGMultiBody && dlbIsOn(dd->comm) && dd->ndim > 1);
for (z = zone_start; z < zone_end; z++)
{
/* With a staggered grid we have different sizes
* for non-shifted dimensions.
*/
- if (dd->bGridJump && zones->shift[z][dim] == 0)
+ if (dlbIsOn(dd->comm) && zones->shift[z][dim] == 0)
{
if (d == 1)
{
if (zones->shift[z][dim] > 0)
{
dim = dd->dim[d];
- if (!dd->bGridJump || d == 0)
+ if (!dlbIsOn(dd->comm) || d == 0)
{
zones->size[z].x0[dim] = comm->cell_x1[dim];
zones->size[z].x1[dim] = comm->cell_x1[dim] + rcs;
bNStGlobalComm = (step % nstglobalcomm == 0);
- if (!comm->bDynLoadBal)
+ if (!dlbIsOn(comm))
{
bDoDLB = FALSE;
}
set_ddbox(dd, bMasterState, cr, ir, state_local->box,
TRUE, &top_local->cgs, state_local->x, &ddbox);
- bRedist = comm->bDynLoadBal;
+ bRedist = dlbIsOn(comm);
}
else
{