From a65fe6e73c0ff06fa1bcfa01b218222136fff240 Mon Sep 17 00:00:00 2001 From: Mark Abraham Date: Mon, 30 Dec 2019 00:08:15 +0100 Subject: [PATCH] Remove use of tuple in LINCS code for GPU implementation GCC 6.4 for POWER9 couldn't compile any form of increasing the size of a vector of tuples that I could think of, so got rid of the tuple. Used some range-based for, rather than explicit indexing plus the (slow) at() function. There's no need to check indices are in range if there are no indices! Change-Id: Ie36a7a6fafe8f6613ec449778cfe2fbf97e02007 --- src/gromacs/mdlib/lincs_cuda.cu | 74 +++++++++++++++++++++++++---------------- 1 file changed, 45 insertions(+), 29 deletions(-) diff --git a/src/gromacs/mdlib/lincs_cuda.cu b/src/gromacs/mdlib/lincs_cuda.cu index 04d7b751b2..fe78390866 100644 --- a/src/gromacs/mdlib/lincs_cuda.cu +++ b/src/gromacs/mdlib/lincs_cuda.cu @@ -547,18 +547,35 @@ LincsCuda::~LincsCuda() } } -/*! \brief Constructs and returns an atom constraint adjacency list - * - * Each constraint will be represented as a tuple, containing index of the second - * constrained atom, index of the constraint and a sign that indicates the order of atoms in - * which they are listed. Sign is needed to compute the mass factors. - */ -static std::vector>> +//! Helper type for discovering coupled constraints +struct AtomsAdjacencyListElement +{ + AtomsAdjacencyListElement(const int indexOfSecondConstrainedAtom, + const int indexOfConstraint, + const int signFactor) : + indexOfSecondConstrainedAtom_(indexOfSecondConstrainedAtom), + indexOfConstraint_(indexOfConstraint), + signFactor_(signFactor) + { + } + //! The index of the other atom constrained to this atom. + int indexOfSecondConstrainedAtom_; + //! The index of this constraint in the container of constraints. + int indexOfConstraint_; + /*! \brief A multiplicative factor that indicates the relative + * order of the atoms in the atom list. + * + * Used for computing the mass factor of this constraint + * relative to any coupled constraints. */ + int signFactor_; +}; +//! Constructs and returns an atom constraint adjacency list +static std::vector> constructAtomsAdjacencyList(const int numAtoms, ArrayRef iatoms) { const int stride = 1 + NRAL(F_CONSTR); const int numConstraints = iatoms.ssize() / stride; - std::vector>> atomsAdjacencyList(numAtoms); + std::vector> atomsAdjacencyList(numAtoms); for (int c = 0; c < numConstraints; c++) { int a1 = iatoms[stride * c + 1]; @@ -567,8 +584,8 @@ constructAtomsAdjacencyList(const int numAtoms, ArrayRef iatoms) // Each constraint will be represented as a tuple, containing index of the second // constrained atom, index of the constraint and a sign that indicates the order of atoms in // which they are listed. Sign is needed to compute the mass factors. - atomsAdjacencyList[a1].push_back(std::make_tuple(a2, c, +1)); - atomsAdjacencyList[a2].push_back(std::make_tuple(a1, c, -1)); + atomsAdjacencyList[a1].emplace_back(a2, c, +1); + atomsAdjacencyList[a2].emplace_back(a1, c, -1); } return atomsAdjacencyList; @@ -594,17 +611,19 @@ constructAtomsAdjacencyList(const int numAtoms, ArrayRef iatoms) */ inline int countCoupled(int a, ArrayRef numCoupledConstraints, - ArrayRef>> atomsAdjacencyList) + ArrayRef> atomsAdjacencyList) { int counted = 0; for (const auto& adjacentAtom : atomsAdjacencyList[a]) { - const int c2 = std::get<1>(adjacentAtom); + const int c2 = adjacentAtom.indexOfConstraint_; if (numCoupledConstraints[c2] == -1) { numCoupledConstraints[c2] = 0; // To indicate we've been here - counted += 1 + countCoupled(std::get<0>(adjacentAtom), numCoupledConstraints, atomsAdjacencyList); + counted += 1 + + countCoupled(adjacentAtom.indexOfSecondConstrainedAtom_, + numCoupledConstraints, atomsAdjacencyList); } } return counted; @@ -628,7 +647,7 @@ inline int countCoupled(int a, */ inline void addWithCoupled(ArrayRef iatoms, const int stride, - ArrayRef>> atomsAdjacencyList, + ArrayRef> atomsAdjacencyList, ArrayRef splitMap, const int c, int* currentMapIndex) @@ -644,7 +663,7 @@ inline void addWithCoupled(ArrayRef const int a1 = iatoms[stride * c + 1 + atomIndexInConstraint]; for (const auto& adjacentAtom : atomsAdjacencyList[a1]) { - const int c2 = std::get<1>(adjacentAtom); + const int c2 = adjacentAtom.indexOfConstraint_; if (c2 != c) { addWithCoupled(iatoms, stride, atomsAdjacencyList, splitMap, c2, currentMapIndex); @@ -663,7 +682,7 @@ inline void addWithCoupled(ArrayRef * numCoupledConstraints vector is also used to keep track if the constrain was already counted. */ static std::vector countNumCoupledConstraints(ArrayRef iatoms, - ArrayRef>> atomsAdjacencyList) + ArrayRef> atomsAdjacencyList) { const int stride = 1 + NRAL(F_CONSTR); const int numConstraints = iatoms.ssize() / stride; @@ -820,21 +839,17 @@ void LincsCuda::set(const t_idef& idef, const t_mdatoms& md) coupledConstraintsCountsHost.at(splitMap.at(c1)) = 0; int c1a1 = iatoms[stride * c1 + 1]; int c1a2 = iatoms[stride * c1 + 2]; - int c2; - int c2a1; - int c2a2; - int sign; - - // Constraints, coupled trough the first atom. - c2a1 = c1a1; - for (unsigned j = 0; j < atomsAdjacencyList.at(c1a1).size(); j++) + // Constraints, coupled through the first atom. + int c2a1 = c1a1; + for (const auto& atomAdjacencyList : atomsAdjacencyList[c1a1]) { - - std::tie(c2a2, c2, sign) = atomsAdjacencyList.at(c1a1).at(j); + int c2 = atomAdjacencyList.indexOfConstraint_; if (c1 != c2) { + int c2a2 = atomAdjacencyList.indexOfSecondConstrainedAtom_; + int sign = atomAdjacencyList.signFactor_; int index = kernelParams_.numConstraintsThreads * coupledConstraintsCountsHost.at(splitMap.at(c1)) + splitMap.at(c1); @@ -854,13 +869,14 @@ void LincsCuda::set(const t_idef& idef, const t_mdatoms& md) // Constraints, coupled through the second atom. c2a1 = c1a2; - for (unsigned j = 0; j < atomsAdjacencyList.at(c1a2).size(); j++) + for (const auto& atomAdjacencyList : atomsAdjacencyList[c1a2]) { - - std::tie(c2a2, c2, sign) = atomsAdjacencyList.at(c1a2).at(j); + int c2 = atomAdjacencyList.indexOfConstraint_; if (c1 != c2) { + int c2a2 = atomAdjacencyList.indexOfSecondConstrainedAtom_; + int sign = atomAdjacencyList.signFactor_; int index = kernelParams_.numConstraintsThreads * coupledConstraintsCountsHost.at(splitMap.at(c1)) + splitMap.at(c1); -- 2.11.4.GIT