Rename some variables in GPU task assignment and fix their usage
authorArtem Zhmurov <zhmurov@gmail.com>
Wed, 10 Mar 2021 18:34:49 +0000 (18:34 +0000)
committerArtem Zhmurov <zhmurov@gmail.com>
Wed, 10 Mar 2021 18:34:49 +0000 (18:34 +0000)
Some variables are oddly named which causes a confusion. This changes
the naming so that it reflects the meaning of the variables. Also,
fixes a miss0use of one of such variables cause by the bad naming.

Fixes #3980
Fixes #3981

13 files changed:
src/gromacs/hardware/device_management.h
src/gromacs/hardware/device_management_common.cpp
src/gromacs/hardware/hw_info.h
src/gromacs/mdrun/legacymdrunoptions.cpp
src/gromacs/mdrun/legacymdrunoptions.h
src/gromacs/mdrun/runner.cpp
src/gromacs/taskassignment/decidegpuusage.cpp
src/gromacs/taskassignment/decidegpuusage.h
src/gromacs/taskassignment/resourcedivision.cpp
src/gromacs/taskassignment/taskassignment.cpp
src/gromacs/taskassignment/taskassignment.h
src/gromacs/taskassignment/usergpuids.cpp
src/gromacs/taskassignment/usergpuids.h

index 60cb54aacc4f8ce7bf29d6cf3b5610751a0ceba8..138b6f7485c9d8a2129f2e696952bac8ea99d7b1 100644 (file)
@@ -2,7 +2,7 @@
  * 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.
@@ -56,6 +56,7 @@
 #include <string>
 #include <vector>
 
+#include "gromacs/utility/arrayref.h"
 #include "gromacs/utility/basedefinitions.h"
 #include "gromacs/utility/iserializer.h"
 
