Support GPU update without constraints
authorAndrey Alekseenko <al42and@gmail.com>
Wed, 19 May 2021 16:15:08 +0000 (16:15 +0000)
committerArtem Zhmurov <zhmurov@gmail.com>
Wed, 19 May 2021 16:15:08 +0000 (16:15 +0000)
src/gromacs/mdlib/update_constrain_gpu.h
src/gromacs/mdlib/update_constrain_gpu_impl.cpp
src/gromacs/mdlib/update_constrain_gpu_impl_stubs.cpp
src/gromacs/taskassignment/decidegpuusage.cpp

index ce23e1dfa04123e2298c60c18e34dc8be8ced217..9050039b13b7b52846746a1858d34a5be7c3320d 100644 (file)
@@ -178,6 +178,13 @@ public:
      */
     static bool isNumCoupledConstraintsSupported(const gmx_mtop_t& mtop);
 
+    /*! \brief
+     * Returns whether the constraints are supported by the GPU code.
+     *
+     * Currently true for CUDA, false for others.
+     */
+    static bool areConstraintsSupported();
+
 private:
     class Impl;
     std::unique_ptr<Impl> impl_;
index df6420d378f1de257e550a3f5a92ce410223f805..6e5c56a8677d10dc181462481ee9751f2e82e79d 100644 (file)
@@ -70,6 +70,9 @@
 #include "gromacs/mdlib/update_constrain_gpu_internal.h"
 #include "gromacs/mdtypes/mdatom.h"
 #include "gromacs/timing/wallcycle.h"
+#include "gromacs/topology/mtop_util.h"
+
+static constexpr bool sc_haveGpuConstraintSupport = (GMX_GPU_CUDA);
 
 namespace gmx
 {
@@ -102,8 +105,11 @@ void UpdateConstrainGpu::Impl::integrate(GpuEventSynchronizer*             fRead
     // Constraints need both coordinates before (d_x_) and after (d_xp_) update. However, after constraints
     // are applied, the d_x_ can be discarded. So we intentionally swap the d_x_ and d_xp_ here to avoid the
     // d_xp_ -> d_x_ copy after constraints. Note that the integrate saves them in the wrong order as well.
-    lincsGpu_->apply(d_xp_, d_x_, updateVelocities, d_v_, 1.0 / dt, computeVirial, virial, pbcAiuc_);
-    settleGpu_->apply(d_xp_, d_x_, updateVelocities, d_v_, 1.0 / dt, computeVirial, virial, pbcAiuc_);
+    if (sc_haveGpuConstraintSupport)
+    {
+        lincsGpu_->apply(d_xp_, d_x_, updateVelocities, d_v_, 1.0 / dt, computeVirial, virial, pbcAiuc_);
+        settleGpu_->apply(d_xp_, d_x_, updateVelocities, d_v_, 1.0 / dt, computeVirial, virial, pbcAiuc_);
+    }
 
     // scaledVirial -> virial (methods above returns scaled values)
     float scaleFactor = 0.5F / (dt * dt);
@@ -164,8 +170,11 @@ UpdateConstrainGpu::Impl::Impl(const t_inputrec&     ir,
     GMX_ASSERT(xUpdatedOnDevice != nullptr, "The event synchronizer can not be nullptr.");
 
     integrator_ = std::make_unique<LeapFrogGpu>(deviceContext_, deviceStream_, numTempScaleValues);
-    lincsGpu_ = std::make_unique<LincsGpu>(ir.nLincsIter, ir.nProjOrder, deviceContext_, deviceStream_);
-    settleGpu_ = std::make_unique<SettleGpu>(mtop, deviceContext_, deviceStream_);
+    if (sc_haveGpuConstraintSupport)
+    {
+        lincsGpu_ = std::make_unique<LincsGpu>(ir.nLincsIter, ir.nProjOrder, deviceContext_, deviceStream_);
+        settleGpu_ = std::make_unique<SettleGpu>(mtop, deviceContext_, deviceStream_);
+    }
 }
 
 UpdateConstrainGpu::Impl::~Impl() {}
@@ -196,8 +205,16 @@ void UpdateConstrainGpu::Impl::set(DeviceBuffer<Float3>          d_x,
 
     // Integrator should also update something, but it does not even have a method yet
     integrator_->set(numAtoms_, md.invmass, md.cTC);
-    lincsGpu_->set(idef, numAtoms_, md.invmass);
-    settleGpu_->set(idef);
+    if (sc_haveGpuConstraintSupport)
+    {
+        lincsGpu_->set(idef, numAtoms_, md.invmass);
+        settleGpu_->set(idef);
+    }
+    else
+    {
+        GMX_ASSERT(idef.il[F_SETTLE].empty(), "SETTLE not supported");
+        GMX_ASSERT(idef.il[F_CONSTR].empty(), "LINCS not supported");
+    }
 
     wallcycle_sub_stop(wcycle_, WallCycleSubCounter::LaunchGpuUpdateConstrain);
     wallcycle_stop(wcycle_, WallCycleCounter::LaunchGpu);
@@ -284,4 +301,9 @@ bool UpdateConstrainGpu::isNumCoupledConstraintsSupported(const gmx_mtop_t& mtop
     return LincsGpu::isNumCoupledConstraintsSupported(mtop);
 }
 
+bool UpdateConstrainGpu::areConstraintsSupported()
+{
+    return sc_haveGpuConstraintSupport;
+}
+
 } // namespace gmx
index 38b55c7931e4d775623987f65a7cc8feafa172f7..0ec9102a80fce6458f467af6dd319e60bdca8686 100644 (file)
@@ -126,6 +126,12 @@ bool UpdateConstrainGpu::isNumCoupledConstraintsSupported(const gmx_mtop_t& /* m
     return false;
 }
 
+
+bool UpdateConstrainGpu::areConstraintsSupported()
+{
+    return false;
+}
+
 } // namespace gmx
 
 #endif /* !GMX_GPU_CUDA && !GMX_GPU_SYCL */
index d7fa6d2ade4845962ae4e2b4361e52a2a198849a..0bb5c92eeae76a6162215aa087fd12bd93a6c14e 100644 (file)
@@ -601,7 +601,6 @@ bool decideWhetherToUseGpuForUpdate(const bool                     isDomainDecom
         errorMessage +=
                 "Either PME or short-ranged non-bonded interaction tasks must run on the GPU.\n";
     }
-
     if (!gpusWereDetected)
     {
         errorMessage += "Compatible GPUs must have been found.\n";
@@ -682,6 +681,10 @@ bool decideWhetherToUseGpuForUpdate(const bool                     isDomainDecom
                 "The number of coupled constraints is higher than supported in the GPU LINCS "
                 "code.\n";
     }
+    if (hasAnyConstraints && !UpdateConstrainGpu::areConstraintsSupported())
+    {
+        errorMessage += "Chosen GPU implementation does not support constraints.\n";
+    }
     if (haveFrozenAtoms)
     {
         // There is a known bug with frozen atoms and GPU update, see Issue #3920.