#include "gromacs/gmxlib/network.h"
#include "gromacs/gpu_utils/gpu_utils.h"
#include "gromacs/hardware/hw_info.h"
-#include "gromacs/taskassignment/hardwareassign.h"
#include "gromacs/utility/exceptions.h"
#include "gromacs/utility/loggerbuilder.h"
#include "gromacs/utility/unique_cptr.h"
// Constructing contexts for all compatible GPUs - will be empty on non-GPU builds
TestHardwareContexts gpuContexts;
- const auto compatibleGpus = getCompatibleGpus(hardwareInfo_->gpu_info);
- for (int gpuIndex : compatibleGpus)
+ for (int gpuIndex : hardwareInfo_->compatibleGpus)
{
char stmp[200] = {};
get_gpu_device_info_string(stmp, hardwareInfo_->gpu_info, gpuIndex);
* the research papers on the package. Check out http://www.gromacs.org.
*/
/*! \internal \file
- * \brief Stub functions for non-GPU builds
+ * \brief Function definitions for non-GPU builds
*
* \author Mark Abraham <mark.j.abraham@gmail.com>
*/
#include "gpu_utils.h"
+#include "gromacs/hardware/gpu_hw_info.h"
+
/*! \brief Set allocation functions used by the GPU host
*
* Since GPU support is not configured, there is no host memory to
*nb_alloc = nullptr;
*nb_free = nullptr;
}
+
+//! This function is documented in the header file
+std::vector<int> getCompatibleGpus(const gmx_gpu_info_t & /*gpu_info*/)
+{
+ // There can't be any compatible GPUs
+ return std::vector<int>();
+}
+
+const char *getGpuCompatibilityDescription(const gmx_gpu_info_t & /*gpu_info*/,
+ int /*index*/)
+{
+ return gpu_detect_res_str[egpuNonexistent];
+}
return retval;
}
-bool isGpuCompatible(const gmx_gpu_info_t &gpu_info,
- int index)
+std::vector<int> getCompatibleGpus(const gmx_gpu_info_t &gpu_info)
{
- assert(gpu_info.n_dev == 0 || gpu_info.gpu_dev);
-
- return (index >= gpu_info.n_dev ?
- false :
- gpu_info.gpu_dev[index].stat == egpuCompatible);
+ // Possible minor over-allocation here, but not important for anything
+ std::vector<int> compatibleGpus;
+ compatibleGpus.reserve(gpu_info.n_dev);
+ for (int i = 0; i < gpu_info.n_dev; i++)
+ {
+ assert(gpu_info.gpu_dev);
+ if (gpu_info.gpu_dev[i].stat == egpuCompatible)
+ {
+ compatibleGpus.push_back(i);
+ }
+ }
+ return compatibleGpus;
}
const char *getGpuCompatibilityDescription(const gmx_gpu_info_t &gpu_info,
#include <cstdio>
+#include <vector>
+
#include "gromacs/gpu_utils/gpu_macros.h"
#include "gromacs/utility/basedefinitions.h"
GPU_FUNC_QUALIFIER
int detect_gpus(struct gmx_gpu_info_t *GPU_FUNC_ARGUMENT(gpu_info), char *GPU_FUNC_ARGUMENT(err_str)) GPU_FUNC_TERM_WITH_RETURN(-1)
-/*! \brief Return whether the GPU with given \c index is compatible, ie suitable for use.
+/*! \brief Return a container of the detected GPUs that are compatible.
*
- * \param[in] gpu_info Information about detected GPUs
- * \param[in] index index of GPU to ask about
- * \returns Whether the GPU is compatible.
- */
-GPU_FUNC_QUALIFIER
-bool isGpuCompatible(const gmx_gpu_info_t &GPU_FUNC_ARGUMENT(gpu_info),
- int GPU_FUNC_ARGUMENT(index)) GPU_FUNC_TERM_WITH_RETURN(false)
+ * This function filters the result of the detection for compatible
+ * GPUs, based on the previously run compatibility tests.
+ *
+ * \param[in] gpu_info Information detected about GPUs, including compatibility.
+ * \return vector of IDs of GPUs already recorded as compatible */
+std::vector<int> getCompatibleGpus(const gmx_gpu_info_t &gpu_info);
/*! \brief Return a string describing how compatible the GPU with given \c index is.
*
* \param[in] index index of GPU to ask about
* \returns A null-terminated C string describing the compatibility status, useful for error messages.
*/
-GPU_FUNC_QUALIFIER
const char *getGpuCompatibilityDescription(const gmx_gpu_info_t &GPU_FUNC_ARGUMENT(gpu_info),
- int GPU_FUNC_ARGUMENT(index)) GPU_FUNC_TERM_WITH_RETURN("")
+ int GPU_FUNC_ARGUMENT(index));
/*! \brief Frees the gpu_dev and dev_use array fields of \p gpu_info.
*
}
//! This function is documented in the header file
-bool isGpuCompatible(const gmx_gpu_info_t &gpu_info,
- int index)
+std::vector<int> getCompatibleGpus(const gmx_gpu_info_t &gpu_info)
{
- return (index >= gpu_info.n_dev ?
- false :
- gpu_info.gpu_dev[index].stat == egpuCompatible);
+ // Possible minor over-allocation here, but not important for anything
+ std::vector<int> compatibleGpus;
+ compatibleGpus.reserve(gpu_info.n_dev);
+ for (int i = 0; i < gpu_info.n_dev; i++)
+ {
+ assert(gpu_info.gpu_dev);
+ if (gpu_info.gpu_dev[i].stat == egpuCompatible)
+ {
+ compatibleGpus.push_back(i);
+ }
+ }
+ return compatibleGpus;
}
//! This function is documented in the header file
gmx_detect_gpus(mdlog, cr);
gmx_collect_hardware_mpi(*hwinfo_g->cpuInfo);
+ hwinfo_g->compatibleGpus = getCompatibleGpus(hwinfo_g->gpu_info);
}
/* increase the reference counter */
n_hwinfo++;
#define GMX_HARDWARE_HWINFO_H
#include <string>
+#include <vector>
#include "gromacs/hardware/gpu_hw_info.h"
#include "gromacs/utility/basedefinitions.h"
{
/* Data for our local physical node */
struct gmx_gpu_info_t gpu_info; /* Information about GPUs detected in the system */
+ std::vector<int> compatibleGpus; /* Contains the device IDs of all GPUs that are compatible */
int nthreads_hw_avail; /* Number of hardware threads available; this number
is based on the number of CPUs reported as available
}
}
-std::vector<int> getCompatibleGpus(const gmx_gpu_info_t &gpu_info)
-{
- // Possible minor over-allocation here, but not important for anything
- std::vector<int> compatibleGpus;
- compatibleGpus.reserve(gpu_info.n_dev);
- for (int i = 0; i < gpu_info.n_dev; i++)
- {
- GMX_ASSERT(gpu_info.gpu_dev, "Invalid gpu_info.gpu_dev");
- if (isGpuCompatible(gpu_info, i))
- {
- compatibleGpus.push_back(i);
- }
- }
- return compatibleGpus;
-}
-
std::vector<int> mapPpRanksToGpus(bool rankCanUseGpu,
const t_commrec *cr,
const gmx_gpu_info_t &gpu_info,
+ const std::vector<int> &compatibleGpus,
const gmx_hw_opt_t &hw_opt)
{
std::vector<int> taskAssignment;
return taskAssignment;
}
- auto compatibleGpus = getCompatibleGpus(gpu_info);
if (!hw_opt.gpuIdTaskAssignment.empty())
{
auto userGpuTaskAssignment = parseGpuTaskAssignment(hw_opt.gpuIdTaskAssignment);
*/
std::vector<int> parseGpuTaskAssignment(const std::string &gpuTaskAssignment);
-/*! \brief Filter the compatible GPUs
- *
- * This function filters gpu_info.gpu_dev for compatible GPUs based
- * on the previously run compatibility tests.
- *
- * \param[in] gpu_info Information detected about GPUs, including compatibility
- * \return vector of IDs of GPUs already recorded as compatible */
-std::vector<int> getCompatibleGpus(const gmx_gpu_info_t &gpu_info);
-
/*! \brief Assign PP ranks to valid GPU IDs.
*
* Will return a validated mapping from PP ranks (ie tasks that can
*
* \param[in] rankCanUseGpu Whether this rank can execute a task on a GPU.
* \param[in] cr Communication record.
- * \param[in] gpu_info Information detected about GPUs, including compatibility.
+ * \param[in] gpu_info Information detected about GPUs
+ * \param[in] compatibleGpus Vector of GPUs that are compatible
* \param[in] hw_opt Parallelisation options, including any user-specified GPU task assignment.
*
* \returns A valid GPU selection.
std::vector<int> mapPpRanksToGpus(bool rankCanUseGpu,
const t_commrec *cr,
const gmx_gpu_info_t &gpu_info,
+ const std::vector<int> &compatibleGpus,
const gmx_hw_opt_t &hw_opt);
} // namespace
* or sharing devices on a node, either from the user
* selection, or automatically. */
bool rankCanUseGpu = thisRankHasDuty(cr, DUTY_PP);
- gpuTaskAssignment = mapPpRanksToGpus(rankCanUseGpu, cr, hwinfo->gpu_info, hw_opt);
+ gpuTaskAssignment = mapPpRanksToGpus(rankCanUseGpu, cr, hwinfo->gpu_info, hwinfo->compatibleGpus, hw_opt);
}
reportGpuUsage(mdlog, hwinfo->gpu_info, !hw_opt.gpuIdTaskAssignment.empty(),