* This file is part of the GROMACS molecular simulation package.
*
* Copyright (c) 2012,2013,2014,2015,2016, by the GROMACS development team.
- * Copyright (c) 2017,2018,2019,2020, by the GROMACS development team, led by
+ * Copyright (c) 2017,2018,2019,2020,2021, 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 <string>
#include <vector>
+#include "gromacs/utility/arrayref.h"
#include "gromacs/utility/basedefinitions.h"
#include "gromacs/utility/iserializer.h"
*
* \return Vector of compatible GPU ids.
*/
-std::vector<int> getCompatibleDeviceIds(const std::vector<std::unique_ptr<DeviceInformation>>& deviceInfoList);
+std::vector<int> getCompatibleDeviceIds(gmx::ArrayRef<const std::unique_ptr<DeviceInformation>> deviceInfoList);
/*! \brief Return whether \p deviceId is found in \p deviceInfoList and is compatible
*
*
* \return Whether \c deviceId is compatible.
*/
-bool deviceIdIsCompatible(const std::vector<std::unique_ptr<DeviceInformation>>& deviceInfoList,
- int deviceId);
+bool deviceIdIsCompatible(gmx::ArrayRef<const std::unique_ptr<DeviceInformation>> deviceInfoList,
+ int deviceId);
/*! \brief Set the active GPU.
*
* \param[in] deviceId An index of the device to check
* \returns A string describing the compatibility status, useful for error messages.
*/
-std::string getDeviceCompatibilityDescription(const std::vector<std::unique_ptr<DeviceInformation>>& deviceInfoList,
+std::string getDeviceCompatibilityDescription(gmx::ArrayRef<const std::unique_ptr<DeviceInformation>> deviceInfoList,
int deviceId);
/*! \brief Serialization of information on devices for MPI broadcasting.
* This file is part of the GROMACS molecular simulation package.
*
* Copyright (c) 2012,2013,2014,2015,2016, by the GROMACS development team.
- * Copyright (c) 2017,2018,2019,2020, by the GROMACS development team, led by
+ * Copyright (c) 2017,2018,2019,2020,2021, 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.
return compatibleDeviceInfoList;
}
-std::vector<int> getCompatibleDeviceIds(const std::vector<std::unique_ptr<DeviceInformation>>& deviceInfoList)
+std::vector<int> getCompatibleDeviceIds(gmx::ArrayRef<const std::unique_ptr<DeviceInformation>> deviceInfoList)
{
// Possible minor over-allocation here, but not important for anything
std::vector<int> compatibleDeviceIds;
return compatibleDeviceIds;
}
-bool deviceIdIsCompatible(const std::vector<std::unique_ptr<DeviceInformation>>& deviceInfoList,
- const int deviceId)
+bool deviceIdIsCompatible(gmx::ArrayRef<const std::unique_ptr<DeviceInformation>> deviceInfoList,
+ const int deviceId)
{
auto foundIt = std::find_if(deviceInfoList.begin(),
deviceInfoList.end(),
return (*foundIt)->status == DeviceStatus::Compatible;
}
-std::string getDeviceCompatibilityDescription(const std::vector<std::unique_ptr<DeviceInformation>>& deviceInfoList,
+std::string getDeviceCompatibilityDescription(const gmx::ArrayRef<const std::unique_ptr<DeviceInformation>> deviceInfoList,
int deviceId)
{
return (deviceId >= static_cast<int>(deviceInfoList.size())
* This file is part of the GROMACS molecular simulation package.
*
* Copyright (c) 2012,2013,2014,2015,2016 by the GROMACS development team.
- * Copyright (c) 2017,2019,2020, by the GROMACS development team, led by
+ * Copyright (c) 2017,2019,2020,2021, 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.
//! Logical core pinning offset.
int core_pinning_offset = 0;
//! Empty, or a string provided by the user declaring (unique) GPU IDs available for mdrun to use.
- std::string gpuIdsAvailable = "";
+ std::string devicesSelectedByUser;
//! Empty, or a string provided by the user mapping GPU tasks to devices.
- std::string userGpuTaskAssignment = "";
+ std::string userGpuTaskAssignment;
//! Tells whether mdrun is free to choose the total number of threads (by choosing the number of OpenMP and/or thread-MPI threads).
bool totNumThreadsIsAuto;
};
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2011-2019,2020, by the GROMACS development team, led by
+ * Copyright (c) 2011-2019,2020,2021, 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.
// fix that by changing the parsing, once more of the roles of
// handling, validating and implementing defaults for user
// command-line options have been seperated.
- hw_opt.gpuIdsAvailable = gpuIdsAvailable;
+ hw_opt.devicesSelectedByUser = devicesSelectedByUser;
hw_opt.userGpuTaskAssignment = userGpuTaskAssignment;
const char* env = getenv("GMX_GPU_ID");
if (env != nullptr)
{
- if (!hw_opt.gpuIdsAvailable.empty())
+ if (!hw_opt.devicesSelectedByUser.empty())
{
gmx_fatal(FARGS, "GMX_GPU_ID and -gpu_id can not be used at the same time");
}
- hw_opt.gpuIdsAvailable = env;
+ hw_opt.devicesSelectedByUser = env;
}
env = getenv("GMX_GPUTASKS");
hw_opt.userGpuTaskAssignment = env;
}
- if (!hw_opt.gpuIdsAvailable.empty() && !hw_opt.userGpuTaskAssignment.empty())
+ if (!hw_opt.devicesSelectedByUser.empty() && !hw_opt.userGpuTaskAssignment.empty())
{
gmx_fatal(FARGS, "-gpu_id and -gputasks cannot be used at the same time");
}
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2011-2020, by the GROMACS development team, led by
+ * Copyright (c) 2011-2020,2021, 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.
const char* pme_fft_opt_choices[5] = { nullptr, "auto", "cpu", "gpu", nullptr };
const char* bonded_opt_choices[5] = { nullptr, "auto", "cpu", "gpu", nullptr };
const char* update_opt_choices[5] = { nullptr, "auto", "cpu", "gpu", nullptr };
- const char* gpuIdsAvailable = "";
+ const char* devicesSelectedByUser = "";
const char* userGpuTaskAssignment = "";
{ "-gpu_id",
FALSE,
etSTR,
- { &gpuIdsAvailable },
+ { &devicesSelectedByUser },
"List of unique GPU device IDs available to use" },
{ "-gputasks",
FALSE,
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);
+ std::vector<int> availableDevices =
+ makeListOfAvailableDevices(hwinfo_->deviceInfoList, hw_opt.devicesSelectedByUser);
+ const int numAvailableDevices = gmx::ssize(availableDevices);
// Print citation requests after all software/hardware printing
pleaseCiteGromacs(fplog);
auto canUseGpuForNonbonded = buildSupportsNonbondedOnGpu(nullptr);
useGpuForNonbonded = decideWhetherToUseGpusForNonbondedWithThreadMpi(
nonbondedTarget,
- numDevicesToUse,
+ numAvailableDevices > 0,
userGpuTaskAssignment,
emulateGpuNonbonded,
canUseGpuForNonbonded,
hw_opt.nthreads_tmpi);
useGpuForPme = decideWhetherToUseGpusForPmeWithThreadMpi(useGpuForNonbonded,
pmeTarget,
- numDevicesToUse,
+ numAvailableDevices,
userGpuTaskAssignment,
*hwinfo_,
*inputrec,
* correctly. */
hw_opt.nthreads_tmpi = get_nthreads_mpi(hwinfo_,
&hw_opt,
- numDevicesToUse,
+ numAvailableDevices,
useGpuForNonbonded,
useGpuForPme,
inputrec.get(),
// Produce the task assignment for this rank - done after DD is constructed
GpuTaskAssignments gpuTaskAssignments = GpuTaskAssignmentsBuilder::build(
- gpuIdsToUse,
+ availableDevices,
userGpuTaskAssignment,
*hwinfo_,
simulationCommunicator,
// where appropriate.
if (!userGpuTaskAssignment.empty())
{
- gpuTaskAssignments.logPerformanceHints(mdlog, numDevicesToUse);
+ gpuTaskAssignments.logPerformanceHints(mdlog, numAvailableDevices);
}
if (PAR(cr))
&& (runScheduleWork.simulationWork.useGpuHaloExchange
|| runScheduleWork.simulationWork.useGpuPmePpCommunication))
{
- setupGpuDevicePeerAccess(gpuIdsToUse, mdlog);
+ setupGpuDevicePeerAccess(gpuTaskAssignments.deviceIdsAssigned(), mdlog);
}
if (hw_opt.threadAffinity != ThreadAffinity::Off)
} // namespace
bool decideWhetherToUseGpusForNonbondedWithThreadMpi(const TaskTarget nonbondedTarget,
- const int numDevicesToUse,
+ const bool haveAvailableDevices,
const std::vector<int>& userGpuTaskAssignment,
const EmulateGpuNonbonded emulateGpuNonbonded,
const bool buildSupportsNonbondedOnGpu,
// all potential ranks can use, and can use that in a global
// decision that will later be consistent.
// If we get here, then the user permitted or required GPUs.
- return (numDevicesToUse > 0);
+ return haveAvailableDevices;
}
bool decideWhetherToUseGpusForPmeWithThreadMpi(const bool useGpuForNonbonded,
*
* \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] haveAvailableDevices Whether there are available devices.
* \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.
* \throws std::bad_alloc If out of memory
* InconsistentInputError If the user requirements are inconsistent. */
bool decideWhetherToUseGpusForNonbondedWithThreadMpi(TaskTarget nonbondedTarget,
- int numDevicesToUse,
+ bool haveAvailableDevices,
const std::vector<int>& userGpuTaskAssignment,
EmulateGpuNonbonded emulateGpuNonbonded,
bool buildSupportsNonbondedOnGpu,
hw_opt->nthreads_tmpi,
hw_opt->nthreads_omp,
hw_opt->nthreads_omp_pme,
- hw_opt->gpuIdsAvailable.c_str(),
+ hw_opt->devicesSelectedByUser.c_str(),
hw_opt->userGpuTaskAssignment.c_str());
}
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2017,2018,2019,2020, by the GROMACS development team, led by
+ * Copyright (c) 2017,2018,2019,2020,2021, 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.
} // namespace
-void GpuTaskAssignments::logPerformanceHints(const MDLogger& mdlog, size_t numCompatibleGpusOnThisNode)
+void GpuTaskAssignments::logPerformanceHints(const MDLogger& mdlog, size_t numAvailableDevicesOnThisNode)
{
- if (numCompatibleGpusOnThisNode > numGpuTasksOnThisNode_)
+ if (numAvailableDevicesOnThisNode > numGpuTasksOnThisNode_)
{
/* TODO In principle, this warning could be warranted only on
* some nodes, but we lack the infrastructure to do a good job
GpuTaskAssignmentsBuilder::GpuTaskAssignmentsBuilder() = default;
-GpuTaskAssignments GpuTaskAssignmentsBuilder::build(const std::vector<int>& gpuIdsToUse,
- const std::vector<int>& userGpuTaskAssignment,
- const gmx_hw_info_t& hardwareInfo,
- MPI_Comm gromacsWorldComm,
+GpuTaskAssignments GpuTaskAssignmentsBuilder::build(const gmx::ArrayRef<const int> availableDevices,
+ const gmx::ArrayRef<const int> userGpuTaskAssignment,
+ const gmx_hw_info_t& hardwareInfo,
+ MPI_Comm gromacsWorldComm,
const PhysicalNodeCommunicator& physicalNodeComm,
const TaskTarget nonbondedTarget,
const TaskTarget pmeTarget,
bool rankHasPmeTask)
{
size_t numRanksOnThisNode = physicalNodeComm.size_;
- std::vector<GpuTask> gpuTasksOnThisRank = findGpuTasksOnThisRank(!gpuIdsToUse.empty(),
+ std::vector<GpuTask> gpuTasksOnThisRank = findGpuTasksOnThisRank(!availableDevices.empty(),
nonbondedTarget,
pmeTarget,
bondedTarget,
std::exception_ptr exceptionPtr;
std::vector<GpuTaskAssignment> taskAssignmentOnRanksOfThisNode;
+ std::vector<int> deviceIdsAssigned;
try
{
// Use the GPU IDs from the user if they supplied
// runtime, and subject to environment modification such as
// with CUDA_VISIBLE_DEVICES) that will be used for the
// GPU-suitable tasks on all of the ranks of that node.
- ArrayRef<const int> gpuIdsForTaskAssignment;
- std::vector<int> generatedGpuIds;
+ std::vector<int> generatedGpuIds;
if (userGpuTaskAssignment.empty())
{
- ArrayRef<const int> compatibleGpusToUse = gpuIdsToUse;
+ ArrayRef<const int> compatibleGpusToUse = availableDevices;
// enforce the single device/rank restriction
if (numRanksOnThisNode == 1 && !compatibleGpusToUse.empty())
// but we don't have any way to do a better job reliably.
generatedGpuIds = makeGpuIds(compatibleGpusToUse, numGpuTasksOnThisNode);
- if ((numGpuTasksOnThisNode > gpuIdsToUse.size())
- && (numGpuTasksOnThisNode % gpuIdsToUse.size() != 0))
+ if ((numGpuTasksOnThisNode > availableDevices.size())
+ && (numGpuTasksOnThisNode % availableDevices.size() != 0))
{
// TODO Decorating the message with hostname should be
// the job of an error-reporting module.
"perhaps after measuring the performance you can get.",
numGpuTasksOnThisNode,
host,
- gpuIdsToUse.size())));
+ availableDevices.size())));
}
- gpuIdsForTaskAssignment = generatedGpuIds;
+ deviceIdsAssigned = generatedGpuIds;
}
else
{
numGpuTasksOnThisNode)));
}
// Did the user choose compatible GPUs?
- checkUserGpuIds(hardwareInfo.deviceInfoList, gpuIdsToUse, userGpuTaskAssignment);
+ checkUserGpuIds(hardwareInfo.deviceInfoList, availableDevices, userGpuTaskAssignment);
- gpuIdsForTaskAssignment = userGpuTaskAssignment;
+ deviceIdsAssigned = gmx::copyOf(userGpuTaskAssignment);
}
taskAssignmentOnRanksOfThisNode =
- buildTaskAssignment(gpuTasksOnRanksOfThisNode, gpuIdsForTaskAssignment);
+ buildTaskAssignment(gpuTasksOnRanksOfThisNode, deviceIdsAssigned);
}
catch (...)
{
gpuTaskAssignments.indexOfThisRank_ = physicalNodeComm.rank_;
gpuTaskAssignments.numGpuTasksOnThisNode_ = numGpuTasksOnThisNode;
gpuTaskAssignments.numRanksOnThisNode_ = numRanksOnThisNode;
+ gpuTaskAssignments.deviceIdsAssigned_ = deviceIdsAssigned;
return gpuTaskAssignments;
}
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2017,2018,2019,2020, by the GROMACS development team, led by
+ * Copyright (c) 2017,2018,2019,2020,2021, 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>
+#include "gromacs/utility/arrayref.h"
#include "gromacs/utility/basedefinitions.h"
#include "gromacs/utility/gmxmpi.h"
* the ranks of that node. It throws InconsistentInputError
* when a/the useful GPU task assignment is not possible.
*
- * \param[in] gpuIdsToUse The compatible GPUs that the user permitted us to use.
+ * \param[in] availableDevices The compatible devices that the user permitted us to use.
* \param[in] userGpuTaskAssignment The user-specified assignment of GPU tasks to device IDs.
* \param[in] hardwareInfo The detected hardware
* \param[in] gromacsWorldComm MPI communicator for all ranks in the current GROMACS run
* \throws std::bad_alloc If out of memory.
* InconsistentInputError If user and/or detected inputs are inconsistent.
*/
- static GpuTaskAssignments build(const std::vector<int>& gpuIdsToUse,
- const std::vector<int>& userGpuTaskAssignment,
+ static GpuTaskAssignments build(ArrayRef<const int> availableDevices,
+ ArrayRef<const int> userGpuTaskAssignment,
const gmx_hw_info_t& hardwareInfo,
MPI_Comm gromacsWorldComm,
const PhysicalNodeCommunicator& physicalNodeComm,
//! Number of ranks on this physical node.
size_t numRanksOnThisNode_ = 0;
+ //! Vector of device IDs assigned to this node
+ std::vector<int> deviceIdsAssigned_;
+
public:
/*! \brief Log a report on how GPUs are being used on
* the ranks of the physical node of rank 0 of the simulation.
* learn how to let mdrun make a task assignment that runs
* faster.
*
- * \param[in] mdlog Logging object.
- * \param[in] numCompatibleGpusOnThisNode The number of compatible GPUs on this node.
+ * \param[in] mdlog Logging object.
+ * \param[in] numAvailableDevicesOnThisNode The number of compatible devices on this node
+ * that the user permitted us to use.
* */
- void logPerformanceHints(const MDLogger& mdlog, size_t numCompatibleGpusOnThisNode);
+ void logPerformanceHints(const MDLogger& mdlog, size_t numAvailableDevicesOnThisNode);
/*! \brief Return handle to the initialized GPU to use in the this rank.
*
* \param[out] deviceId Index of the assigned device.
bool thisRankHasPmeGpuTask() const;
//! Return whether this rank has any task running on a GPU
bool thisRankHasAnyGpuTask() const;
+ //! Get the list of devices assigned to this node
+ std::vector<int> deviceIdsAssigned() { return deviceIdsAssigned_; }
};
} // namespace gmx
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2017,2018,2019,2020, by the GROMACS development team, led by
+ * Copyright (c) 2017,2018,2019,2020,2021, 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.
return digits;
}
-std::vector<int> makeGpuIdsToUse(const std::vector<std::unique_ptr<DeviceInformation>>& deviceInfoList,
- const std::string& gpuIdsAvailableString)
+std::vector<int> makeListOfAvailableDevices(gmx::ArrayRef<const std::unique_ptr<DeviceInformation>> deviceInfoList,
+ const std::string& devicesSelectedByUserString)
{
- std::vector<int> gpuIdsAvailable = parseUserGpuIdString(gpuIdsAvailableString);
+ std::vector<int> devicesSelectedByUser = parseUserGpuIdString(devicesSelectedByUserString);
- if (gpuIdsAvailable.empty())
+ if (devicesSelectedByUser.empty())
{
- // The user didn't restrict the choice, so we use all compatible GPUs
+ // The user didn't restrict the choice, so we use all compatible devices.
return getCompatibleDeviceIds(deviceInfoList);
}
- std::vector<int> gpuIdsToUse;
- gpuIdsToUse.reserve(gpuIdsAvailable.size());
- std::vector<int> availableGpuIdsThatAreIncompatible;
- for (const int& availableGpuId : gpuIdsAvailable)
+ std::vector<int> availableDevices;
+ availableDevices.reserve(devicesSelectedByUser.size());
+ std::vector<int> incompatibleDevicesSelectedByUser;
+ for (const int& selectedDeviceId : devicesSelectedByUser)
{
- if (deviceIdIsCompatible(deviceInfoList, availableGpuId))
+ if (deviceIdIsCompatible(deviceInfoList, selectedDeviceId))
{
- gpuIdsToUse.push_back(availableGpuId);
+ availableDevices.push_back(selectedDeviceId);
}
else
{
- // Prepare data for an error message about all incompatible available GPU IDs.
- availableGpuIdsThatAreIncompatible.push_back(availableGpuId);
+ // Prepare data for an error message about all incompatible devices that were selected by the user.
+ incompatibleDevicesSelectedByUser.push_back(selectedDeviceId);
}
}
- if (!availableGpuIdsThatAreIncompatible.empty())
+ if (!incompatibleDevicesSelectedByUser.empty())
{
- auto message = "You requested mdrun to use GPUs with IDs " + gpuIdsAvailableString
- + ", but that includes the following incompatible GPUs: "
- + formatAndJoin(availableGpuIdsThatAreIncompatible, ",", StringFormatter("%d"))
- + ". Request only compatible GPUs.";
+ auto message = "You requested mdrun to use GPU devices with IDs " + devicesSelectedByUserString
+ + ", but that includes the following incompatible devices: "
+ + formatAndJoin(incompatibleDevicesSelectedByUser, ",", StringFormatter("%d"))
+ + ". Request only compatible devices.";
GMX_THROW(InvalidInputError(message));
}
- return gpuIdsToUse;
+ return availableDevices;
}
std::vector<int> parseUserTaskAssignmentString(const std::string& gpuIdString)
return formatAndJoin(resultGpuIds, ",", StringFormatter("%d"));
}
-void checkUserGpuIds(const std::vector<std::unique_ptr<DeviceInformation>>& deviceInfoList,
- const std::vector<int>& compatibleGpus,
- const std::vector<int>& gpuIds)
+void checkUserGpuIds(const ArrayRef<const std::unique_ptr<DeviceInformation>> deviceInfoList,
+ const ArrayRef<const int> compatibleGpus,
+ const ArrayRef<const int> gpuIds)
{
bool foundIncompatibleGpuIds = false;
std::string message =
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2017,2018,2019,2020, by the GROMACS development team, led by
+ * Copyright (c) 2017,2018,2019,2020,2021, 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.
* all compatible GPUs on this physical node. Otherwise, check the
* user specified compatible GPUs and return their IDs.
*
- * \param[in] deviceInfoList Information on the GPUs on this physical node.
- * \param[in] gpuIdsAvailableString String like "013" or "0,1,3" typically
- * supplied by the user to mdrun -gpu_id.
- * Must contain only unique decimal digits, or only decimal
- * digits separated by comma delimiters. A terminal
- * comma is accceptable (and required to specify a
- * single ID that is larger than 9).
+ * \param[in] deviceInfoList Information on the GPUs on this physical node.
+ * \param[in] devicesSelectedByUserString String like "013" or "0,1,3" typically
+ * supplied by the user to mdrun -gpu_id.
+ * Must contain only unique decimal digits, or only decimal
+ * digits separated by comma delimiters. A terminal
+ * comma is accceptable (and required to specify a
+ * single ID that is larger than 9).
*
* \returns A vector of unique compatible GPU IDs on this physical node.
*
* \throws std::bad_alloc If out of memory.
* InvalidInputError If an invalid character is found (ie not a digit or ',') or if
* identifiers are duplicated in the specifier list.
- * InvalidInputError If gpuIdsAvailableString specifies GPU IDs that are
+ * InvalidInputError If devicesSelectedByUserString specifies IDs of the devices that are
* not compatible.
*/
-std::vector<int> makeGpuIdsToUse(const std::vector<std::unique_ptr<DeviceInformation>>& deviceInfoList,
- const std::string& gpuIdsAvailableString);
+std::vector<int> makeListOfAvailableDevices(gmx::ArrayRef<const std::unique_ptr<DeviceInformation>> deviceInfoList,
+ const std::string& devicesSelectedByUserString);
/*! \brief Parse a GPU ID specifier string into a container describing device ID to task mapping.
*
* \throws std::bad_alloc If out of memory
* InconsistentInputError If the assigned GPUs are not valid
*/
-void checkUserGpuIds(const std::vector<std::unique_ptr<DeviceInformation>>& deviceInfoList,
- const std::vector<int>& compatibleGpus,
- const std::vector<int>& gpuIds);
+void checkUserGpuIds(ArrayRef<const std::unique_ptr<DeviceInformation>> deviceInfoList,
+ ArrayRef<const int> compatibleGpus,
+ ArrayRef<const int> gpuIds);
} // namespace gmx