2 * This file is part of the GROMACS molecular simulation package.
4 * Copyright (c) 2017,2018,2019,2020, by the GROMACS development team, led by
5 * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
6 * and including many others, as listed in the AUTHORS file in the
7 * top-level source directory and at http://www.gromacs.org.
9 * GROMACS is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public License
11 * as published by the Free Software Foundation; either version 2.1
12 * of the License, or (at your option) any later version.
14 * GROMACS is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with GROMACS; if not, see
21 * http://www.gnu.org/licenses, or write to the Free Software Foundation,
22 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24 * If you want to redistribute modifications to GROMACS, please
25 * consider that scientific software is very special. Version
26 * control is crucial - bugs must be traceable. We will be happy to
27 * consider code for inclusion in the official distribution, but
28 * derived work must not be called official GROMACS. Details are found
29 * in the README & COPYING files - if they are missing, get the
30 * official version at http://www.gromacs.org.
32 * To help us fund GROMACS development, we humbly ask that you cite
33 * the research papers on the package. Check out http://www.gromacs.org.
35 /*! \libinternal \file
36 * \brief Declares functionality for deciding whether tasks will run on GPUs.
38 * \author Mark Abraham <mark.j.abraham@gmail.com>
39 * \ingroup module_taskassignment
43 #ifndef GMX_TASKASSIGNMENT_DECIDEGPUUSAGE_H
44 #define GMX_TASKASSIGNMENT_DECIDEGPUUSAGE_H
51 enum class PmeRunMode
;
58 //! Record where a compute task is targetted.
59 enum class TaskTarget
: int
66 //! Help pass GPU-emulation parameters with type safety.
67 enum class EmulateGpuNonbonded
: bool
69 //! Do not emulate GPUs.
76 * \brief Structure that holds boolean flags corresponding to the development
77 * features present enabled through environment variables.
80 struct DevelopmentFeatureFlags
82 //! True if the Buffer ops development feature is enabled
83 // TODO: when the trigger of the buffer ops offload is fully automated this should go away
84 bool enableGpuBufferOps
= false;
85 //! If true, forces 'mdrun -update auto' default to 'gpu'
86 bool forceGpuUpdateDefault
= false;
87 //! True if the GPU halo exchange development feature is enabled
88 bool enableGpuHaloExchange
= false;
89 //! True if the PME PP direct communication GPU development feature is enabled
90 bool enableGpuPmePPComm
= false;
96 /*! \brief Decide whether this thread-MPI simulation will run
97 * nonbonded tasks on GPUs.
99 * The number of GPU tasks and devices influences both the choice of
100 * the number of ranks, and checks upon any such choice made by the
101 * user. So we need to consider this before any automated choice of
102 * the number of thread-MPI ranks.
104 * \param[in] nonbondedTarget The user's choice for mdrun -nb for where to assign
105 * short-ranged nonbonded interaction tasks.
106 * \param[in] numDevicesToUse Number of compatible GPUs that the user permitted
108 * \param[in] userGpuTaskAssignment The user-specified assignment of GPU tasks to device IDs.
109 * \param[in] emulateGpuNonbonded Whether we will emulate GPU calculation of nonbonded
111 * \param[in] buildSupportsNonbondedOnGpu Whether GROMACS was built with GPU support.
112 * \param[in] nonbondedOnGpuIsUseful Whether computing nonbonded interactions on a GPU is
113 * useful for this calculation.
114 * \param[in] numRanksPerSimulation The number of ranks in each simulation.
116 * \returns Whether the simulation will run nonbonded tasks on GPUs.
118 * \throws std::bad_alloc If out of memory
119 * InconsistentInputError If the user requirements are inconsistent. */
120 bool decideWhetherToUseGpusForNonbondedWithThreadMpi(TaskTarget nonbondedTarget
,
122 const std::vector
<int>& userGpuTaskAssignment
,
123 EmulateGpuNonbonded emulateGpuNonbonded
,
124 bool buildSupportsNonbondedOnGpu
,
125 bool nonbondedOnGpuIsUseful
,
126 int numRanksPerSimulation
);
128 /*! \brief Decide whether this thread-MPI simulation will run
131 * The number of GPU tasks and devices influences both the choice of
132 * the number of ranks, and checks upon any such choice made by the
133 * user. So we need to consider this before any automated choice of
134 * the number of thread-MPI ranks.
136 * \param[in] useGpuForNonbonded Whether GPUs will be used for nonbonded interactions.
137 * \param[in] pmeTarget The user's choice for mdrun -pme for where to assign
138 * long-ranged PME nonbonded interaction tasks.
139 * \param[in] numDevicesToUse The number of compatible GPUs that the user permitted us to use.
140 * \param[in] userGpuTaskAssignment The user-specified assignment of GPU tasks to device IDs.
141 * \param[in] hardwareInfo Hardware information
142 * \param[in] inputrec The user input
143 * \param[in] numRanksPerSimulation The number of ranks in each simulation.
144 * \param[in] numPmeRanksPerSimulation The number of PME ranks in each simulation.
146 * \returns Whether the simulation will run PME tasks on GPUs.
148 * \throws std::bad_alloc If out of memory
149 * InconsistentInputError If the user requirements are inconsistent. */
150 bool decideWhetherToUseGpusForPmeWithThreadMpi(bool useGpuForNonbonded
,
151 TaskTarget pmeTarget
,
153 const std::vector
<int>& userGpuTaskAssignment
,
154 const gmx_hw_info_t
& hardwareInfo
,
155 const t_inputrec
& inputrec
,
156 int numRanksPerSimulation
,
157 int numPmeRanksPerSimulation
);
159 /*! \brief Decide whether the simulation will try to run nonbonded
162 * The final decision cannot be made until after the duty of the rank
163 * is known. But we need to know if nonbonded will run on GPUs for
164 * setting up DD (particularly rlist) and determining duty. If the
165 * user requires GPUs for the tasks of that duty, then it will be an
166 * error when none are found.
168 * With thread-MPI, calls have been made to
169 * decideWhetherToUseGpusForNonbondedWithThreadMpi() and
170 * decideWhetherToUseGpusForPmeWithThreadMpi() to help determine
171 * the number of ranks and run some checks, but the final
172 * decision is made in this routine, along with many more
173 * consistency checks.
175 * \param[in] nonbondedTarget The user's choice for mdrun -nb for where to assign short-ranged nonbonded interaction tasks.
176 * \param[in] userGpuTaskAssignment The user-specified assignment of GPU tasks to device IDs.
177 * \param[in] emulateGpuNonbonded Whether we will emulate GPU calculation of nonbonded interactions.
178 * \param[in] buildSupportsNonbondedOnGpu Whether GROMACS was build with GPU support.
179 * \param[in] nonbondedOnGpuIsUseful Whether computing nonbonded interactions on a GPU is useful for this calculation.
180 * \param[in] gpusWereDetected Whether compatible GPUs were detected on any node.
182 * \returns Whether the simulation will run nonbonded and PME tasks, respectively, on GPUs.
184 * \throws std::bad_alloc If out of memory
185 * InconsistentInputError If the user requirements are inconsistent. */
186 bool decideWhetherToUseGpusForNonbonded(TaskTarget nonbondedTarget
,
187 const std::vector
<int>& userGpuTaskAssignment
,
188 EmulateGpuNonbonded emulateGpuNonbonded
,
189 bool buildSupportsNonbondedOnGpu
,
190 bool nonbondedOnGpuIsUseful
,
191 bool gpusWereDetected
);
193 /*! \brief Decide whether the simulation will try to run tasks of
194 * different types on GPUs.
196 * The final decision cannot be made until after the duty of the rank
197 * is known. But we need to know if nonbonded will run on GPUs for
198 * setting up DD (particularly rlist) and determining duty. If the
199 * user requires GPUs for the tasks of that duty, then it will be an
200 * error when none are found.
202 * With thread-MPI, calls have been made to
203 * decideWhetherToUseGpusForNonbondedWithThreadMpi() and
204 * decideWhetherToUseGpusForPmeWithThreadMpi() to help determine
205 * the number of ranks and run some checks, but the final
206 * decision is made in this routine, along with many more
207 * consistency checks.
209 * \param[in] useGpuForNonbonded Whether GPUs will be used for nonbonded interactions.
210 * \param[in] pmeTarget The user's choice for mdrun -pme for where to assign long-ranged PME nonbonded interaction tasks.
211 * \param[in] userGpuTaskAssignment The user-specified assignment of GPU tasks to device IDs.
212 * \param[in] hardwareInfo Hardware information
213 * \param[in] inputrec The user input
214 * \param[in] numRanksPerSimulation The number of ranks in each simulation.
215 * \param[in] numPmeRanksPerSimulation The number of PME ranks in each simulation.
216 * \param[in] gpusWereDetected Whether compatible GPUs were detected on any node.
218 * \returns Whether the simulation will run nonbonded and PME tasks, respectively, on GPUs.
220 * \throws std::bad_alloc If out of memory
221 * InconsistentInputError If the user requirements are inconsistent. */
222 bool decideWhetherToUseGpusForPme(bool useGpuForNonbonded
,
223 TaskTarget pmeTarget
,
224 const std::vector
<int>& userGpuTaskAssignment
,
225 const gmx_hw_info_t
& hardwareInfo
,
226 const t_inputrec
& inputrec
,
227 int numRanksPerSimulation
,
228 int numPmeRanksPerSimulation
,
229 bool gpusWereDetected
);
231 /*! \brief Determine PME run mode.
233 * Given the PME task assignment in \p useGpuForPme and the user-provided
234 * FFT task target in \p pmeFftTarget, returns a PME run mode for the
235 * current run. It also checks the compatibility of the two.
237 * \note Aborts the run upon incompatible values of \p useGpuForPme and \p pmeFftTarget.
239 * \param[in] useGpuForPme PME task assignment, true if PME task is mapped to the GPU.
240 * \param[in] pmeFftTarget The user's choice for -pmefft for where to assign the FFT
241 * work of the PME task. \param[in] inputrec The user input record
243 PmeRunMode
determinePmeRunMode(bool useGpuForPme
, const TaskTarget
& pmeFftTarget
, const t_inputrec
& inputrec
);
245 /*! \brief Decide whether the simulation will try to run bonded tasks on GPUs.
247 * \param[in] useGpuForNonbonded Whether GPUs will be used for nonbonded interactions.
248 * \param[in] useGpuForPme Whether GPUs will be used for PME interactions.
249 * \param[in] bondedTarget The user's choice for mdrun -bonded for where to assign tasks.
250 * \param[in] inputrec The user input.
251 * \param[in] mtop The global topology.
252 * \param[in] numPmeRanksPerSimulation The number of PME ranks in each simulation, can be -1 for auto.
253 * \param[in] gpusWereDetected Whether compatible GPUs were detected on any node.
255 * \returns Whether the simulation will run bondeded tasks on GPUs.
257 * \throws std::bad_alloc If out of memory
258 * InconsistentInputError If the user requirements are inconsistent. */
259 bool decideWhetherToUseGpusForBonded(bool useGpuForNonbonded
,
261 TaskTarget bondedTarget
,
262 const t_inputrec
& inputrec
,
263 const gmx_mtop_t
& mtop
,
264 int numPmeRanksPerSimulation
,
265 bool gpusWereDetected
);
267 /*! \brief Decide whether to use GPU for update.
269 * \param[in] isDomainDecomposition Whether there more than one domain.
270 * \param[in] useUpdateGroups If the constraints can be split across domains.
271 * \param[in] pmeRunMode PME running mode: CPU, GPU or mixed.
272 * \param[in] havePmeOnlyRank If there is a PME-only rank in the simulation.
273 * \param[in] useGpuForNonbonded Whether GPUs will be used for nonbonded interactions.
274 * \param[in] updateTarget User choice for running simulation on GPU.
275 * \param[in] gpusWereDetected Whether compatible GPUs were detected on any node.
276 * \param[in] inputrec The user input.
277 * \param[in] mtop The global topology.
278 * \param[in] useEssentialDynamics If essential dynamics is active.
279 * \param[in] doOrientationRestraints If orientation restraints are enabled.
280 * \param[in] useReplicaExchange If this is a REMD simulation.
281 * \param[in] doRerun It this is a rerun.
282 * \param[in] devFlags GPU development / experimental feature flags.
283 * \param[in] mdlog MD logger.
285 * \returns Whether complete simulation can be run on GPU.
286 * \throws std::bad_alloc If out of memory
287 * InconsistentInputError If the user requirements are inconsistent.
289 bool decideWhetherToUseGpuForUpdate(bool isDomainDecomposition
,
290 bool useUpdateGroups
,
291 PmeRunMode pmeRunMode
,
292 bool havePmeOnlyRank
,
293 bool useGpuForNonbonded
,
294 TaskTarget updateTarget
,
295 bool gpusWereDetected
,
296 const t_inputrec
& inputrec
,
297 const gmx_mtop_t
& mtop
,
298 bool useEssentialDynamics
,
299 bool doOrientationRestraints
,
300 bool useReplicaExchange
,
302 const DevelopmentFeatureFlags
& devFlags
,
303 const gmx::MDLogger
& mdlog
);
306 /*! \brief Decide whether to use GPU for halo exchange.
308 * \param[in] devFlags GPU development / experimental feature flags.
309 * \param[in] havePPDomainDecomposition Whether PP domain decomposition is in use.
310 * \param[in] useGpuForNonbonded Whether GPUs will be used for nonbonded interactions.
311 * \param[in] useModularSimulator Whether modularsimulator is in use.
312 * \param[in] doRerun Whether this is a rerun.
313 * \param[in] haveEnergyMinimization Whether energy minimization is in use.
315 * \returns Whether halo exchange can be run on GPU.
317 bool decideWhetherToUseGpuForHalo(const DevelopmentFeatureFlags
& devFlags
,
318 bool havePPDomainDecomposition
,
319 bool useGpuForNonbonded
,
320 bool useModularSimulator
,
322 bool haveEnergyMinimization
);