From 4c64cc271fe478c88d4302db6a22bf12a2378ba7 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Szil=C3=A1rd=20P=C3=A1ll?= Date: Fri, 20 Oct 2017 16:37:49 +0200 Subject: [PATCH] Eliminate some OCL/CUDA code code duplication Atom to interaction locality conversion and atom range calculation has been duplicated across the OpenCL and CUDA modules. As an intermediate step this functionality is now gathered in the common header. Change-Id: I55b1b34992621ecebed6dad0978a47553511fc87 --- src/gromacs/mdlib/nbnxn_cuda/nbnxn_cuda.cu | 46 ++---------------- src/gromacs/mdlib/nbnxn_gpu_common.h | 77 ++++++++++++++++++++++++++++++ src/gromacs/mdlib/nbnxn_ocl/nbnxn_ocl.cpp | 47 ++---------------- 3 files changed, 83 insertions(+), 87 deletions(-) diff --git a/src/gromacs/mdlib/nbnxn_cuda/nbnxn_cuda.cu b/src/gromacs/mdlib/nbnxn_cuda/nbnxn_cuda.cu index 3f79587105..0828549918 100644 --- a/src/gromacs/mdlib/nbnxn_cuda/nbnxn_cuda.cu +++ b/src/gromacs/mdlib/nbnxn_cuda/nbnxn_cuda.cu @@ -662,24 +662,9 @@ void nbnxn_gpu_launch_cpyback(gmx_nbnxn_cuda_t *nb, { cudaError_t stat; int adat_begin, adat_len; /* local/nonlocal offset and length used for xq and f */ - int iloc = -1; /* determine interaction locality from atom locality */ - if (LOCAL_A(aloc)) - { - iloc = eintLocal; - } - else if (NONLOCAL_A(aloc)) - { - iloc = eintNonlocal; - } - else - { - char stmp[STRLEN]; - sprintf(stmp, "Invalid atom locality passed (%d); valid here is only " - "local (%d) or nonlocal (%d)", aloc, eatLocal, eatNonlocal); - gmx_incons(stmp); - } + int iloc = gpuAtomToInteractionLocality(aloc); cu_atomdata_t *adat = nb->atdat; cu_timers_t *t = nb->timers; @@ -695,17 +680,7 @@ void nbnxn_gpu_launch_cpyback(gmx_nbnxn_cuda_t *nb, return; } - /* calculate the atom data index range based on locality */ - if (LOCAL_A(aloc)) - { - adat_begin = 0; - adat_len = adat->natoms_local; - } - else - { - adat_begin = adat->natoms_local; - adat_len = adat->natoms - adat->natoms_local; - } + getGpuAtomRange(adat, aloc, adat_begin, adat_len); /* beginning of timed D2H section */ if (bDoTime) @@ -802,24 +777,9 @@ void nbnxn_gpu_wait_for_gpu(gmx_nbnxn_cuda_t *nb, { /* NOTE: only implemented for single-precision at this time */ cudaError_t stat; - int iloc = -1; /* determine interaction locality from atom locality */ - if (LOCAL_A(aloc)) - { - iloc = eintLocal; - } - else if (NONLOCAL_A(aloc)) - { - iloc = eintNonlocal; - } - else - { - char stmp[STRLEN]; - sprintf(stmp, "Invalid atom locality passed (%d); valid here is only " - "local (%d) or nonlocal (%d)", aloc, eatLocal, eatNonlocal); - gmx_incons(stmp); - } + int iloc = gpuAtomToInteractionLocality(aloc); cu_plist_t *plist = nb->plist[iloc]; cu_timers_t *timers = nb->timers; diff --git a/src/gromacs/mdlib/nbnxn_gpu_common.h b/src/gromacs/mdlib/nbnxn_gpu_common.h index 334ee76b29..2b93a015cb 100644 --- a/src/gromacs/mdlib/nbnxn_gpu_common.h +++ b/src/gromacs/mdlib/nbnxn_gpu_common.h @@ -44,6 +44,8 @@ #include "config.h" +#include + #if GMX_GPU == GMX_GPU_CUDA #include "nbnxn_cuda/nbnxn_cuda_types.h" #endif @@ -51,6 +53,8 @@ #if GMX_GPU == GMX_GPU_OPENCL #include "nbnxn_ocl/nbnxn_ocl_types.h" #endif +#include "gromacs/utility/stringutil.h" + /*! \brief An early return condition for empty NB GPU workloads * @@ -65,4 +69,77 @@ static inline bool canSkipWork(const gmx_nbnxn_gpu_t *nb, int iloc) return (iloc == eintNonlocal) && (nb->plist[iloc]->nsci == 0); } +/*! \brief Check that atom locality values are valid for the GPU module. + * + * In the GPU module atom locality "all" is not supported, the local and + * non-local ranges are treated separately. + * + * \param[in] atomLocality atom locality specifier + */ +static inline void validateGpuAtomLocality(int atomLocality) +{ + std::string str = gmx::formatString("Invalid atom locality passed (%d); valid here is only " + "local (%d) or nonlocal (%d)", atomLocality, eatLocal, eatNonlocal); + + GMX_ASSERT(LOCAL_OR_NONLOCAL_A(atomLocality), str.c_str()); +} + +/*! \brief Convert atom locality to interaction locality. + * + * In the current implementation the this is straightforward conversion: + * local to local, non-local to non-local. + * + * \param[in] atomLocality Atom locality specifier + * \returns Interaction locality corresponding to the atom locality passed. + */ +static inline int gpuAtomToInteractionLocality(int atomLocality) +{ + validateGpuAtomLocality(atomLocality); + + /* determine interaction locality from atom locality */ + if (LOCAL_A(atomLocality)) + { + return eintLocal; + } + else if (NONLOCAL_A(atomLocality)) + { + return eintNonlocal; + } + else + { + // can't be reached + assert(false); + return -1; + } +} + +/*! \brief Calculate atom range and return start index and length. + * + * \param[in] atomData Atom descriptor data structure + * \param[in] atomLocality Atom locality specifier + * \param[out] atomRangeBegin Starting index of the atom range in the atom data array. + * \param[out] atomRangeLen Atom range length in the atom data array. + */ +template +static inline void getGpuAtomRange(const AtomDataT *atomData, + int atomLocality, + int &atomRangeBegin, + int &atomRangeLen) +{ + assert(atomData); + validateGpuAtomLocality(atomLocality); + + /* calculate the atom data index range based on locality */ + if (LOCAL_A(atomLocality)) + { + atomRangeBegin = 0; + atomRangeLen = atomData->natoms_local; + } + else + { + atomRangeBegin = atomData->natoms_local; + atomRangeLen = atomData->natoms - atomData->natoms_local; + } +} + #endif diff --git a/src/gromacs/mdlib/nbnxn_ocl/nbnxn_ocl.cpp b/src/gromacs/mdlib/nbnxn_ocl/nbnxn_ocl.cpp index 881688d14f..31f574863b 100644 --- a/src/gromacs/mdlib/nbnxn_ocl/nbnxn_ocl.cpp +++ b/src/gromacs/mdlib/nbnxn_ocl/nbnxn_ocl.cpp @@ -840,25 +840,9 @@ void nbnxn_gpu_launch_cpyback(gmx_nbnxn_ocl_t *nb, { cl_int gmx_unused cl_error; int adat_begin, adat_len; /* local/nonlocal offset and length used for xq and f */ - int iloc = -1; /* determine interaction locality from atom locality */ - if (LOCAL_A(aloc)) - { - iloc = eintLocal; - } - else if (NONLOCAL_A(aloc)) - { - iloc = eintNonlocal; - } - else - { - char stmp[STRLEN]; - sprintf(stmp, "Invalid atom locality passed (%d); valid here is only " - "local (%d) or nonlocal (%d)", aloc, eatLocal, eatNonlocal); - - gmx_incons(stmp); - } + int iloc = gpuAtomToInteractionLocality(aloc); cl_atomdata_t *adat = nb->atdat; cl_timers_t *t = nb->timers; @@ -884,17 +868,7 @@ void nbnxn_gpu_launch_cpyback(gmx_nbnxn_ocl_t *nb, return; } - /* calculate the atom data index range based on locality */ - if (LOCAL_A(aloc)) - { - adat_begin = 0; - adat_len = adat->natoms_local; - } - else - { - adat_begin = adat->natoms_local; - adat_len = adat->natoms - adat->natoms_local; - } + getGpuAtomRange(adat, aloc, adat_begin, adat_len); /* beginning of timed D2H section */ if (bDoTime) @@ -1005,24 +979,9 @@ void nbnxn_gpu_wait_for_gpu(gmx_nbnxn_ocl_t *nb, { /* NOTE: only implemented for single-precision at this time */ cl_int gmx_unused cl_error; - int iloc = -1; /* determine interaction locality from atom locality */ - if (LOCAL_A(aloc)) - { - iloc = eintLocal; - } - else if (NONLOCAL_A(aloc)) - { - iloc = eintNonlocal; - } - else - { - char stmp[STRLEN]; - sprintf(stmp, "Invalid atom locality passed (%d); valid here is only " - "local (%d) or nonlocal (%d)", aloc, eatLocal, eatNonlocal); - gmx_incons(stmp); - } + int iloc = gpuAtomToInteractionLocality(aloc); cl_plist_t *plist = nb->plist[iloc]; cl_timers_t *timers = nb->timers; -- 2.11.4.GIT