asize(pa), pa);
/* Check any GPU IDs passed make sense, and fill the data structure for them */
snew(gpu_ids, 1);
- parse_digits_from_plain_string(eligible_gpu_ids, &gpu_ids->n, &gpu_ids->ids);
+ parse_digits_from_string(eligible_gpu_ids, &gpu_ids->n, &gpu_ids->ids);
/* Determine the maximum and minimum number of PME nodes to test,
* the actual list of settings is build in do_the_tests(). */
/* parse GPU IDs if the user passed any */
if (env != NULL)
{
- /* Parse a "plain" GPU ID string which contains a sequence of
- * digits corresponding to GPU IDs; the order will indicate
- * the process/tMPI thread - GPU assignment. */
- parse_digits_from_plain_string(env,
- &gpu_opt->n_dev_use,
- &gpu_opt->dev_use);
+ /* Parse a "plain" or comma-separated GPU ID string which contains a
+ * sequence of digits corresponding to GPU IDs; the order will
+ * indicate the process/tMPI thread - GPU assignment. */
+ parse_digits_from_string(env, &gpu_opt->n_dev_use, &gpu_opt->dev_use);
+
if (!gmx_multiple_gpu_per_node_supported() && 1 < gpu_opt->n_dev_use)
{
gmx_fatal(FARGS, "The %s implementation only supports using exactly one PP rank per node", getGpuImplementationString());
#include <cctype>
#include <cstring>
+#include <sstream>
+#include <string>
+#include <vector>
+
#include "gromacs/utility/basedefinitions.h"
#include "gromacs/utility/fatalerror.h"
#include "gromacs/utility/futil.h"
return buf;
}
+void parse_digits_from_string(const char *digitstring, int *ndigits, int **digitlist)
+{
+ if (strstr(digitstring, ",") != NULL)
+ {
+ parse_digits_from_csv_string(digitstring, ndigits, digitlist);
+ }
+ else
+ {
+ parse_digits_from_plain_string(digitstring, ndigits, digitlist);
+ }
+}
+
void parse_digits_from_plain_string(const char *digitstring, int *ndigits, int **digitlist)
{
int i;
(*digitlist)[i] = digitstring[i] - '0';
}
}
+
+void parse_digits_from_csv_string(const char *digitstring, int *ndigits, int **digitlist)
+{
+ if (NULL == digitstring)
+ {
+ *ndigits = 0;
+ *digitlist = NULL;
+ return;
+ }
+
+ std::vector<int> digits;
+ std::istringstream ss(digitstring);
+ std::string token;
+ while (std::getline(ss, token, ','))
+ {
+ if (token.find_first_not_of("0123456789") != std::string::npos)
+ {
+ gmx_fatal(FARGS, "Invalid token in digit-only string: \"%s\"\n",
+ token.c_str());
+ }
+ int number = static_cast<int>(str_to_int64_t(token.c_str(), NULL));
+ digits.push_back(number);
+ }
+
+ *ndigits = digits.size();
+ snew(*digitlist, *ndigits);
+ for (size_t i = 0; i < digits.size(); i++)
+ {
+ (*digitlist)[i] = digits[i];
+ }
+}
*/
void parse_digits_from_plain_string(const char *digitstring, int *ndigits, int **digitlist);
+/*! \brief Construct an array of digits from a comma separated input string
+ *
+ * \param[in] digitstring String that must contain only digits and commas
+ * \param[out] ndigits Size of return array with the values of the digits
+ * \param[out] digitlist Array of digits found in
+ * digitstring. Allocated by this function
+ * with size *ndigits. Calling code is
+ * responsible for deallocation.
+ *
+ * If digitstring is NULL, then ndigits is set to zero and digitlist
+ * to NULL. If digitstring contains a non digit-or-comma character, a fatal
+ * error results.
+ */
+void parse_digits_from_csv_string(const char *digitstring, int *ndigits, int **digitlist);
+
+/*! \brief Construct an array of digits an input string
+ *
+ *
+ * \param[in] digitstring String that must contain only digits, or only
+ * digits and commas
+ * \param[out] ndigits Size of return array with the values of the digits
+ * \param[out] digitlist Array of digits found in
+ * digitstring. Allocated by this function
+ * with size *ndigits. Calling code is
+ * responsible for deallocation.
+ * If digitstring is NULL, then ndigits is set to zero and digitlist
+ * to NULL. If digitstring contains a non digit-or-comma character, a fatal
+ * error results.
+ */
+void parse_digits_from_string(const char *digitstring, int *ndigits, int **digitlist);
+
#ifdef __cplusplus
}
#endif