@@ -153,7 +154,7 @@ getCompatibleDevices(const std::vector<std::unique_ptr<DeviceInformation>>& devi
  *
  * \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
  *
@@ -167,8 +168,8 @@ std::vector<int> getCompatibleDeviceIds(const std::vector<std::unique_ptr<Device
  *
  * \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.
  *
@@ -219,7 +220,7 @@ std::string getDeviceInformationString(const DeviceInformation& deviceInfo);
  * \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.
index 608d9498b1e2d587d7ac2c59551bfaa195bd52ad..ad6cb0026f8ed266f001045bbac7b345649531af 100644 (file)
@@ -2,7 +2,7 @@
  * 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.
@@ -110,7 +110,7 @@ getCompatibleDevices(const std::vector<std::unique_ptr<DeviceInformation>>& devi
     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;
@@ -125,8 +125,8 @@ std::vector<int> getCompatibleDeviceIds(const std::vector<std::unique_ptr<Device
     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(),
@@ -141,7 +141,7 @@ bool deviceIdIsCompatible(const std::vector<std::unique_ptr<DeviceInformation>>&
     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())
index 4d51d955adef28c88cd822041b06d4bd1e1183e1..044c8dd86b47e28eabe4ae4bb9b1cc09f38078b3 100644 (file)
@@ -2,7 +2,7 @@
  * 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.
@@ -134,9 +134,9 @@ struct gmx_hw_opt_t
     //! 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;
 };
index 3ef319dadd421a53b07ad4b3bb4e5e78073d94db..c78f448792c1d8c54a66069444947cce51035f7f 100644 (file)
@@ -3,7 +3,7 @@
  *
  * 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.
@@ -111,17 +111,17 @@ int LegacyMdrunOptions::updateFromCommandLine(int argc, char** argv, ArrayRef<co
         // 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");
@@ -134,7 +134,7 @@ int LegacyMdrunOptions::updateFromCommandLine(int argc, char** argv, ArrayRef<co
             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");
         }
index 97daa7e5481844a804df31b2c200552c49122e8e..95abef6a57f49e4bcdc9e303cf19ce79ded5701d 100644 (file)
@@ -3,7 +3,7 @@
  *
  * 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.
@@ -163,7 +163,7 @@ public:
     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  = "";
 
 
@@ -217,7 +217,7 @@ public:
         { "-gpu_id",
           FALSE,
           etSTR,
-          { &gpuIdsAvailable },
+          { &devicesSelectedByUser },
           "List of unique GPU device IDs available to use" },
         { "-gputasks",
           FALSE,
index 725165f59ef3e1bda76f2f68700d0986e4afec39..05a7239325948736ff713491b597bd6675ad5eea 100644 (file)
@@ -792,8 +792,9 @@ int Mdrunner::mdrunner()
 
     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);
@@ -837,7 +838,7 @@ int Mdrunner::mdrunner()
             auto canUseGpuForNonbonded = buildSupportsNonbondedOnGpu(nullptr);
             useGpuForNonbonded         = decideWhetherToUseGpusForNonbondedWithThreadMpi(
                     nonbondedTarget,
-                    numDevicesToUse,
+                    numAvailableDevices > 0,
                     userGpuTaskAssignment,
                     emulateGpuNonbonded,
                     canUseGpuForNonbonded,
@@ -845,7 +846,7 @@ int Mdrunner::mdrunner()
                     hw_opt.nthreads_tmpi);
             useGpuForPme = decideWhetherToUseGpusForPmeWithThreadMpi(useGpuForNonbonded,
                                                                      pmeTarget,
-                                                                     numDevicesToUse,
+                                                                     numAvailableDevices,
                                                                      userGpuTaskAssignment,
                                                                      *hwinfo_,
                                                                      *inputrec,
@@ -861,7 +862,7 @@ int Mdrunner::mdrunner()
          * correctly. */
         hw_opt.nthreads_tmpi = get_nthreads_mpi(hwinfo_,
                                                 &hw_opt,
-                                                numDevicesToUse,
+                                                numAvailableDevices,
                                                 useGpuForNonbonded,
                                                 useGpuForPme,
                                                 inputrec.get(),
@@ -1301,7 +1302,7 @@ int Mdrunner::mdrunner()
 
     // Produce the task assignment for this rank - done after DD is constructed
     GpuTaskAssignments gpuTaskAssignments = GpuTaskAssignmentsBuilder::build(
-            gpuIdsToUse,
+            availableDevices,
             userGpuTaskAssignment,
             *hwinfo_,
             simulationCommunicator,
@@ -1429,7 +1430,7 @@ int Mdrunner::mdrunner()
     // where appropriate.
     if (!userGpuTaskAssignment.empty())
     {
-        gpuTaskAssignments.logPerformanceHints(mdlog, numDevicesToUse);
+        gpuTaskAssignments.logPerformanceHints(mdlog, numAvailableDevices);
     }
 
     if (PAR(cr))
@@ -1508,7 +1509,7 @@ int Mdrunner::mdrunner()
         && (runScheduleWork.simulationWork.useGpuHaloExchange
             || runScheduleWork.simulationWork.useGpuPmePpCommunication))
     {
-        setupGpuDevicePeerAccess(gpuIdsToUse, mdlog);
+        setupGpuDevicePeerAccess(gpuTaskAssignments.deviceIdsAssigned(), mdlog);
     }
 
     if (hw_opt.threadAffinity != ThreadAffinity::Off)
index ba2e3563c8149dbd15ee08fe010608737041634c..b4d02f8213f26135a945c87a2f1fd6d96166648c 100644 (file)
@@ -112,7 +112,7 @@ const char* g_specifyEverythingFormatString =
 } // namespace
 
 bool decideWhetherToUseGpusForNonbondedWithThreadMpi(const TaskTarget        nonbondedTarget,
-                                                     const int               numDevicesToUse,
+                                                     const bool              haveAvailableDevices,
                                                      const std::vector<int>& userGpuTaskAssignment,
                                                      const EmulateGpuNonbonded emulateGpuNonbonded,
                                                      const bool buildSupportsNonbondedOnGpu,
@@ -149,7 +149,7 @@ bool decideWhetherToUseGpusForNonbondedWithThreadMpi(const TaskTarget        non
     // 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,
index 765636c448dec7cb1f69c683270c0bfc1b3322f6..d660da7f113a9130dcd08bf6a83a0caf3ea7f4b5 100644 (file)
@@ -103,8 +103,7 @@ class MDAtoms;
  *
  * \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.
@@ -118,7 +117,7 @@ class MDAtoms;
  * \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,
index c2a9e618812d8ada49cc13acda09aa4aa16495f3..03c80d89e69ef8a6cb9e1afdbe945c6be8060861 100644 (file)
@@ -681,7 +681,7 @@ static void print_hw_opt(FILE* fp, const gmx_hw_opt_t* hw_opt)
             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());
 }
 
index bcfce0e0ecf9f7430a0257521244005a67eb1edd..a9256ba27c97162ed6202bef6b0743eeb4d5ba5c 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * 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.
@@ -154,9 +154,9 @@ bool isAnyGpuSharedBetweenRanks(ArrayRef<const GpuTaskAssignment> gpuTaskAssignm
 
 } // 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
@@ -234,10 +234,10 @@ void barrierOverAllRanks(MPI_Comm comm)
 
 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,
@@ -249,7 +249,7 @@ GpuTaskAssignments GpuTaskAssignmentsBuilder::build(const std::vector<int>& gpuI
                                                     bool       rankHasPmeTask)
 {
     size_t               numRanksOnThisNode = physicalNodeComm.size_;
-    std::vector<GpuTask> gpuTasksOnThisRank = findGpuTasksOnThisRank(!gpuIdsToUse.empty(),
+    std::vector<GpuTask> gpuTasksOnThisRank = findGpuTasksOnThisRank(!availableDevices.empty(),
                                                                      nonbondedTarget,
                                                                      pmeTarget,
                                                                      bondedTarget,
@@ -265,6 +265,7 @@ GpuTaskAssignments GpuTaskAssignmentsBuilder::build(const std::vector<int>& gpuI
 
     std::exception_ptr             exceptionPtr;
     std::vector<GpuTaskAssignment> taskAssignmentOnRanksOfThisNode;
+    std::vector<int>               deviceIdsAssigned;
     try
     {
         // Use the GPU IDs from the user if they supplied
@@ -283,11 +284,10 @@ GpuTaskAssignments GpuTaskAssignmentsBuilder::build(const std::vector<int>& gpuI
         // 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())
@@ -301,8 +301,8 @@ GpuTaskAssignments GpuTaskAssignmentsBuilder::build(const std::vector<int>& gpuI
             // 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.
@@ -318,9 +318,9 @@ GpuTaskAssignments GpuTaskAssignmentsBuilder::build(const std::vector<int>& gpuI
                         "perhaps after measuring the performance you can get.",
                         numGpuTasksOnThisNode,
                         host,
-                        gpuIdsToUse.size())));
+                        availableDevices.size())));
             }
-            gpuIdsForTaskAssignment = generatedGpuIds;
+            deviceIdsAssigned = generatedGpuIds;
         }
         else
         {
@@ -340,12 +340,12 @@ GpuTaskAssignments GpuTaskAssignmentsBuilder::build(const std::vector<int>& gpuI
                         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 (...)
     {
@@ -392,6 +392,7 @@ GpuTaskAssignments GpuTaskAssignmentsBuilder::build(const std::vector<int>& gpuI
     gpuTaskAssignments.indexOfThisRank_                 = physicalNodeComm.rank_;
     gpuTaskAssignments.numGpuTasksOnThisNode_           = numGpuTasksOnThisNode;
     gpuTaskAssignments.numRanksOnThisNode_              = numRanksOnThisNode;
+    gpuTaskAssignments.deviceIdsAssigned_               = deviceIdsAssigned;
     return gpuTaskAssignments;
 }
 
index f709f24e4067e0a6813bc36bb9266ec03a297f0d..63cf9c54ff35c243df80a86e5f619f0147fa6a70 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * 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.
@@ -52,6 +52,7 @@
 
 #include <vector>
 
+#include "gromacs/utility/arrayref.h"
 #include "gromacs/utility/basedefinitions.h"
 #include "gromacs/utility/gmxmpi.h"
 
@@ -140,7 +141,7 @@ public:
      * 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
@@ -159,8 +160,8 @@ public:
      * \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,
@@ -210,6 +211,9 @@ private:
     //! 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.
@@ -235,10 +239,11 @@ public:
      * 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.
@@ -251,6 +256,8 @@ public:
     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
index 881d3eea86d2a5eec5e61d1ae7ba18f9796fec5a..0162f2eb4fe10f335b61edb9f520c32e3f0b6dfb 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * 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.
@@ -136,41 +136,41 @@ std::vector<int> parseUserGpuIdString(const std::string& gpuIdString)
     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)
@@ -209,9 +209,9 @@ std::string makeGpuIdString(const std::vector<int>& gpuIds, int totalNumberOfTas
     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 =
index e85d15bf18d6d446956ffaff249af399b6e00016..c6c89aa5781fccc17ab9923adb1a69ce777e0c2e 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * 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.
@@ -84,24 +84,24 @@ std::vector<int> parseUserGpuIdString(const std::string& gpuIdString);
  * 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.
  *
@@ -172,9 +172,9 @@ std::string makeGpuIdString(const std::vector<int>& gpuIds, int totalNumberOfTas
  * \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