Check q perturbation when PME on GPU is tested
authorMagnus Lundborg <lundborg.magnus@gmail.com>
Tue, 4 Sep 2018 09:59:55 +0000 (11:59 +0200)
committerMark Abraham <mark.j.abraham@gmail.com>
Fri, 7 Sep 2018 07:28:32 +0000 (09:28 +0200)
If charges are not perturbued allow running PME on the GPU in
FE simulations.

Refs #2054.

Change-Id: Ibc610cb63afaadf4aa97608b8e03b6906fe2d026

docs/release-notes/performance.rst
src/gromacs/ewald/pme.cpp
src/gromacs/ewald/pme.h
src/gromacs/ewald/tests/pmetestcommon.cpp
src/gromacs/mdrun/runner.cpp
src/gromacs/taskassignment/resourcedivision.cpp
src/gromacs/topology/topology.cpp
src/gromacs/topology/topology.h

index 5c947c28f57da7ec531bfff7dd17262c0a96445b..3bbff7ba1a80c3ef5fa72cd352497a2a80b521c8 100644 (file)
@@ -1,3 +1,7 @@
 Performance improvements
 ^^^^^^^^^^^^^^^^^^^^^^^^
 
+PME on GPU when running free energy perturbations not involving charges
+""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+PME can now be run on a GPU when doing free energy perturbations
+that do not involve perturbing charges.
index befc17c9d28087f01f50d3a49704879430d57bc0..2d2f04484a5cd0a858d0cf339410f7bacbb55699 100644 (file)
 #include "gromacs/timing/cyclecounter.h"
 #include "gromacs/timing/wallcycle.h"
 #include "gromacs/timing/walltime_accounting.h"
+#include "gromacs/topology/topology.h"
 #include "gromacs/utility/basedefinitions.h"
 #include "gromacs/utility/exceptions.h"
 #include "gromacs/utility/fatalerror.h"
@@ -154,30 +155,33 @@ bool pme_gpu_supports_build(std::string *error)
     return addMessageIfNotSupported(errorReasons, error);
 }
 
