gmx_print_detected_hardware(fplog, isSimulationMasterRank && isMasterSim(ms), mdlog, hwinfo);
std::vector<int> gpuIdsToUse = makeGpuIdsToUse(hwinfo->deviceInfoList, hw_opt.gpuIdsAvailable);
+ const int numDevicesToUse = gmx::ssize(gpuIdsToUse);
// Print citation requests after all software/hardware printing
pleaseCiteGromacs(fplog);
// the number of GPUs to choose the number of ranks.
auto canUseGpuForNonbonded = buildSupportsNonbondedOnGpu(nullptr);
useGpuForNonbonded = decideWhetherToUseGpusForNonbondedWithThreadMpi(
- nonbondedTarget, gpuIdsToUse, userGpuTaskAssignment, emulateGpuNonbonded,
+ nonbondedTarget, numDevicesToUse, userGpuTaskAssignment, emulateGpuNonbonded,
canUseGpuForNonbonded,
gpuAccelerationOfNonbondedIsUseful(mdlog, *inputrec, GMX_THREAD_MPI),
hw_opt.nthreads_tmpi);
useGpuForPme = decideWhetherToUseGpusForPmeWithThreadMpi(
- useGpuForNonbonded, pmeTarget, gpuIdsToUse, userGpuTaskAssignment, *hwinfo,
+ useGpuForNonbonded, pmeTarget, numDevicesToUse, userGpuTaskAssignment, *hwinfo,
*inputrec, hw_opt.nthreads_tmpi, domdecOptions.numPmeRanks);
}
GMX_CATCH_ALL_AND_EXIT_WITH_FATAL_ERROR
* prevent any possible subsequent checks from working
* correctly. */
hw_opt.nthreads_tmpi =
- get_nthreads_mpi(hwinfo, &hw_opt, gpuIdsToUse, useGpuForNonbonded, useGpuForPme,
+ get_nthreads_mpi(hwinfo, &hw_opt, numDevicesToUse, useGpuForNonbonded, useGpuForPme,
inputrec.get(), &mtop, mdlog, membedHolder.doMembed());
// Now start the threads for thread MPI.
// where appropriate.
if (!userGpuTaskAssignment.empty())
{
- gpuTaskAssignments.logPerformanceHints(mdlog, ssize(gpuIdsToUse));
+ gpuTaskAssignments.logPerformanceHints(mdlog, numDevicesToUse);
}
if (PAR(cr))
} // namespace
bool decideWhetherToUseGpusForNonbondedWithThreadMpi(const TaskTarget nonbondedTarget,
- const std::vector<int>& gpuIdsToUse,
+ const int numDevicesToUse,
const std::vector<int>& userGpuTaskAssignment,
const EmulateGpuNonbonded emulateGpuNonbonded,
const bool buildSupportsNonbondedOnGpu,
// Because this is thread-MPI, we already know about the GPUs that
// all potential ranks can use, and can use that in a global
// decision that will later be consistent.
- auto haveGpus = !gpuIdsToUse.empty();
-
// If we get here, then the user permitted or required GPUs.
- return haveGpus;
+ return (numDevicesToUse > 0);
}
bool decideWhetherToUseGpusForPmeWithThreadMpi(const bool useGpuForNonbonded,
const TaskTarget pmeTarget,
- const std::vector<int>& gpuIdsToUse,
+ const int numDevicesToUse,
const std::vector<int>& userGpuTaskAssignment,
const gmx_hw_info_t& hardwareInfo,
const t_inputrec& inputrec,
{
// PME can run well on a GPU shared with NB, and we permit
// mdrun to default to try that.
- return !gpuIdsToUse.empty();
+ return numDevicesToUse > 0;
}
if (numRanksPerSimulation < 1)
// Full automated mode for thread-MPI (the default). PME can
// run well on a GPU shared with NB, and we permit mdrun to
// default to it if there is only one GPU available.
- return (gpuIdsToUse.size() == 1);
+ return (numDevicesToUse == 1);
}
// Not enough support for PME on GPUs for anything else
* user. So we need to consider this before any automated choice of
* the number of thread-MPI ranks.
*
- * \param[in] nonbondedTarget The user's choice for mdrun -nb for where to assign short-ranged nonbonded interaction tasks.
- * \param[in] gpuIdsToUse The compatible GPUs that the user permitted us to use.
- * \param[in] userGpuTaskAssignment The user-specified assignment of GPU tasks to device IDs.
- * \param[in] emulateGpuNonbonded Whether we will emulate GPU calculation of nonbonded interactions.
- * \param[in] buildSupportsNonbondedOnGpu Whether GROMACS was built with GPU support.
- * \param[in] nonbondedOnGpuIsUseful Whether computing nonbonded interactions on a GPU is useful for this calculation.
- * \param[in] numRanksPerSimulation The number of ranks in each simulation.
+ * \param[in] nonbondedTarget The user's choice for mdrun -nb for where to assign
+ * short-ranged nonbonded interaction tasks.
+ * \param[in] numDevicesToUse Number of compatible GPUs that the user permitted
+ * us to use.
+ * \param[in] userGpuTaskAssignment The user-specified assignment of GPU tasks to device IDs.
+ * \param[in] emulateGpuNonbonded Whether we will emulate GPU calculation of nonbonded
+ * interactions.
+ * \param[in] buildSupportsNonbondedOnGpu Whether GROMACS was built with GPU support.
+ * \param[in] nonbondedOnGpuIsUseful Whether computing nonbonded interactions on a GPU is
+ * useful for this calculation.
+ * \param[in] numRanksPerSimulation The number of ranks in each simulation.
*
* \returns Whether the simulation will run nonbonded tasks on GPUs.
*
* \throws std::bad_alloc If out of memory
* InconsistentInputError If the user requirements are inconsistent. */
bool decideWhetherToUseGpusForNonbondedWithThreadMpi(TaskTarget nonbondedTarget,
- const std::vector<int>& gpuIdsToUse,
+ int numDevicesToUse,
const std::vector<int>& userGpuTaskAssignment,
EmulateGpuNonbonded emulateGpuNonbonded,
bool buildSupportsNonbondedOnGpu,
* \param[in] useGpuForNonbonded Whether GPUs will be used for nonbonded interactions.
* \param[in] pmeTarget The user's choice for mdrun -pme for where to assign
* long-ranged PME nonbonded interaction tasks.
- * \param[in] gpuIdsToUse The compatible GPUs that the user permitted us to use.
+ * \param[in] numDevicesToUse The number of compatible GPUs that the user permitted us to use.
* \param[in] userGpuTaskAssignment The user-specified assignment of GPU tasks to device IDs.
* \param[in] hardwareInfo Hardware information
* \param[in] inputrec The user input
* InconsistentInputError If the user requirements are inconsistent. */
bool decideWhetherToUseGpusForPmeWithThreadMpi(bool useGpuForNonbonded,
TaskTarget pmeTarget,
- const std::vector<int>& gpuIdsToUse,
+ int numDevicesToUse,
const std::vector<int>& userGpuTaskAssignment,
const gmx_hw_info_t& hardwareInfo,
const t_inputrec& inputrec,
* Thus all options should be internally consistent and consistent
* with the hardware, except that ntmpi could be larger than #GPU.
*/
-int get_nthreads_mpi(const gmx_hw_info_t* hwinfo,
- gmx_hw_opt_t* hw_opt,
- const std::vector<int>& gpuIdsToUse,
- bool nonbondedOnGpu,
- bool pmeOnGpu,
- const t_inputrec* inputrec,
- const gmx_mtop_t* mtop,
- const gmx::MDLogger& mdlog,
- bool doMembed)
+int get_nthreads_mpi(const gmx_hw_info_t* hwinfo,
+ gmx_hw_opt_t* hw_opt,
+ const int numDevicesToUse,
+ bool nonbondedOnGpu,
+ bool pmeOnGpu,
+ const t_inputrec* inputrec,
+ const gmx_mtop_t* mtop,
+ const gmx::MDLogger& mdlog,
+ bool doMembed)
{
int nthreads_hw, nthreads_tot_max, nrank, ngpu;
int min_atoms_per_mpi_rank;
/* nonbondedOnGpu might be false e.g. because this simulation
* is a rerun with energy groups. */
- ngpu = (nonbondedOnGpu ? gmx::ssize(gpuIdsToUse) : 0);
+ ngpu = (nonbondedOnGpu ? numDevicesToUse : 0);
nrank = get_tmpi_omp_thread_division(hwinfo, *hw_opt, nthreads_tot_max, ngpu);
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2015,2016,2017,2018,2019,2020, 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.
* with the hardware, except that ntmpi could be larger than number of GPUs.
* If necessary, this function will modify hw_opt->nthreads_omp.
*/
-int get_nthreads_mpi(const gmx_hw_info_t* hwinfo,
- gmx_hw_opt_t* hw_opt,
- const std::vector<int>& gpuIdsToUse,
- bool nonbondedOnGpu,
- bool pmeOnGpu,
- const t_inputrec* inputrec,
- const gmx_mtop_t* mtop,
- const gmx::MDLogger& mdlog,
- bool doMembed);
+int get_nthreads_mpi(const gmx_hw_info_t* hwinfo,
+ gmx_hw_opt_t* hw_opt,
+ int numDevicesToUse,
+ bool nonbondedOnGpu,
+ bool pmeOnGpu,
+ const t_inputrec* inputrec,
+ const gmx_mtop_t* mtop,
+ const gmx::MDLogger& mdlog,
+ bool doMembed);
/*! \brief Check if the number of OpenMP threads is within reasonable range
* considering the hardware used. This is a crude check, but mainly