*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017,2018,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.
addMessageIfNotSupported(const std::list<std::string> &errorReasons,
std::string *error)
{
- bool foundErrorReasons = errorReasons.empty();
- if (!foundErrorReasons && error)
+ bool isSupported = errorReasons.empty();
+ if (!isSupported && error)
{
std::string regressionTestMarker = "PME GPU does not support";
// this prefix is tested for in the regression tests script gmxtest.pl
- *error = regressionTestMarker + ": " + gmx::joinStrings(errorReasons, "; ") + ".";
+ *error = regressionTestMarker;
+ if (errorReasons.size() == 1)
+ {
+ *error += " " + errorReasons.back();
+ }
+ else
+ {
+ *error += ": " + gmx::joinStrings(errorReasons, "; ");
+ }
+ *error += ".";
}
- return foundErrorReasons;
+ return isSupported;
}
-bool pme_gpu_supports_build(const gmx_hw_info_t &hwinfo,
- std::string *error)
+bool pme_gpu_supports_build(std::string *error)
{
std::list<std::string> errorReasons;
if (GMX_DOUBLE)
{
- errorReasons.emplace_back("double precision");
+ errorReasons.emplace_back("a double-precision build");
}
if (GMX_GPU == GMX_GPU_NONE)
{
- errorReasons.emplace_back("non-GPU build of GROMACS");
+ errorReasons.emplace_back("a non-GPU build");
}
+ return addMessageIfNotSupported(errorReasons, error);
+}
+
+bool pme_gpu_supports_hardware(const gmx_hw_info_t &hwinfo,
+ std::string *error)
+{
+ std::list<std::string> errorReasons;
if (GMX_GPU == GMX_GPU_OPENCL)
{
if (!areAllGpuDevicesFromAmd(hwinfo.gpu_info))
{
- errorReasons.emplace_back("only AMD devices are supported");
+ errorReasons.emplace_back("non-AMD devices");
}
}
return addMessageIfNotSupported(errorReasons, error);
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017,2018,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.
* TODO: this partly duplicates an internal PME assert function
* pme_gpu_check_restrictions(), except that works with a
* formed gmx_pme_t structure. Should that one go away/work with inputrec?
+ *
+ * \param[out] error If non-null, the error message when PME is not supported on GPU.
+ *
+ * \returns true if PME can run on GPU on this build, false otherwise.
+ */
+bool pme_gpu_supports_build(std::string *error);
+
+/*! \brief Checks whether the detected (GPU) hardware allows to run PME on GPU.
*
* \param[in] hwinfo Information about the detected hardware
* \param[out] error If non-null, the error message when PME is not supported on GPU.
*
* \returns true if PME can run on GPU on this build, false otherwise.
*/
-bool pme_gpu_supports_build(const gmx_hw_info_t &hwinfo,
- std::string *error);
+bool pme_gpu_supports_hardware(const gmx_hw_info_t &hwinfo,
+ std::string *error);
/*! \brief Checks whether the input system allows to run PME on GPU.
* TODO: this partly duplicates an internal PME assert function
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2016,2017,2018, by the GROMACS development team, led by
+ * Copyright (c) 2016,2017,2018,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.
break;
case CodePath::GPU:
- implemented = (pme_gpu_supports_build(hwinfo, nullptr) &&
+ implemented = (pme_gpu_supports_build(nullptr) &&
+ pme_gpu_supports_hardware(hwinfo, nullptr) &&
pme_gpu_supports_input(*inputRec, mtop, nullptr));
break;
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2017,2018, by the GROMACS development team, led by
+ * Copyright (c) 2017,2018,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.
hardwareContexts_.emplace_back(compat::make_unique<TestHardwareContext>(CodePath::CPU, "", nullptr));
hardwareInfo_ = hardwareInit();
- if (!pme_gpu_supports_build(*hardwareInfo_, nullptr))
+ if (!pme_gpu_supports_build(nullptr) ||
+ !pme_gpu_supports_hardware(*hardwareInfo_, nullptr))
{
// PME can only run on the CPU, so don't make any more test contexts.
return;
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2011,2012,2013,2014,2015,2016,2017,2018, by the GROMACS development team, led by
+ * Copyright (c) 2011,2012,2013,2014,2015,2016,2017,2018,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.
inputrec->cutoff_scheme == ecutsVERLET,
gpuAccelerationOfNonbondedIsUseful(mdlog, inputrec, GMX_THREAD_MPI),
hw_opt.nthreads_tmpi);
- auto canUseGpuForPme = pme_gpu_supports_build(*hwinfo, nullptr) && pme_gpu_supports_input(*inputrec, mtop, nullptr);
useGpuForPme = decideWhetherToUseGpusForPmeWithThreadMpi
(useGpuForNonbonded, pmeTarget, gpuIdsToUse, userGpuTaskAssignment,
- canUseGpuForPme, hw_opt.nthreads_tmpi, domdecOptions.numPmeRanks);
+ *hwinfo, *inputrec, mtop, hw_opt.nthreads_tmpi, domdecOptions.numPmeRanks);
}
GMX_CATCH_ALL_AND_EXIT_WITH_FATAL_ERROR;
usingVerletScheme,
gpuAccelerationOfNonbondedIsUseful(mdlog, inputrec, !GMX_THREAD_MPI),
gpusWereDetected);
- auto canUseGpuForPme = pme_gpu_supports_build(*hwinfo, nullptr) && pme_gpu_supports_input(*inputrec, mtop, nullptr);
useGpuForPme = decideWhetherToUseGpusForPme(useGpuForNonbonded, pmeTarget, userGpuTaskAssignment,
- canUseGpuForPme, cr->nnodes, domdecOptions.numPmeRanks,
+ *hwinfo, *inputrec, mtop,
+ cr->nnodes, domdecOptions.numPmeRanks,
gpusWereDetected);
auto canUseGpuForBonded = buildSupportsGpuBondeds(nullptr) && inputSupportsGpuBondeds(*inputrec, mtop, nullptr);
useGpuForBonded =
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2015,2016,2017,2018, by the GROMACS development team, led by
+ * Copyright (c) 2015,2016,2017,2018,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.
#include <algorithm>
#include <string>
+#include "gromacs/ewald/pme.h"
#include "gromacs/hardware/cpuinfo.h"
#include "gromacs/hardware/detecthardware.h"
#include "gromacs/hardware/hardwaretopology.h"
const TaskTarget pmeTarget,
const std::vector<int> &gpuIdsToUse,
const std::vector<int> &userGpuTaskAssignment,
- const bool canUseGpuForPme,
+ const gmx_hw_info_t &hardwareInfo,
+ const t_inputrec &inputrec,
+ const gmx_mtop_t &mtop,
const int numRanksPerSimulation,
const int numPmeRanksPerSimulation)
{
// First, exclude all cases where we can't run PME on GPUs.
if ((pmeTarget == TaskTarget::Cpu) ||
!useGpuForNonbonded ||
- !canUseGpuForPme)
+ !pme_gpu_supports_build(nullptr) ||
+ !pme_gpu_supports_hardware(hardwareInfo, nullptr) ||
+ !pme_gpu_supports_input(inputrec, mtop, nullptr))
{
// PME can't run on a GPU. If the user required that, we issue
// an error later.
bool decideWhetherToUseGpusForPme(const bool useGpuForNonbonded,
const TaskTarget pmeTarget,
const std::vector<int> &userGpuTaskAssignment,
- const bool canUseGpuForPme,
+ const gmx_hw_info_t &hardwareInfo,
+ const t_inputrec &inputrec,
+ const gmx_mtop_t &mtop,
const int numRanksPerSimulation,
const int numPmeRanksPerSimulation,
const bool gpusWereDetected)
if (pmeTarget == TaskTarget::Gpu)
{
GMX_THROW(NotImplementedError
- ("The PME on the GPU is only supported when nonbonded interactions run on GPUs also."));
+ ("PME on GPUs is only supported when nonbonded interactions run on GPUs also."));
}
return false;
}
- if (!canUseGpuForPme)
+ std::string message;
+ if (!pme_gpu_supports_build(&message))
{
if (pmeTarget == TaskTarget::Gpu)
{
- // TODO Pass in the inputrec so we can give more help here?
GMX_THROW(NotImplementedError
- ("The input simulation did not use PME in a way that is supported on the GPU."));
+ ("Cannot compute PME interactions on a GPU, because " + message));
+ }
+ return false;
+ }
+ if (!pme_gpu_supports_hardware(hardwareInfo, &message))
+ {
+ if (pmeTarget == TaskTarget::Gpu)
+ {
+ GMX_THROW(NotImplementedError
+ ("Cannot compute PME interactions on a GPU, because " + message));
+ }
+ return false;
+ }
+ if (!pme_gpu_supports_input(inputrec, mtop, &message))
+ {
+ if (pmeTarget == TaskTarget::Gpu)
+ {
+ GMX_THROW(NotImplementedError
+ ("Cannot compute PME interactions on a GPU, because " + message));
}
return false;
}
// Specifying -gputasks requires specifying everything.
if (pmeTarget == TaskTarget::Auto)
{
- GMX_THROW(InconsistentInputError(formatString(g_specifyEverythingFormatString, "all of -nb, -pme, and -ntmpi")));
+ GMX_THROW(InconsistentInputError(formatString(g_specifyEverythingFormatString, "all of -nb, -pme, and -ntmpi"))); // TODO ntmpi?
}
return true;
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2017,2018, by the GROMACS development team, led by
+ * Copyright (c) 2017,2018,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.
#include <vector>
struct gmx_hw_info_t;
+struct gmx_mtop_t;
+struct t_inputrec;
enum class EmulateGpuNonbonded : bool;
* \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] userGpuTaskAssignment The user-specified assignment of GPU tasks to device IDs.
- * \param[in] canUseGpuForPme Whether the form of PME chosen can run on a GPU
+ * \param[in] hardwareInfo Hardware information
+ * \param[in] inputrec The user input
+ * \param[in] mtop Global system topology
* \param[in] numRanksPerSimulation The number of ranks in each simulation.
* \param[in] numPmeRanksPerSimulation The number of PME ranks in each simulation.
*
TaskTarget pmeTarget,
const std::vector<int> &gpuIdsToUse,
const std::vector<int> &userGpuTaskAssignment,
- bool canUseGpuForPme,
+ const gmx_hw_info_t &hardwareInfo,
+ const t_inputrec &inputrec,
+ const gmx_mtop_t &mtop,
int numRanksPerSimulation,
int numPmeRanksPerSimulation);
* \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] userGpuTaskAssignment The user-specified assignment of GPU tasks to device IDs.
- * \param[in] canUseGpuForPme Whether the form of PME chosen can run on a GPU
+ * \param[in] hardwareInfo Hardware information
+ * \param[in] inputrec The user input
+ * \param[in] mtop Global system topology
* \param[in] numRanksPerSimulation The number of ranks in each simulation.
* \param[in] numPmeRanksPerSimulation The number of PME ranks in each simulation.
* \param[in] gpusWereDetected Whether compatible GPUs were detected on any node.
bool decideWhetherToUseGpusForPme(bool useGpuForNonbonded,
TaskTarget pmeTarget,
const std::vector<int> &userGpuTaskAssignment,
- bool canUseGpuForPme,
+ const gmx_hw_info_t &hardwareInfo,
+ const t_inputrec &inputrec,
+ const gmx_mtop_t &mtop,
int numRanksPerSimulation,
int numPmeRanksPerSimulation,
bool gpusWereDetected);
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2015,2016,2017,2018, by the GROMACS development team, led by
+ * Copyright (c) 2015,2016,2017,2018,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.
if (pmeOnGpu)
{
GMX_RELEASE_ASSERT((EEL_PME(inputrec->coulombtype) || EVDW_PME(inputrec->vdwtype)) &&
- pme_gpu_supports_build(*hwinfo, nullptr) && pme_gpu_supports_input(*inputrec, *mtop, nullptr),
+ pme_gpu_supports_build(nullptr) &&
+ pme_gpu_supports_hardware(*hwinfo, 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.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2016,2017,2018, by the GROMACS development team, led by
+ * Copyright (c) 2016,2017,2018,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.
continue;
}
auto modeTargetsPmeOnGpus = (mode.first.find("PmeOnGpu") != std::string::npos);
- if (modeTargetsPmeOnGpus && !pme_gpu_supports_build(*hardwareInfo_, nullptr))
+ if (modeTargetsPmeOnGpus &&
+ !(pme_gpu_supports_build(nullptr) &&
+ pme_gpu_supports_hardware(*hardwareInfo_, nullptr)))
{
// This run mode will cause a fatal error from mdrun when
// it finds an unsuitable device, which is not something