-bool pme_gpu_supports_input(const t_inputrec *ir, std::string *error)
+bool pme_gpu_supports_input(const t_inputrec &ir, const gmx_mtop_t &mtop, std::string *error)
 {
     std::list<std::string> errorReasons;
-    if (!EEL_PME(ir->coulombtype))
+    if (!EEL_PME(ir.coulombtype))
     {
         errorReasons.emplace_back("systems that do not use PME for electrostatics");
     }
-    if (ir->pme_order != 4)
+    if (ir.pme_order != 4)
     {
         errorReasons.emplace_back("interpolation orders other than 4");
     }
-    if (ir->efep != efepNO)
+    if (ir.efep != efepNO)
     {
-        errorReasons.emplace_back("free energy calculations (multiple grids)");
+        if (gmx_mtop_has_perturbed_charges(mtop))
+        {
+            errorReasons.emplace_back("free energy calculations with perturbed charges (multiple grids)");
+        }
     }
-    if (EVDW_PME(ir->vdwtype))
+    if (EVDW_PME(ir.vdwtype))
     {
         errorReasons.emplace_back("Lennard-Jones PME");
     }
-    if (ir->cutoff_scheme == ecutsGROUP)
+    if (ir.cutoff_scheme == ecutsGROUP)
     {
         errorReasons.emplace_back("group cutoff scheme");
     }
-    if (!EI_DYNAMICS(ir->eI))
+    if (!EI_DYNAMICS(ir.eI))
     {
         errorReasons.emplace_back("not a dynamical integrator");
     }
index 5f6e83f7175d271ab82cd0f777ecf73222e5959f..642967d9e43b2ec35cb52c69cd07f7ff3708c512 100644 (file)
@@ -64,6 +64,7 @@ struct t_nrnb;
 struct PmeGpu;
 struct gmx_wallclock_gpu_pme_t;
 struct gmx_device_info_t;
+struct gmx_mtop_t;
 struct gmx_pme_t;
 struct gmx_wallcycle;
 struct NumPmeDomains;
@@ -261,11 +262,12 @@ bool pme_gpu_supports_build(std::string *error);
  * formed gmx_pme_t structure. Should that one go away/work with inputrec?
  *
  * \param[in]  ir     Input system.
+ * \param[in]  mtop   Complete system topology to check if an FE simulation perturbs charges.
  * \param[out] error  If non-null, the error message if the input is not supported on GPU.
  *
  * \returns true if PME can run on GPU with this input, false otherwise.
  */
-bool pme_gpu_supports_input(const t_inputrec *ir, std::string *error);
+bool pme_gpu_supports_input(const t_inputrec &ir, const gmx_mtop_t &mtop, std::string *error);
 
 /*! \brief
  * Returns the active PME codepath (CPU, GPU, mixed).
index bb82470c011ce578b911e65bc1e9ff2326fec408..186e2a1cfaed76bc2e799c5b73fc21d2401b4852 100644 (file)
@@ -57,6 +57,7 @@
 #include "gromacs/math/invertmatrix.h"
 #include "gromacs/mdtypes/commrec.h"
 #include "gromacs/pbcutil/pbc.h"
+#include "gromacs/topology/topology.h"
 #include "gromacs/utility/exceptions.h"
 #include "gromacs/utility/gmxassert.h"
 #include "gromacs/utility/logger.h"
@@ -71,7 +72,8 @@ namespace test
 
 bool pmeSupportsInputForMode(const t_inputrec *inputRec, CodePath mode)
 {
-    bool implemented;
+    bool       implemented;
+    gmx_mtop_t mtop;
     switch (mode)
     {
         case CodePath::CPU:
@@ -80,7 +82,7 @@ bool pmeSupportsInputForMode(const t_inputrec *inputRec, CodePath mode)
 
         case CodePath::CUDA:
             implemented = (pme_gpu_supports_build(nullptr) &&
-                           pme_gpu_supports_input(inputRec, nullptr));
+                           pme_gpu_supports_input(*inputRec, mtop, nullptr));
             break;
 
         default:
index 5f19274056ce3948553650aaa72abd65bf614a30..46201786c9ca3b3e9c5a46f554a90db7d4f99e3f 100644 (file)
@@ -561,7 +561,7 @@ int Mdrunner::mdrunner()
                     inputrec->cutoff_scheme == ecutsVERLET,
                     gpuAccelerationOfNonbondedIsUseful(mdlog, inputrec, GMX_THREAD_MPI),
                     hw_opt.nthreads_tmpi);
-            auto canUseGpuForPme   = pme_gpu_supports_build(nullptr) && pme_gpu_supports_input(inputrec, nullptr);
+            auto canUseGpuForPme   = pme_gpu_supports_build(nullptr) && pme_gpu_supports_input(*inputrec, mtop, nullptr);
             useGpuForPme = decideWhetherToUseGpusForPmeWithThreadMpi
                     (useGpuForNonbonded, pmeTarget, gpuIdsToUse, userGpuTaskAssignment,
                     canUseGpuForPme, hw_opt.nthreads_tmpi, domdecOptions.numPmeRanks);
@@ -623,7 +623,7 @@ int Mdrunner::mdrunner()
                                                                 emulateGpuNonbonded, inputrec->cutoff_scheme == ecutsVERLET,
                                                                 gpuAccelerationOfNonbondedIsUseful(mdlog, inputrec, !GMX_THREAD_MPI),
                                                                 gpusWereDetected);
-        auto canUseGpuForPme   = pme_gpu_supports_build(nullptr) && pme_gpu_supports_input(inputrec, nullptr);
+        auto canUseGpuForPme   = pme_gpu_supports_build(nullptr) && pme_gpu_supports_input(*inputrec, mtop, nullptr);
         useGpuForPme = decideWhetherToUseGpusForPme(useGpuForNonbonded, pmeTarget, userGpuTaskAssignment,
                                                     canUseGpuForPme, cr->nnodes, domdecOptions.numPmeRanks,
                                                     gpusWereDetected);
index 7ef15ed2a190cd8512da4ff16546ac55a01ea7ba..bd3090152bdd91063a7a4a429b7507a445866b08 100644 (file)
@@ -361,7 +361,7 @@ int get_nthreads_mpi(const gmx_hw_info_t    *hwinfo,
     if (pmeOnGpu)
     {
         GMX_RELEASE_ASSERT((EEL_PME(inputrec->coulombtype) || EVDW_PME(inputrec->vdwtype)) &&
-                           pme_gpu_supports_build(nullptr) && pme_gpu_supports_input(inputrec, nullptr),
+                           pme_gpu_supports_build(nullptr) && pme_gpu_supports_input(*inputrec, *mtop, nullptr),
                            "PME can't be on GPUs unless we are using PME");
 
         // PME on GPUs supports a single PME rank with PP running on the same or few other ranks.
index f03322256729577c2ed6cf8266b9187f08072643..d82c2ac3b27fdad74cad3931de65d5fc0685f6f5 100644 (file)
@@ -251,6 +251,25 @@ bool gmx_mtop_has_charges(const gmx_mtop_t *mtop)
     return mtop->moltype.empty() || mtop->moltype[0].atoms.haveCharge;
 }
 
+bool gmx_mtop_has_perturbed_charges(const gmx_mtop_t &mtop)
+{
+    for (const gmx_moltype_t &moltype : mtop.moltype)
+    {
+        const t_atoms &atoms = moltype.atoms;
+        if (atoms.haveBState)
+        {
+            for (int a = 0; a < atoms.nr; a++)
+            {
+                if (atoms.atom[a].q != atoms.atom[a].qB)
+                {
+                    return true;
+                }
+            }
+        }
+    }
+    return false;
+}
+
 bool gmx_mtop_has_atomtypes(const gmx_mtop_t *mtop)
 {
     if (mtop == nullptr)
index fda99e34017ed6cc3d3838286e514ee04d62ba16..bb9b844f290fd15ff55bf3da424b4db8db838c3b 100644 (file)
@@ -181,6 +181,7 @@ void done_top_mtop(t_topology *top, gmx_mtop_t *mtop);
 
 bool gmx_mtop_has_masses(const gmx_mtop_t *mtop);
 bool gmx_mtop_has_charges(const gmx_mtop_t *mtop);
+bool gmx_mtop_has_perturbed_charges(const gmx_mtop_t &mtop);
 bool gmx_mtop_has_atomtypes(const gmx_mtop_t *mtop);
 bool gmx_mtop_has_pdbinfo(const gmx_mtop_t *mtop);