#include "gromacs/utility/cstringutil.h"
#include "gromacs/utility/fatalerror.h"
#include "gromacs/utility/gmxassert.h"
+#include "gromacs/utility/logger.h"
+#include "gromacs/utility/stringutil.h"
/*! \brief Returns if we can (heuristically) change nstlist and rlist
*
bool useOrEmulateGpuForNonbondeds,
const gmx::CpuInfo &cpuinfo)
{
+ if (!EI_DYNAMICS(ir->eI))
+ {
+ /* Can only increase nstlist with dynamics */
+ return;
+ }
+
float listfac_ok, listfac_max;
int nstlist_orig, nstlist_prev;
- verletbuf_list_setup_t ls;
real rlistWithReferenceNstlist, rlist_inc, rlist_ok, rlist_max;
real rlist_new, rlist_prev;
size_t nstlist_ind = 0;
return;
}
- if (fp != nullptr && useOrEmulateGpuForNonbondeds && ir->nstlist < nstlist_try[0])
+ /* With a GPU and fixed nstlist suggest tuning nstlist */
+ if (fp != nullptr &&
+ useOrEmulateGpuForNonbondeds &&
+ ir->nstlist < nstlist_try[0] &&
+ !supportsDynamicPairlistGenerationInterval(*ir))
{
fprintf(fp, nstl_gpu, ir->nstlist);
}
+
nstlist_ind = 0;
while (nstlist_ind < NNSTL && ir->nstlist >= nstlist_try[nstlist_ind])
{
return;
}
+ GMX_RELEASE_ASSERT(supportsDynamicPairlistGenerationInterval(*ir), "In all cases that do not support dynamic nstlist, we should have returned with an appropriate message above");
+
if (useOrEmulateGpuForNonbondeds)
{
listfac_ok = c_nbnxnListSizeFactorGPU;
ir->nstlist = nstlist_cmdline;
}
- verletbuf_get_list_setup(TRUE, useOrEmulateGpuForNonbondeds, &ls);
+ ListSetupType listType = (useOrEmulateGpuForNonbondeds ? ListSetupType::Gpu : ListSetupType::CpuSimdWhenSupported);
+ VerletbufListSetup listSetup = verletbufGetSafeListSetup(listType);
/* Allow rlist to make the list a given factor larger than the list
* would be with the reference value for nstlist (10).
nstlist_prev = ir->nstlist;
ir->nstlist = nbnxnReferenceNstlist;
calc_verlet_buffer_size(mtop, det(box), ir, ir->nstlist, ir->nstlist - 1,
- -1, &ls, nullptr, &rlistWithReferenceNstlist);
+ -1, &listSetup,
+ nullptr, &rlistWithReferenceNstlist);
ir->nstlist = nstlist_prev;
/* Determine the pair list size increase due to zero interactions */
- rlist_inc = nbnxn_get_rlist_effective_inc(ls.cluster_size_j,
+ rlist_inc = nbnxn_get_rlist_effective_inc(listSetup.cluster_size_j,
mtop->natoms/det(box));
rlist_ok = (rlistWithReferenceNstlist + rlist_inc)*std::cbrt(listfac_ok) - rlist_inc;
rlist_max = (rlistWithReferenceNstlist + rlist_inc)*std::cbrt(listfac_max) - rlist_inc;
}
/* Set the pair-list buffer size in ir */
- calc_verlet_buffer_size(mtop, det(box), ir, ir->nstlist, ir->nstlist - 1, -1, &ls, nullptr, &rlist_new);
+ calc_verlet_buffer_size(mtop, det(box), ir, ir->nstlist, ir->nstlist - 1, -1, &listSetup, nullptr, &rlist_new);
/* Does rlist fit in the box? */
bBox = (gmx::square(rlist_new) < max_cutoff2(ir->ePBC, box));
const gmx_mtop_t *mtop,
matrix box,
gmx_bool useGpu,
- const verletbuf_list_setup_t &listSetup,
+ const VerletbufListSetup &listSetup,
bool userSetNstlistPrune,
const interaction_const_t *ic,
NbnxnListParameters *listParams)
}
}
-void setupDynamicPairlistPruning(FILE *fplog,
+/*! \brief Returns a string describing the setup of a single pair-list
+ *
+ * \param[in] listName Short name of the list, can be ""
+ * \param[in] nstList The list update interval in steps
+ * \param[in] nstListForSpacing Update interval for setting the number characters for printing \p nstList
+ * \param[in] rList List cut-off radius
+ * \param[in] interactionCutoff The interaction cut-off, use for printing the list buffer size
+ */
+static std::string formatListSetup(const std::string &listName,
+ int nstList,
+ int nstListForSpacing,
+ real rList,
+ real interactionCutoff)
+{
+ std::string listSetup = " ";
+ if (!listName.empty())
+ {
+ listSetup += listName + " list: ";
+ }
+ listSetup += "updated every ";
+ // Make the shortest int format string that fits nstListForSpacing
+ std::string nstListFormat = "%" + gmx::formatString("%d", gmx::formatString("%zu", nstListForSpacing).size()) + "d";
+ listSetup += gmx::formatString(nstListFormat.c_str(), nstList);
+ listSetup += gmx::formatString(" steps, buffer %.3f nm, rlist %.3f nm\n",
+ rList - interactionCutoff, rList);
+
+ return listSetup;
+}
+
+void setupDynamicPairlistPruning(const gmx::MDLogger &mdlog,
const t_inputrec *ir,
const gmx_mtop_t *mtop,
matrix box,
- bool useGpu,
+ int nbnxnKernelType,
const interaction_const_t *ic,
NbnxnListParameters *listParams)
{
/* Initialize the parameters to no dynamic list pruning */
listParams->useDynamicPruning = false;
+ const VerletbufListSetup ls = verletbufGetListSetup(nbnxnKernelType);
+
+ /* Currently emulation mode does not support dual pair-lists */
+ const bool useGpu = (nbnxnKernelType == nbnxnk8x8x8_GPU);
+
if (supportsDynamicPairlistGenerationInterval(*ir) &&
getenv("GMX_DISABLE_DYNAMICPRUNING") == NULL)
{
- verletbuf_list_setup_t ls;
- verletbuf_get_list_setup(TRUE, TRUE, &ls);
-
/* Note that nstlistPrune can have any value independently of nstlist.
* Actually applying rolling pruning is only useful when
* nstlistPrune < nstlist -1
{
listParams->numRollingParts = 1;
}
+ }
+
+ std::string mesg;
- if (fplog && listParams->useDynamicPruning)
+ const real interactionCutoff = std::max(ic->rcoulomb, ic->rvdw);
+ if (listParams->useDynamicPruning)
+ {
+ mesg += gmx::formatString("Using a dual %dx%d pair-list setup updated with dynamic%s pruning:\n",
+ ls.cluster_size_i, ls.cluster_size_j,
+ listParams->numRollingParts > 1 ? ", rolling" : "");
+ mesg += formatListSetup("outer", ir->nstlist, ir->nstlist, listParams->rlistOuter, interactionCutoff);
+ mesg += formatListSetup("inner", listParams->nstlistPrune, ir->nstlist, listParams->rlistInner, interactionCutoff);
+ }
+ else
+ {
+ mesg += gmx::formatString("Using a %dx%d pair-list setup:\n",
+ ls.cluster_size_i, ls.cluster_size_j);
+ mesg += formatListSetup("", ir->nstlist, ir->nstlist, listParams->rlistOuter, interactionCutoff);
+ }
+ if (supportsDynamicPairlistGenerationInterval(*ir))
+ {
+ VerletbufListSetup listSetup1x1 = { 1, 1 };
+ real rlistOuter;
+ real rlistInner;
+ calc_verlet_buffer_size(mtop, det(box), ir, ir->nstlist, ir->nstlist - 1,
+ -1, &listSetup1x1, nullptr, &rlistOuter);
+ if (listParams->useDynamicPruning)
{
- const real interactionCutoff = std::max(ic->rcoulomb, ic->rvdw);
- fprintf(fplog,
- "Using a dual pair-list setup updated with dynamic%s pruning:\n"
- " outer list: updated every %3d steps, buffer %.3f nm, rlist %.3f nm\n"
- " inner list: updated every %3d steps, buffer %.3f nm, rlist %.3f nm\n",
- listParams->numRollingParts > 1 ? ", rolling" : "",
- ir->nstlist, listParams->rlistOuter - interactionCutoff, listParams->rlistOuter,
- listParams->nstlistPrune, listParams->rlistInner - interactionCutoff, listParams->rlistInner);
+ int listLifeTime = listParams->nstlistPrune - (useGpu ? 0 : 1);
+ calc_verlet_buffer_size(mtop, det(box), ir, listParams->nstlistPrune, listLifeTime,
+ -1, &listSetup1x1, nullptr, &rlistInner);
+ }
+
+ mesg += gmx::formatString("At tolerance %g kJ/mol/ps per atom, equivalent classical 1x1 list would be:\n",
+ ir->verletbuf_tol);
+ if (listParams->useDynamicPruning)
+ {
+ mesg += formatListSetup("outer", ir->nstlist, ir->nstlist, rlistOuter, interactionCutoff);
+ mesg += formatListSetup("inner", listParams->nstlistPrune, ir->nstlist, rlistInner, interactionCutoff);
+ }
+ else
+ {
+ mesg += formatListSetup("", ir->nstlist, ir->nstlist, rlistOuter, interactionCutoff);
}
}
+
+ GMX_LOG(mdlog.info).asParagraph().appendText(mesg);
}