Basic population of simulation workload
authorPaul Bauer <paul.bauer.q@gmail.com>
Mon, 7 Oct 2019 09:36:04 +0000 (11:36 +0200)
committerArtem Zhmurov <zhmurov@gmail.com>
Thu, 10 Oct 2019 13:22:15 +0000 (15:22 +0200)
Adds basic population of simulation workload datastructure from
information available after task assignment is done to GPU(s).

Also changes population of step and domain work datastructures to
return new datastructure instead of passing pointer to routine that
fills them.

Change-Id: Ie48a4f74eaa69092f24355e19f66a90d6700baa0

src/gromacs/mdlib/sim_util.cpp
src/gromacs/mdrun/isimulator.h
src/gromacs/mdrun/md.cpp
src/gromacs/mdrun/runner.cpp
src/gromacs/mdtypes/simulation_workload.h
src/gromacs/taskassignment/CMakeLists.txt
src/gromacs/taskassignment/decidesimulationworkload.cpp [new file with mode: 0644]
src/gromacs/taskassignment/decidesimulationworkload.h [new file with mode: 0644]
src/gromacs/taskassignment/taskassignment.h

index c34b5559858c54fbc0e6caf852edd13edae5376a..0ea11d91465992adca3f0c305d077399554b1b11 100644 (file)
@@ -759,9 +759,8 @@ setupForceOutputs(t_forcerec                          *fr,
 
 /*! \brief Set up flags that have the lifetime of the domain indicating what type of work is there to compute.
  */
-static void
-setupDomainLifetimeWorkload(DomainLifetimeWorkload *domainWork,
-                            const t_inputrec       &inputrec,
+static DomainLifetimeWorkload
+setupDomainLifetimeWorkload(const t_inputrec       &inputrec,
                             const t_forcerec       &fr,
                             const pull_t           *pull_work,
                             const gmx_edsam        *ed,
@@ -770,36 +769,39 @@ setupDomainLifetimeWorkload(DomainLifetimeWorkload *domainWork,
                             const t_mdatoms        &mdatoms,
                             const StepWorkload     &stepWork)
 {
+    DomainLifetimeWorkload domainWork;
     // Note that haveSpecialForces is constant over the whole run
-    domainWork->haveSpecialForces      = haveSpecialForces(inputrec, *fr.forceProviders, pull_work, stepWork.computeForces, ed);
-    domainWork->haveCpuBondedWork      = haveCpuBondeds(fr);
-    domainWork->haveGpuBondedWork      = ((fr.gpuBonded != nullptr) && fr.gpuBonded->haveInteractions());
-    domainWork->haveRestraintsWork     = havePositionRestraints(idef, fcd);
-    domainWork->haveCpuListedForceWork = haveCpuListedForces(fr, idef, fcd);
+    domainWork.haveSpecialForces      = haveSpecialForces(inputrec, *fr.forceProviders, pull_work, stepWork.computeForces, ed);
+    domainWork.haveCpuBondedWork      = haveCpuBondeds(fr);
+    domainWork.haveGpuBondedWork      = ((fr.gpuBonded != nullptr) && fr.gpuBonded->haveInteractions());
+    domainWork.haveRestraintsWork     = havePositionRestraints(idef, fcd);
+    domainWork.haveCpuListedForceWork = haveCpuListedForces(fr, idef, fcd);
     // Note that haveFreeEnergyWork is constant over the whole run
-    domainWork->haveFreeEnergyWork     = (fr.efep != efepNO && mdatoms.nPerturbed != 0);
+    domainWork.haveFreeEnergyWork     = (fr.efep != efepNO && mdatoms.nPerturbed != 0);
+    return domainWork;
 }
 
 /*! \brief Set up force flag stuct from the force bitmask.
  *
- * \param[out]     flags                Force schedule flags
  * \param[in]      legacyFlags          Force bitmask flags used to construct the new flags
  * \param[in]      isNonbondedOn        Global override, if false forces to turn off all nonbonded calculation.
+ * \returns New Stepworkload description.
  */
-static void
-setupStepWorkload(StepWorkload *flags,
-                  const int     legacyFlags,
+static StepWorkload
+setupStepWorkload(const int     legacyFlags,
                   const bool    isNonbondedOn)
 {
-    flags->stateChanged           = ((legacyFlags & GMX_FORCE_STATECHANGED) != 0);
-    flags->haveDynamicBox         = ((legacyFlags & GMX_FORCE_DYNAMICBOX) != 0);
-    flags->doNeighborSearch       = ((legacyFlags & GMX_FORCE_NS) != 0);
-    flags->computeVirial          = ((legacyFlags & GMX_FORCE_VIRIAL) != 0);
-    flags->computeEnergy          = ((legacyFlags & GMX_FORCE_ENERGY) != 0);
-    flags->computeForces          = ((legacyFlags & GMX_FORCE_FORCES) != 0);
-    flags->computeListedForces    = ((legacyFlags & GMX_FORCE_LISTED) != 0);
-    flags->computeNonbondedForces = ((legacyFlags & GMX_FORCE_NONBONDED) != 0) && isNonbondedOn;
-    flags->computeDhdl            = ((legacyFlags & GMX_FORCE_DHDL) != 0);
+    StepWorkload flags;
+    flags.stateChanged           = ((legacyFlags & GMX_FORCE_STATECHANGED) != 0);
+    flags.haveDynamicBox         = ((legacyFlags & GMX_FORCE_DYNAMICBOX) != 0);
+    flags.doNeighborSearch       = ((legacyFlags & GMX_FORCE_NS) != 0);
+    flags.computeVirial          = ((legacyFlags & GMX_FORCE_VIRIAL) != 0);
+    flags.computeEnergy          = ((legacyFlags & GMX_FORCE_ENERGY) != 0);
+    flags.computeForces          = ((legacyFlags & GMX_FORCE_FORCES) != 0);
+    flags.computeListedForces    = ((legacyFlags & GMX_FORCE_LISTED) != 0);
+    flags.computeNonbondedForces = ((legacyFlags & GMX_FORCE_NONBONDED) != 0) && isNonbondedOn;
+    flags.computeDhdl            = ((legacyFlags & GMX_FORCE_DHDL) != 0);
+    return flags;
 }
 
 
@@ -900,7 +902,7 @@ void do_force(FILE                                     *fplog,
     {
         legacyFlags &= ~GMX_FORCE_NONBONDED;
     }
-    setupStepWorkload(&runScheduleWork->stepWork, legacyFlags, fr->bNonbonded);
+    runScheduleWork->stepWork = setupStepWorkload(legacyFlags, fr->bNonbonded);
 
     const gmx::StepWorkload &stepWork = runScheduleWork->stepWork;
 
@@ -1096,15 +1098,15 @@ void do_force(FILE                                     *fplog,
     {
         // Need to run after the GPU-offload bonded interaction lists
         // are set up to be able to determine whether there is bonded work.
-        setupDomainLifetimeWorkload(&runScheduleWork->domainWork,
-                                    *inputrec,
-                                    *fr,
-                                    pull_work,
-                                    ed,
-                                    top->idef,
-                                    *fcd,
-                                    *mdatoms,
-                                    stepWork);
+        runScheduleWork->domainWork =
+            setupDomainLifetimeWorkload(*inputrec,
+                                        *fr,
+                                        pull_work,
+                                        ed,
+                                        top->idef,
+                                        *fcd,
+                                        *mdatoms,
+                                        stepWork);
 
         wallcycle_start_nocount(wcycle, ewcNS);
         wallcycle_sub_start(wcycle, ewcsNBS_SEARCH_LOCAL);
index e7f3c66249219a4851241eb651d5740c8422395f..73f9a4119c05cdd72885d658fb42dce78620f1c5 100644 (file)
@@ -134,8 +134,7 @@ class ISimulator
             gmx_membed_t                       *membed,
             gmx_walltime_accounting            *walltime_accounting,
             std::unique_ptr<StopHandlerBuilder> stopHandlerBuilder,
-            bool                                doRerun,
-            bool                                useGpuForUpdate) :
+            bool                                doRerun) :
             fplog(fplog),
             cr(cr),
             ms(ms),
@@ -170,8 +169,7 @@ class ISimulator
             membed(membed),
             walltime_accounting(walltime_accounting),
             stopHandlerBuilder(std::move(stopHandlerBuilder)),
-            doRerun(doRerun),
-            useGpuForUpdate(useGpuForUpdate)
+            doRerun(doRerun)
         {}
 
     protected:
@@ -245,9 +243,6 @@ class ISimulator
         std::unique_ptr<StopHandlerBuilder> stopHandlerBuilder;
         //! Whether we're doing a rerun.
         bool                                doRerun;
-        //! Whether we will use the GPU for calculating the update.
-        bool                                useGpuForUpdate;
-
 };
 
 }      // namespace gmx
index 7655cc6f022d8a950219197a17df6db2b36caaeb..6e834cd7c36f55a126841f8c7f792d6c8d121a4a 100644 (file)
 #include "gromacs/mdtypes/mdrunoptions.h"
 #include "gromacs/mdtypes/observableshistory.h"
 #include "gromacs/mdtypes/pullhistory.h"
+#include "gromacs/mdtypes/simulation_workload.h"
 #include "gromacs/mdtypes/state.h"
 #include "gromacs/mdtypes/state_propagator_data_gpu.h"
 #include "gromacs/modularsimulator/energyelement.h"
@@ -322,10 +323,12 @@ void gmx::LegacySimulator::do_md()
 //       1. We have the useGpuForBufferOps variable set and available here and in do_force(...)
 //       2. The proper GPU syncronization is introduced, so that the H2D and D2H data copies can be performed in the separate
 //          stream owned by the StatePropagatorDataGpu
-    bool useGpuForPme       = (fr->pmedata != nullptr) && (pme_run_mode(fr->pmedata) != PmeRunMode::CPU);
-    bool useGpuForNonbonded = fr->nbv->useGpu();
+    const auto &simulationWork     = runScheduleWork->simulationWork;
+    const bool  useGpuForPme       = simulationWork.usePmeGpu;
+    const bool  useGpuForNonbonded = simulationWork.useGpuNonbonded;
     // Temporary solution to make sure that the buffer ops are offloaded when update is offloaded
-    bool useGpuForBufferOps   = (getenv("GMX_USE_GPU_BUFFER_OPS") != nullptr);
+    const bool  useGpuForBufferOps   = simulationWork.useGpuBufferOps;
+    const bool  useGpuForUpdate      = simulationWork.useGpuUpdate;
 
     if (useGpuForUpdate)
     {
index 92057c8320fe263aaad67100d7d79f35a817ab3e..bc01d9bfdd2c47f1cb8c6c6cab42493efde4b27f 100644 (file)
 #include "gromacs/restraint/restraintpotential.h"
 #include "gromacs/swap/swapcoords.h"
 #include "gromacs/taskassignment/decidegpuusage.h"
+#include "gromacs/taskassignment/decidesimulationworkload.h"
 #include "gromacs/taskassignment/resourcedivision.h"
 #include "gromacs/taskassignment/taskassignment.h"
 #include "gromacs/taskassignment/usergpuids.h"
@@ -1532,6 +1533,10 @@ int Mdrunner::mdrunner()
         // this data structure, but currently it's the easiest way to
         // make it work.
         MdrunScheduleWorkload runScheduleWork;
+        // Also populates the simulation constant workload description.
+        runScheduleWork.simulationWork = createSimulationWorkload(useGpuForNonbonded,
+                                                                  useGpuForPme, (pmeRunMode == PmeRunMode::GPU), useGpuForBonded, useGpuForUpdate);
+
 
         GMX_ASSERT(stopHandlerBuilder_, "Runner must provide StopHandlerBuilder to simulator.");
         SimulatorBuilder simulatorBuilder;
@@ -1560,8 +1565,7 @@ int Mdrunner::mdrunner()
                     membed,
                     walltime_accounting,
                     std::move(stopHandlerBuilder_),
-                    doRerun,
-                    useGpuForUpdate);
+                    doRerun);
         simulator->run();
 
         if (inputrec->bPull)
index e1bdc28ee7a3db2e4de004ec2d931f2781555835..e20bcc9e7cfedfb457ab646e025fe2f4973420d9 100644 (file)
@@ -123,19 +123,38 @@ class DomainLifetimeWorkload
  */
 class SimulationWorkload
 {
+    public:
+        //! If we have calculation of short range nonbondeds on GPU
+        bool useGpuNonbonded           = false;
+        //! If we have calculation of long range PME in GPU
+        bool usePmeGpu                 = false;
+        //! If PME FFT solving is done on GPU.
+        bool usePmeFftGpu              = false;
+        //! If bonded interactions are calculated on GPU.
+        bool useGpuBonded              = false;
+        //! If update and constraint solving is performed on GPU.
+        bool useGpuUpdate              = false;
+        //! If buffer operations are performed on GPU.
+        bool useGpuBufferOps           = false;
+        //! If domain decomposition halo exchange is performed on GPU.
+        bool useGpuHaloExchange        = false;
+        //! If direct PP-PME communication between GPU is used.
+        bool useGpuPmePPCommunication  = false;
+        //! If direct GPU-GPU communication is enabled.
+        bool useGpuDirectCommunication = false;
 };
 
 class MdrunScheduleWorkload
 {
     public:
         //! Workload descriptor for information constant for an entire run
-        gmx::SimulationWorkload     simulationWork;
+        SimulationWorkload     simulationWork;
 
         //! Workload descriptor for information constant for an nstlist range of steps
-        gmx::DomainLifetimeWorkload domainWork;
+        DomainLifetimeWorkload domainWork;
 
         //! Workload descriptor for information that may change per-step
-        gmx::StepWorkload           stepWork;
+        StepWorkload           stepWork;
 };
 
 }      // namespace gmx
index 27f179abc3fe2ad016472c7f7b7ac604ee45f6f0..9afd05e13b5e227d1f0f0c372510ff22f7c56cbd 100644 (file)
@@ -1,7 +1,7 @@
 #
 # This file is part of the GROMACS molecular simulation package.
 #
-# Copyright (c) 2017, by the GROMACS development team, led by
+# Copyright (c) 2017,2019, by the GROMACS development team, led by
 # Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
 # and including many others, as listed in the AUTHORS file in the
 # top-level source directory and at http://www.gromacs.org.
@@ -34,6 +34,7 @@
 
 gmx_add_libgromacs_sources(
     decidegpuusage.cpp
+    decidesimulationworkload.cpp
     findallgputasks.cpp
     reportgpuusage.cpp
     resourcedivision.cpp
diff --git a/src/gromacs/taskassignment/decidesimulationworkload.cpp b/src/gromacs/taskassignment/decidesimulationworkload.cpp
new file mode 100644 (file)
index 0000000..be1b5d6
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * This file is part of the GROMACS molecular simulation package.
+ *
+ * Copyright (c) 2019, by the GROMACS development team, led by
+ * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
+ * and including many others, as listed in the AUTHORS file in the
+ * top-level source directory and at http://www.gromacs.org.
+ *
+ * GROMACS is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * of the License, or (at your option) any later version.
+ *
+ * GROMACS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with GROMACS; if not, see
+ * http://www.gnu.org/licenses, or write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
+ *
+ * If you want to redistribute modifications to GROMACS, please
+ * consider that scientific software is very special. Version
+ * control is crucial - bugs must be traceable. We will be happy to
+ * consider code for inclusion in the official distribution, but
+ * derived work must not be called official GROMACS. Details are found
+ * in the README & COPYING files - if they are missing, get the
+ * official version at http://www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the research papers on the package. Check out http://www.gromacs.org.
+ */
+/*! \internal \file
+ * \brief
+ * Defines routine for building simulation workload task description.
+ *
+ * \author Paul Bauer <paul.bauer.q@gmail.com>
+ * \ingroup module_taskassignment
+ */
+#include "gmxpre.h"
+
+#include "decidesimulationworkload.h"
+
+#include "gromacs/taskassignment/taskassignment.h"
+#include "gromacs/utility/arrayref.h"
+
+namespace gmx
+{
+
+SimulationWorkload createSimulationWorkload(bool useGpuForNonbonded,
+                                            bool useGpuForPme,
+                                            bool useGpuForPmeFft,
+                                            bool useGpuForBonded,
+                                            bool useGpuForUpdateConstraints)
+{
+    SimulationWorkload simulationWorkload {
+        useGpuForNonbonded,
+        useGpuForPme,
+        useGpuForPmeFft,
+        useGpuForBonded,
+        useGpuForUpdateConstraints,
+        (getenv("GMX_USE_GPU_BUFFER_OPS") != nullptr),
+        (getenv("GMX_GPU_DD_COMMS") != nullptr),
+        (getenv("GMX_GPU_PME_PP_COMMS") != nullptr),
+        (getenv("GMX_GPU_DD_COMMS") != nullptr) || (getenv("GMX_GPU_PME_PP_COMMS") != nullptr)
+    };
+
+    return simulationWorkload;
+}
+
+}  // namespace gmx
diff --git a/src/gromacs/taskassignment/decidesimulationworkload.h b/src/gromacs/taskassignment/decidesimulationworkload.h
new file mode 100644 (file)
index 0000000..538c2ac
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * This file is part of the GROMACS molecular simulation package.
+ *
+ * Copyright (c) 2019, by the GROMACS development team, led by
+ * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
+ * and including many others, as listed in the AUTHORS file in the
+ * top-level source directory and at http://www.gromacs.org.
+ *
+ * GROMACS is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * of the License, or (at your option) any later version.
+ *
+ * GROMACS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with GROMACS; if not, see
+ * http://www.gnu.org/licenses, or write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
+ *
+ * If you want to redistribute modifications to GROMACS, please
+ * consider that scientific software is very special. Version
+ * control is crucial - bugs must be traceable. We will be happy to
+ * consider code for inclusion in the official distribution, but
+ * derived work must not be called official GROMACS. Details are found
+ * in the README & COPYING files - if they are missing, get the
+ * official version at http://www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the research papers on the package. Check out http://www.gromacs.org.
+ */
+/*! \internal
+ * \file
+ * \brief Declares routine for deciding simulation workload based on GPU tasks.
+ *
+ * \author Paul Bauer <paul.bauer.q@gmail.com>
+ * \ingroup module_taskassignment
+ */
+#ifndef GMX_TASKASSIGNMENT_DECIDESIMULATIONWORKLOAD_H
+#define GMX_TASKASSIGNMENT_DECIDESIMULATIONWORKLOAD_H
+
+#include <vector>
+
+#include "gromacs/mdtypes/simulation_workload.h"
+
+namespace gmx
+{
+
+/*! \brief
+ * Build datastructure that contains decisions whether to run different workload
+ * task on GPUs.
+ *
+ * \param[in] useGpuForNonbonded If we have short-range nonbonded interactions
+ *                               calculations on GPU(s).
+ * \param[in] useGpuForPme       If long range PME interactions are calculated on GPU(s).
+ * \param[in] useGpuForPmeFft    If FFT solving for PME is done on the GPU.
+ * \param[in] useGpuForBonded    If bonded interactions are calculated on GPU(s).
+ * \param[in] useGpuForUpdateConstraints If coordinate update and constraint solving is performed on
+ *                                       GPU(s).
+ * \returns Simulation lifetime constant workload description.
+ */
+SimulationWorkload createSimulationWorkload(bool useGpuForNonbonded,
+                                            bool useGpuForPme,
+                                            bool useGpuForPmeFft,
+                                            bool useGpuForBonded,
+                                            bool useGpuForUpdateConstraints);
+
+
+}  // namespace gmx
+
+#endif
index 689035806e8d454d6ff9f7e9201268d1252ca236..b518638e0a7dd538ed7385a7467f790e9eafb739 100644 (file)
@@ -77,7 +77,9 @@ enum class GpuTask : int
     //! Short-ranged interactions.
     Nonbonded,
     //! Long-ranged interactions.
-    Pme
+    Pme,
+    //! Number of possible tasks.
+    Count
 };
 
 /*! \libinternal