Add support for CUDA CC 6.0/6.1
[alexxy/gromacs.git] / src / gromacs / mdlib / nbnxn_cuda / nbnxn_cuda.cu
1 /*
2  * This file is part of the GROMACS molecular simulation package.
3  *
4  * Copyright (c) 2012,2013,2014,2015,2016, by the GROMACS development team, led by
5  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
6  * and including many others, as listed in the AUTHORS file in the
7  * top-level source directory and at http://www.gromacs.org.
8  *
9  * GROMACS is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public License
11  * as published by the Free Software Foundation; either version 2.1
12  * of the License, or (at your option) any later version.
13  *
14  * GROMACS is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with GROMACS; if not, see
21  * http://www.gnu.org/licenses, or write to the Free Software Foundation,
22  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
23  *
24  * If you want to redistribute modifications to GROMACS, please
25  * consider that scientific software is very special. Version
26  * control is crucial - bugs must be traceable. We will be happy to
27  * consider code for inclusion in the official distribution, but
28  * derived work must not be called official GROMACS. Details are found
29  * in the README & COPYING files - if they are missing, get the
30  * official version at http://www.gromacs.org.
31  *
32  * To help us fund GROMACS development, we humbly ask that you cite
33  * the research papers on the package. Check out http://www.gromacs.org.
34  */
35 /*! \file
36  *  \brief Define CUDA implementation of nbnxn_gpu.h
37  *
38  *  \author Szilard Pall <pall.szilard@gmail.com>
39  */
40 #include "gmxpre.h"
41
42 #include "config.h"
43
44 #include <assert.h>
45 #include <stdlib.h>
46
47 #include "gromacs/mdlib/nbnxn_gpu.h"
48
49 #if defined(_MSVC)
50 #include <limits>
51 #endif
52
53 #include <cuda.h>
54
55 #ifdef TMPI_ATOMICS
56 #include "thread_mpi/atomic.h"
57 #endif
58
59 #include "gromacs/gmxlib/cuda_tools/cudautils.cuh"
60 #include "gromacs/legacyheaders/types/force_flags.h"
61 #include "gromacs/legacyheaders/types/simple.h"
62 #include "gromacs/mdlib/nb_verlet.h"
63 #include "gromacs/mdlib/nbnxn_consts.h"
64 #include "gromacs/mdlib/nbnxn_gpu_data_mgmt.h"
65 #include "gromacs/mdlib/nbnxn_pairlist.h"
66 #include "gromacs/pbcutil/ishift.h"
67 #include "gromacs/timing/gpu_timing.h"
68 #include "gromacs/utility/cstringutil.h"
69
70 #include "nbnxn_cuda_types.h"
71
72 /*! Texture reference for LJ C6/C12 parameters; bound to cu_nbparam_t.nbfp */
73 texture<float, 1, cudaReadModeElementType> nbfp_texref;
74
75 /*! Texture reference for LJ-PME parameters; bound to cu_nbparam_t.nbfp_comb */
76 texture<float, 1, cudaReadModeElementType> nbfp_comb_texref;
77
78 /*! Texture reference for Ewald coulomb force table; bound to cu_nbparam_t.coulomb_tab */
79 texture<float, 1, cudaReadModeElementType> coulomb_tab_texref;
80
81 /* Convenience defines */
82 #define NCL_PER_SUPERCL         (NBNXN_GPU_NCLUSTER_PER_SUPERCLUSTER)
83 #define CL_SIZE                 (NBNXN_GPU_CLUSTER_SIZE)
84
85 /***** The kernels come here *****/
86 #include "gromacs/mdlib/nbnxn_cuda/nbnxn_cuda_kernel_utils.cuh"
87
88 /* Top-level kernel generation: will generate through multiple inclusion the
89  * following flavors for all kernels:
90  * - force-only output;
91  * - force and energy output;
92  * - force-only with pair list pruning;
93  * - force and energy output with pair list pruning.
94  */
95 /** Force only **/
96 #include "gromacs/mdlib/nbnxn_cuda/nbnxn_cuda_kernels.cuh"
97 /** Force & energy **/
98 #define CALC_ENERGIES
99 #include "gromacs/mdlib/nbnxn_cuda/nbnxn_cuda_kernels.cuh"
100 #undef CALC_ENERGIES
101
102 /*** Pair-list pruning kernels ***/
103 /** Force only **/
104 #define PRUNE_NBL
105 #include "gromacs/mdlib/nbnxn_cuda/nbnxn_cuda_kernels.cuh"
106 /** Force & energy **/
107 #define CALC_ENERGIES
108 #include "gromacs/mdlib/nbnxn_cuda/nbnxn_cuda_kernels.cuh"
109 #undef CALC_ENERGIES
110 #undef PRUNE_NBL
111
112
113 /*! Nonbonded kernel function pointer type */
114 typedef void (*nbnxn_cu_kfunc_ptr_t)(const cu_atomdata_t,
115                                      const cu_nbparam_t,
116                                      const cu_plist_t,
117                                      bool);
118
119 /*********************************/
120
121 /* XXX always/never run the energy/pruning kernels -- only for benchmarking purposes */
122 static bool always_ener  = (getenv("GMX_GPU_ALWAYS_ENER") != NULL);
123 static bool never_ener   = (getenv("GMX_GPU_NEVER_ENER") != NULL);
124 static bool always_prune = (getenv("GMX_GPU_ALWAYS_PRUNE") != NULL);
125
126
127 /* Bit-pattern used for polling-based GPU synchronization. It is used as a float
128  * and corresponds to having the exponent set to the maximum (127 -- single
129  * precision) and the mantissa to 0.
130  */
131 static unsigned int poll_wait_pattern = (0x7FU << 23);
132
133 /*! Returns the number of blocks to be used for the nonbonded GPU kernel. */
134 static inline int calc_nb_kernel_nblock(int nwork_units, gmx_device_info_t *dinfo)
135 {
136     int max_grid_x_size;
137
138     assert(dinfo);
139     /* CUDA does not accept grid dimension of 0 (which can happen e.g. with an
140        empty domain) and that case should be handled before this point. */
141     assert(nwork_units > 0);
142
143     max_grid_x_size = dinfo->prop.maxGridSize[0];
144
145     /* do we exceed the grid x dimension limit? */
146     if (nwork_units > max_grid_x_size)
147     {
148         gmx_fatal(FARGS, "Watch out, the input system is too large to simulate!\n"
149                   "The number of nonbonded work units (=number of super-clusters) exceeds the"
150                   "maximum grid size in x dimension (%d > %d)!", nwork_units, max_grid_x_size);
151     }
152
153     return nwork_units;
154 }
155
156
157 /* Constant arrays listing all kernel function pointers and enabling selection
158    of a kernel in an elegant manner. */
159
160 /*! Pointers to the non-bonded kernels organized in 2-dim arrays by:
161  *  electrostatics and VDW type.
162  *
163  *  Note that the row- and column-order of function pointers has to match the
164  *  order of corresponding enumerated electrostatics and vdw types, resp.,
165  *  defined in nbnxn_cuda_types.h.
166  */
167
168 /*! Force-only kernel function pointers. */
169 static const nbnxn_cu_kfunc_ptr_t nb_kfunc_noener_noprune_ptr[eelCuNR][evdwCuNR] =
170 {
171     { nbnxn_kernel_ElecCut_VdwLJ_F_cuda,            nbnxn_kernel_ElecCut_VdwLJFsw_F_cuda,            nbnxn_kernel_ElecCut_VdwLJPsw_F_cuda,            nbnxn_kernel_ElecCut_VdwLJEwCombGeom_F_cuda,            nbnxn_kernel_ElecCut_VdwLJEwCombLB_F_cuda            },
172     { nbnxn_kernel_ElecRF_VdwLJ_F_cuda,             nbnxn_kernel_ElecRF_VdwLJFsw_F_cuda,             nbnxn_kernel_ElecRF_VdwLJPsw_F_cuda,             nbnxn_kernel_ElecRF_VdwLJEwCombGeom_F_cuda,             nbnxn_kernel_ElecRF_VdwLJEwCombLB_F_cuda             },
173     { nbnxn_kernel_ElecEwQSTab_VdwLJ_F_cuda,        nbnxn_kernel_ElecEwQSTab_VdwLJFsw_F_cuda,        nbnxn_kernel_ElecEwQSTab_VdwLJPsw_F_cuda,        nbnxn_kernel_ElecEwQSTab_VdwLJEwCombGeom_F_cuda,        nbnxn_kernel_ElecEwQSTab_VdwLJEwCombLB_F_cuda        },
174     { nbnxn_kernel_ElecEwQSTabTwinCut_VdwLJ_F_cuda, nbnxn_kernel_ElecEwQSTabTwinCut_VdwLJFsw_F_cuda, nbnxn_kernel_ElecEwQSTabTwinCut_VdwLJPsw_F_cuda, nbnxn_kernel_ElecEwQSTabTwinCut_VdwLJEwCombGeom_F_cuda, nbnxn_kernel_ElecEwQSTabTwinCut_VdwLJEwCombLB_F_cuda },
175     { nbnxn_kernel_ElecEw_VdwLJ_F_cuda,             nbnxn_kernel_ElecEw_VdwLJFsw_F_cuda,             nbnxn_kernel_ElecEw_VdwLJPsw_F_cuda,             nbnxn_kernel_ElecEw_VdwLJEwCombGeom_F_cuda,             nbnxn_kernel_ElecEw_VdwLJEwCombLB_F_cuda             },
176     { nbnxn_kernel_ElecEwTwinCut_VdwLJ_F_cuda,      nbnxn_kernel_ElecEwTwinCut_VdwLJFsw_F_cuda,      nbnxn_kernel_ElecEwTwinCut_VdwLJPsw_F_cuda,      nbnxn_kernel_ElecEwTwinCut_VdwLJEwCombGeom_F_cuda,      nbnxn_kernel_ElecEwTwinCut_VdwLJEwCombLB_F_cuda      }
177 };
178
179 /*! Force + energy kernel function pointers. */
180 static const nbnxn_cu_kfunc_ptr_t nb_kfunc_ener_noprune_ptr[eelCuNR][evdwCuNR] =
181 {
182     { nbnxn_kernel_ElecCut_VdwLJ_VF_cuda,            nbnxn_kernel_ElecCut_VdwLJFsw_VF_cuda,            nbnxn_kernel_ElecCut_VdwLJPsw_VF_cuda,            nbnxn_kernel_ElecCut_VdwLJEwCombGeom_VF_cuda,            nbnxn_kernel_ElecCut_VdwLJEwCombLB_VF_cuda              },
183     { nbnxn_kernel_ElecRF_VdwLJ_VF_cuda,             nbnxn_kernel_ElecRF_VdwLJFsw_VF_cuda,             nbnxn_kernel_ElecRF_VdwLJPsw_VF_cuda,             nbnxn_kernel_ElecRF_VdwLJEwCombGeom_VF_cuda,             nbnxn_kernel_ElecRF_VdwLJEwCombLB_VF_cuda               },
184     { nbnxn_kernel_ElecEwQSTab_VdwLJ_VF_cuda,        nbnxn_kernel_ElecEwQSTab_VdwLJFsw_VF_cuda,        nbnxn_kernel_ElecEwQSTab_VdwLJPsw_VF_cuda,        nbnxn_kernel_ElecEwQSTab_VdwLJEwCombGeom_VF_cuda,        nbnxn_kernel_ElecEwQSTab_VdwLJEwCombLB_VF_cuda          },
185     { nbnxn_kernel_ElecEwQSTabTwinCut_VdwLJ_VF_cuda, nbnxn_kernel_ElecEwQSTabTwinCut_VdwLJFsw_VF_cuda, nbnxn_kernel_ElecEwQSTabTwinCut_VdwLJPsw_VF_cuda, nbnxn_kernel_ElecEwQSTabTwinCut_VdwLJEwCombGeom_VF_cuda, nbnxn_kernel_ElecEwQSTabTwinCut_VdwLJEwCombLB_VF_cuda     },
186     { nbnxn_kernel_ElecEw_VdwLJ_VF_cuda,             nbnxn_kernel_ElecEw_VdwLJFsw_VF_cuda,             nbnxn_kernel_ElecEw_VdwLJPsw_VF_cuda,             nbnxn_kernel_ElecEw_VdwLJEwCombGeom_VF_cuda,             nbnxn_kernel_ElecEw_VdwLJEwCombLB_VF_cuda               },
187     { nbnxn_kernel_ElecEwTwinCut_VdwLJ_VF_cuda,      nbnxn_kernel_ElecEwTwinCut_VdwLJFsw_VF_cuda,      nbnxn_kernel_ElecEwTwinCut_VdwLJPsw_VF_cuda,      nbnxn_kernel_ElecEwTwinCut_VdwLJEwCombGeom_VF_cuda,      nbnxn_kernel_ElecEwTwinCut_VdwLJEwCombLB_VF_cuda        }
188 };
189
190 /*! Force + pruning kernel function pointers. */
191 static const nbnxn_cu_kfunc_ptr_t nb_kfunc_noener_prune_ptr[eelCuNR][evdwCuNR] =
192 {
193     { nbnxn_kernel_ElecCut_VdwLJ_F_prune_cuda,             nbnxn_kernel_ElecCut_VdwLJFsw_F_prune_cuda,            nbnxn_kernel_ElecCut_VdwLJPsw_F_prune_cuda,            nbnxn_kernel_ElecCut_VdwLJEwCombGeom_F_prune_cuda,            nbnxn_kernel_ElecCut_VdwLJEwCombLB_F_prune_cuda            },
194     { nbnxn_kernel_ElecRF_VdwLJ_F_prune_cuda,              nbnxn_kernel_ElecRF_VdwLJFsw_F_prune_cuda,             nbnxn_kernel_ElecRF_VdwLJPsw_F_prune_cuda,             nbnxn_kernel_ElecRF_VdwLJEwCombGeom_F_prune_cuda,             nbnxn_kernel_ElecRF_VdwLJEwCombLB_F_prune_cuda             },
195     { nbnxn_kernel_ElecEwQSTab_VdwLJ_F_prune_cuda,         nbnxn_kernel_ElecEwQSTab_VdwLJFsw_F_prune_cuda,        nbnxn_kernel_ElecEwQSTab_VdwLJPsw_F_prune_cuda,        nbnxn_kernel_ElecEwQSTab_VdwLJEwCombGeom_F_prune_cuda,        nbnxn_kernel_ElecEwQSTab_VdwLJEwCombLB_F_prune_cuda        },
196     { nbnxn_kernel_ElecEwQSTabTwinCut_VdwLJ_F_prune_cuda,  nbnxn_kernel_ElecEwQSTabTwinCut_VdwLJFsw_F_prune_cuda, nbnxn_kernel_ElecEwQSTabTwinCut_VdwLJPsw_F_prune_cuda, nbnxn_kernel_ElecEwQSTabTwinCut_VdwLJEwCombGeom_F_prune_cuda, nbnxn_kernel_ElecEwQSTabTwinCut_VdwLJEwCombLB_F_prune_cuda },
197     { nbnxn_kernel_ElecEw_VdwLJ_F_prune_cuda,              nbnxn_kernel_ElecEw_VdwLJFsw_F_prune_cuda,             nbnxn_kernel_ElecEw_VdwLJPsw_F_prune_cuda,             nbnxn_kernel_ElecEw_VdwLJEwCombGeom_F_prune_cuda,             nbnxn_kernel_ElecEw_VdwLJEwCombLB_F_prune_cuda             },
198     { nbnxn_kernel_ElecEwTwinCut_VdwLJ_F_prune_cuda,       nbnxn_kernel_ElecEwTwinCut_VdwLJFsw_F_prune_cuda,      nbnxn_kernel_ElecEwTwinCut_VdwLJPsw_F_prune_cuda,      nbnxn_kernel_ElecEwTwinCut_VdwLJEwCombGeom_F_prune_cuda,      nbnxn_kernel_ElecEwTwinCut_VdwLJEwCombLB_F_prune_cuda      }
199 };
200
201 /*! Force + energy + pruning kernel function pointers. */
202 static const nbnxn_cu_kfunc_ptr_t nb_kfunc_ener_prune_ptr[eelCuNR][evdwCuNR] =
203 {
204     { nbnxn_kernel_ElecCut_VdwLJ_VF_prune_cuda,            nbnxn_kernel_ElecCut_VdwLJFsw_VF_prune_cuda,            nbnxn_kernel_ElecCut_VdwLJPsw_VF_prune_cuda,            nbnxn_kernel_ElecCut_VdwLJEwCombGeom_VF_prune_cuda,            nbnxn_kernel_ElecCut_VdwLJEwCombLB_VF_prune_cuda            },
205     { nbnxn_kernel_ElecRF_VdwLJ_VF_prune_cuda,             nbnxn_kernel_ElecRF_VdwLJFsw_VF_prune_cuda,             nbnxn_kernel_ElecRF_VdwLJPsw_VF_prune_cuda,             nbnxn_kernel_ElecRF_VdwLJEwCombGeom_VF_prune_cuda,             nbnxn_kernel_ElecRF_VdwLJEwCombLB_VF_prune_cuda             },
206     { nbnxn_kernel_ElecEwQSTab_VdwLJ_VF_prune_cuda,        nbnxn_kernel_ElecEwQSTab_VdwLJFsw_VF_prune_cuda,        nbnxn_kernel_ElecEwQSTab_VdwLJPsw_VF_prune_cuda,        nbnxn_kernel_ElecEwQSTab_VdwLJEwCombGeom_VF_prune_cuda,        nbnxn_kernel_ElecEwQSTab_VdwLJEwCombLB_VF_prune_cuda        },
207     { nbnxn_kernel_ElecEwQSTabTwinCut_VdwLJ_VF_prune_cuda, nbnxn_kernel_ElecEwQSTabTwinCut_VdwLJFsw_VF_prune_cuda, nbnxn_kernel_ElecEwQSTabTwinCut_VdwLJPsw_VF_prune_cuda, nbnxn_kernel_ElecEwQSTabTwinCut_VdwLJEwCombGeom_VF_prune_cuda, nbnxn_kernel_ElecEwQSTabTwinCut_VdwLJEwCombLB_VF_prune_cuda },
208     { nbnxn_kernel_ElecEw_VdwLJ_VF_prune_cuda,             nbnxn_kernel_ElecEw_VdwLJFsw_VF_prune_cuda,             nbnxn_kernel_ElecEw_VdwLJPsw_VF_prune_cuda,             nbnxn_kernel_ElecEw_VdwLJEwCombGeom_VF_prune_cuda,             nbnxn_kernel_ElecEw_VdwLJEwCombLB_VF_prune_cuda             },
209     { nbnxn_kernel_ElecEwTwinCut_VdwLJ_VF_prune_cuda,      nbnxn_kernel_ElecEwTwinCut_VdwLJFsw_VF_prune_cuda,      nbnxn_kernel_ElecEwTwinCut_VdwLJPsw_VF_prune_cuda,      nbnxn_kernel_ElecEwTwinCut_VdwLJEwCombGeom_VF_prune_cuda,      nbnxn_kernel_ElecEwTwinCut_VdwLJEwCombLB_VF_prune_cuda      }
210 };
211
212 /*! Return a pointer to the kernel version to be executed at the current step. */
213 static inline nbnxn_cu_kfunc_ptr_t select_nbnxn_kernel(int  eeltype,
214                                                        int  evdwtype,
215                                                        bool bDoEne,
216                                                        bool bDoPrune)
217 {
218     nbnxn_cu_kfunc_ptr_t res;
219
220     assert(eeltype < eelCuNR);
221     assert(evdwtype < evdwCuNR);
222
223     if (bDoEne)
224     {
225         if (bDoPrune)
226         {
227             res = nb_kfunc_ener_prune_ptr[eeltype][evdwtype];
228         }
229         else
230         {
231             res = nb_kfunc_ener_noprune_ptr[eeltype][evdwtype];
232         }
233     }
234     else
235     {
236         if (bDoPrune)
237         {
238             res = nb_kfunc_noener_prune_ptr[eeltype][evdwtype];
239         }
240         else
241         {
242             res = nb_kfunc_noener_noprune_ptr[eeltype][evdwtype];
243         }
244     }
245
246     return res;
247 }
248
249 /*! Calculates the amount of shared memory required by the CUDA kernel in use. */
250 static inline int calc_shmem_required(const int num_threads_z, gmx_device_info_t gmx_unused *dinfo)
251 {
252     int shmem;
253
254     assert(dinfo);
255
256     /* size of shmem (force-buffers/xq/atom type preloading) */
257     /* NOTE: with the default kernel on sm3.0 we need shmem only for pre-loading */
258     /* i-atom x+q in shared memory */
259     shmem  = NCL_PER_SUPERCL * CL_SIZE * sizeof(float4);
260     /* cj in shared memory, for each warp separately */
261     shmem += num_threads_z * 2 * NBNXN_GPU_JGROUP_SIZE * sizeof(int);
262     /* CUDA versions below 4.2 won't generate code for sm>=3.0 */
263 #if GMX_CUDA_VERSION >= 4200
264     if (dinfo->prop.major >= 3)
265     {
266         /* i-atom types in shared memory */
267         shmem += NCL_PER_SUPERCL * CL_SIZE * sizeof(int);
268     }
269     if (dinfo->prop.major < 3)
270 #endif
271     {
272         /* force reduction buffers in shared memory */
273         shmem += CL_SIZE * CL_SIZE * 3 * sizeof(float);
274     }
275     return shmem;
276 }
277
278 /*! As we execute nonbonded workload in separate streams, before launching
279    the kernel we need to make sure that he following operations have completed:
280    - atomdata allocation and related H2D transfers (every nstlist step);
281    - pair list H2D transfer (every nstlist step);
282    - shift vector H2D transfer (every nstlist step);
283    - force (+shift force and energy) output clearing (every step).
284
285    These operations are issued in the local stream at the beginning of the step
286    and therefore always complete before the local kernel launch. The non-local
287    kernel is launched after the local on the same device/context hence it is
288    inherently scheduled after the operations in the local stream (including the
289    above "misc_ops") on pre-GK110 devices with single hardware queue, but on later
290    devices with multiple hardware queues the dependency needs to be enforced.
291    We use the misc_ops_and_local_H2D_done event to record the point where
292    the local x+q H2D (and all preceding) tasks are complete and synchronize
293    with this event in the non-local stream before launching the non-bonded kernel.
294  */
295 void nbnxn_gpu_launch_kernel(gmx_nbnxn_cuda_t       *nb,
296                              const nbnxn_atomdata_t *nbatom,
297                              int                     flags,
298                              int                     iloc)
299 {
300     cudaError_t          stat;
301     int                  adat_begin, adat_len; /* local/nonlocal offset and length used for xq and f */
302     /* CUDA kernel launch-related stuff */
303     int                  shmem, nblock;
304     dim3                 dim_block, dim_grid;
305     nbnxn_cu_kfunc_ptr_t nb_kernel = NULL; /* fn pointer to the nonbonded kernel */
306
307     cu_atomdata_t       *adat    = nb->atdat;
308     cu_nbparam_t        *nbp     = nb->nbparam;
309     cu_plist_t          *plist   = nb->plist[iloc];
310     cu_timers_t         *t       = nb->timers;
311     cudaStream_t         stream  = nb->stream[iloc];
312
313     bool                 bCalcEner   = flags & GMX_FORCE_ENERGY;
314     bool                 bCalcFshift = flags & GMX_FORCE_VIRIAL;
315     bool                 bDoTime     = nb->bDoTime;
316
317     /* turn energy calculation always on/off (for debugging/testing only) */
318     bCalcEner = (bCalcEner || always_ener) && !never_ener;
319
320     /* Don't launch the non-local kernel if there is no work to do.
321        Doing the same for the local kernel is more complicated, since the
322        local part of the force array also depends on the non-local kernel.
323        So to avoid complicating the code and to reduce the risk of bugs,
324        we always call the local kernel, the local x+q copy and later (not in
325        this function) the stream wait, local f copyback and the f buffer
326        clearing. All these operations, except for the local interaction kernel,
327        are needed for the non-local interactions. The skip of the local kernel
328        call is taken care of later in this function. */
329     if (iloc == eintNonlocal && plist->nsci == 0)
330     {
331         return;
332     }
333
334     /* calculate the atom data index range based on locality */
335     if (LOCAL_I(iloc))
336     {
337         adat_begin  = 0;
338         adat_len    = adat->natoms_local;
339     }
340     else
341     {
342         adat_begin  = adat->natoms_local;
343         adat_len    = adat->natoms - adat->natoms_local;
344     }
345
346     /* beginning of timed HtoD section */
347     if (bDoTime)
348     {
349         stat = cudaEventRecord(t->start_nb_h2d[iloc], stream);
350         CU_RET_ERR(stat, "cudaEventRecord failed");
351     }
352
353     /* HtoD x, q */
354     cu_copy_H2D_async(adat->xq + adat_begin, nbatom->x + adat_begin * 4,
355                       adat_len * sizeof(*adat->xq), stream);
356
357     /* When we get here all misc operations issues in the local stream as well as
358        the local xq H2D are done,
359        so we record that in the local stream and wait for it in the nonlocal one. */
360     if (nb->bUseTwoStreams)
361     {
362         if (iloc == eintLocal)
363         {
364             stat = cudaEventRecord(nb->misc_ops_and_local_H2D_done, stream);
365             CU_RET_ERR(stat, "cudaEventRecord on misc_ops_and_local_H2D_done failed");
366         }
367         else
368         {
369             stat = cudaStreamWaitEvent(stream, nb->misc_ops_and_local_H2D_done, 0);
370             CU_RET_ERR(stat, "cudaStreamWaitEvent on misc_ops_and_local_H2D_done failed");
371         }
372     }
373
374     if (bDoTime)
375     {
376         stat = cudaEventRecord(t->stop_nb_h2d[iloc], stream);
377         CU_RET_ERR(stat, "cudaEventRecord failed");
378     }
379
380     if (plist->nsci == 0)
381     {
382         /* Don't launch an empty local kernel (not allowed with CUDA) */
383         return;
384     }
385
386     /* beginning of timed nonbonded calculation section */
387     if (bDoTime)
388     {
389         stat = cudaEventRecord(t->start_nb_k[iloc], stream);
390         CU_RET_ERR(stat, "cudaEventRecord failed");
391     }
392
393     /* get the pointer to the kernel flavor we need to use */
394     nb_kernel = select_nbnxn_kernel(nbp->eeltype,
395                                     nbp->vdwtype,
396                                     bCalcEner,
397                                     plist->bDoPrune || always_prune);
398
399     /* Kernel launch config:
400      * - The thread block dimensions match the size of i-clusters, j-clusters,
401      *   and j-cluster concurrency, in x, y, and z, respectively.
402      * - The 1D block-grid contains as many blocks as super-clusters.
403      */
404     int num_threads_z = 1;
405     if ((nb->dev_info->prop.major == 3 && nb->dev_info->prop.minor == 7) ||
406         (nb->dev_info->prop.major == 6 && nb->dev_info->prop.minor == 0))
407     {
408         num_threads_z = 2;
409     }
410     nblock    = calc_nb_kernel_nblock(plist->nsci, nb->dev_info);
411     dim_block = dim3(CL_SIZE, CL_SIZE, num_threads_z);
412     dim_grid  = dim3(nblock, 1, 1);
413     shmem     = calc_shmem_required(num_threads_z, nb->dev_info);
414
415     if (debug)
416     {
417         fprintf(debug, "GPU launch configuration:\n\tThread block: %dx%dx%d\n\t"
418                 "\tGrid: %dx%d\n\t#Super-clusters/clusters: %d/%d (%d)\n"
419                 "\tShMem: %d\n",
420                 dim_block.x, dim_block.y, dim_block.z,
421                 dim_grid.x, dim_grid.y, plist->nsci*NCL_PER_SUPERCL,
422                 NCL_PER_SUPERCL, plist->na_c,
423                 shmem);
424     }
425
426     nb_kernel<<< dim_grid, dim_block, shmem, stream>>> (*adat, *nbp, *plist, bCalcFshift);
427     CU_LAUNCH_ERR("k_calc_nb");
428
429     if (bDoTime)
430     {
431         stat = cudaEventRecord(t->stop_nb_k[iloc], stream);
432         CU_RET_ERR(stat, "cudaEventRecord failed");
433     }
434
435 #if (defined(WIN32) || defined( _WIN32 ))
436     /* Windows: force flushing WDDM queue */
437     stat = cudaStreamQuery(stream);
438 #endif
439 }
440
441 void nbnxn_gpu_launch_cpyback(gmx_nbnxn_cuda_t       *nb,
442                               const nbnxn_atomdata_t *nbatom,
443                               int                     flags,
444                               int                     aloc)
445 {
446     cudaError_t stat;
447     int         adat_begin, adat_len, adat_end; /* local/nonlocal offset and length used for xq and f */
448     int         iloc = -1;
449
450     /* determine interaction locality from atom locality */
451     if (LOCAL_A(aloc))
452     {
453         iloc = eintLocal;
454     }
455     else if (NONLOCAL_A(aloc))
456     {
457         iloc = eintNonlocal;
458     }
459     else
460     {
461         char stmp[STRLEN];
462         sprintf(stmp, "Invalid atom locality passed (%d); valid here is only "
463                 "local (%d) or nonlocal (%d)", aloc, eatLocal, eatNonlocal);
464         gmx_incons(stmp);
465     }
466
467     cu_atomdata_t   *adat    = nb->atdat;
468     cu_timers_t     *t       = nb->timers;
469     bool             bDoTime = nb->bDoTime;
470     cudaStream_t     stream  = nb->stream[iloc];
471
472     bool             bCalcEner   = flags & GMX_FORCE_ENERGY;
473     bool             bCalcFshift = flags & GMX_FORCE_VIRIAL;
474
475     /* don't launch non-local copy-back if there was no non-local work to do */
476     if (iloc == eintNonlocal && nb->plist[iloc]->nsci == 0)
477     {
478         return;
479     }
480
481     /* calculate the atom data index range based on locality */
482     if (LOCAL_A(aloc))
483     {
484         adat_begin  = 0;
485         adat_len    = adat->natoms_local;
486         adat_end    = nb->atdat->natoms_local;
487     }
488     else
489     {
490         adat_begin  = adat->natoms_local;
491         adat_len    = adat->natoms - adat->natoms_local;
492         adat_end    = nb->atdat->natoms;
493     }
494
495     /* beginning of timed D2H section */
496     if (bDoTime)
497     {
498         stat = cudaEventRecord(t->start_nb_d2h[iloc], stream);
499         CU_RET_ERR(stat, "cudaEventRecord failed");
500     }
501
502     if (!nb->bUseStreamSync)
503     {
504         /* For safety reasons set a few (5%) forces to NaN. This way even if the
505            polling "hack" fails with some future NVIDIA driver we'll get a crash. */
506         for (int i = adat_begin; i < 3*adat_end + 2; i += adat_len/20)
507         {
508 #ifdef NAN
509             nbatom->out[0].f[i] = NAN;
510 #else
511 #  ifdef _MSVC
512             if (numeric_limits<float>::has_quiet_NaN)
513             {
514                 nbatom->out[0].f[i] = numeric_limits<float>::quiet_NaN();
515             }
516             else
517 #  endif
518             {
519                 nbatom->out[0].f[i] = GMX_REAL_MAX;
520             }
521 #endif
522         }
523
524         /* Set the last four bytes of the force array to a bit pattern
525            which can't be the result of the force calculation:
526            max exponent (127) and zero mantissa. */
527         *(unsigned int*)&nbatom->out[0].f[adat_end*3 - 1] = poll_wait_pattern;
528     }
529
530     /* With DD the local D2H transfer can only start after the non-local
531        kernel has finished. */
532     if (iloc == eintLocal && nb->bUseTwoStreams)
533     {
534         stat = cudaStreamWaitEvent(stream, nb->nonlocal_done, 0);
535         CU_RET_ERR(stat, "cudaStreamWaitEvent on nonlocal_done failed");
536     }
537
538     /* DtoH f */
539     cu_copy_D2H_async(nbatom->out[0].f + adat_begin * 3, adat->f + adat_begin,
540                       (adat_len)*sizeof(*adat->f), stream);
541
542     /* After the non-local D2H is launched the nonlocal_done event can be
543        recorded which signals that the local D2H can proceed. This event is not
544        placed after the non-local kernel because we want the non-local data
545        back first. */
546     if (iloc == eintNonlocal)
547     {
548         stat = cudaEventRecord(nb->nonlocal_done, stream);
549         CU_RET_ERR(stat, "cudaEventRecord on nonlocal_done failed");
550     }
551
552     /* only transfer energies in the local stream */
553     if (LOCAL_I(iloc))
554     {
555         /* DtoH fshift */
556         if (bCalcFshift)
557         {
558             cu_copy_D2H_async(nb->nbst.fshift, adat->fshift,
559                               SHIFTS * sizeof(*nb->nbst.fshift), stream);
560         }
561
562         /* DtoH energies */
563         if (bCalcEner)
564         {
565             cu_copy_D2H_async(nb->nbst.e_lj, adat->e_lj,
566                               sizeof(*nb->nbst.e_lj), stream);
567             cu_copy_D2H_async(nb->nbst.e_el, adat->e_el,
568                               sizeof(*nb->nbst.e_el), stream);
569         }
570     }
571
572     if (bDoTime)
573     {
574         stat = cudaEventRecord(t->stop_nb_d2h[iloc], stream);
575         CU_RET_ERR(stat, "cudaEventRecord failed");
576     }
577 }
578
579 /* Atomic compare-exchange operation on unsigned values. It is used in
580  * polling wait for the GPU.
581  */
582 static inline bool atomic_cas(volatile unsigned int *ptr,
583                               unsigned int           oldval,
584                               unsigned int           newval)
585 {
586     assert(ptr);
587
588 #ifdef TMPI_ATOMICS
589     return tMPI_Atomic_cas((tMPI_Atomic_t *)ptr, oldval, newval);
590 #else
591     gmx_incons("Atomic operations not available, atomic_cas() should not have been called!");
592     return true;
593 #endif
594 }
595
596 void nbnxn_gpu_wait_for_gpu(gmx_nbnxn_cuda_t *nb,
597                             const nbnxn_atomdata_t *nbatom,
598                             int flags, int aloc,
599                             real *e_lj, real *e_el, rvec *fshift)
600 {
601     /* NOTE:  only implemented for single-precision at this time */
602     cudaError_t            stat;
603     int                    i, adat_end, iloc = -1;
604     volatile unsigned int *poll_word;
605
606     /* determine interaction locality from atom locality */
607     if (LOCAL_A(aloc))
608     {
609         iloc = eintLocal;
610     }
611     else if (NONLOCAL_A(aloc))
612     {
613         iloc = eintNonlocal;
614     }
615     else
616     {
617         char stmp[STRLEN];
618         sprintf(stmp, "Invalid atom locality passed (%d); valid here is only "
619                 "local (%d) or nonlocal (%d)", aloc, eatLocal, eatNonlocal);
620         gmx_incons(stmp);
621     }
622
623     cu_plist_t                 *plist    = nb->plist[iloc];
624     cu_timers_t                *timers   = nb->timers;
625     struct gmx_wallclock_gpu_t *timings  = nb->timings;
626     nb_staging                  nbst     = nb->nbst;
627
628     bool                        bCalcEner   = flags & GMX_FORCE_ENERGY;
629     bool                        bCalcFshift = flags & GMX_FORCE_VIRIAL;
630
631     /* turn energy calculation always on/off (for debugging/testing only) */
632     bCalcEner = (bCalcEner || always_ener) && !never_ener;
633
634     /* Launch wait/update timers & counters, unless doing the non-local phase
635        when there is not actually work to do. This is consistent with
636        nbnxn_cuda_launch_kernel.
637
638        NOTE: if timing with multiple GPUs (streams) becomes possible, the
639        counters could end up being inconsistent due to not being incremented
640        on some of the nodes! */
641     if (iloc == eintNonlocal && nb->plist[iloc]->nsci == 0)
642     {
643         return;
644     }
645
646     /* calculate the atom data index range based on locality */
647     if (LOCAL_A(aloc))
648     {
649         adat_end = nb->atdat->natoms_local;
650     }
651     else
652     {
653         adat_end = nb->atdat->natoms;
654     }
655
656     if (nb->bUseStreamSync)
657     {
658         stat = cudaStreamSynchronize(nb->stream[iloc]);
659         CU_RET_ERR(stat, "cudaStreamSynchronize failed in cu_blockwait_nb");
660     }
661     else
662     {
663         /* Busy-wait until we get the signal pattern set in last byte
664          * of the l/nl float vector. This pattern corresponds to a floating
665          * point number which can't be the result of the force calculation
666          * (maximum, 127 exponent and 0 mantissa).
667          * The polling uses atomic compare-exchange.
668          */
669         poll_word = (volatile unsigned int*)&nbatom->out[0].f[adat_end*3 - 1];
670         while (atomic_cas(poll_word, poll_wait_pattern, poll_wait_pattern))
671         {
672         }
673     }
674
675     /* timing data accumulation */
676     if (nb->bDoTime)
677     {
678         /* only increase counter once (at local F wait) */
679         if (LOCAL_I(iloc))
680         {
681             timings->nb_c++;
682             timings->ktime[plist->bDoPrune ? 1 : 0][bCalcEner ? 1 : 0].c += 1;
683         }
684
685         /* kernel timings */
686         timings->ktime[plist->bDoPrune ? 1 : 0][bCalcEner ? 1 : 0].t +=
687             cu_event_elapsed(timers->start_nb_k[iloc], timers->stop_nb_k[iloc]);
688
689         /* X/q H2D and F D2H timings */
690         timings->nb_h2d_t += cu_event_elapsed(timers->start_nb_h2d[iloc],
691                                               timers->stop_nb_h2d[iloc]);
692         timings->nb_d2h_t += cu_event_elapsed(timers->start_nb_d2h[iloc],
693                                               timers->stop_nb_d2h[iloc]);
694
695         /* only count atdat and pair-list H2D at pair-search step */
696         if (plist->bDoPrune)
697         {
698             /* atdat transfer timing (add only once, at local F wait) */
699             if (LOCAL_A(aloc))
700             {
701                 timings->pl_h2d_c++;
702                 timings->pl_h2d_t += cu_event_elapsed(timers->start_atdat,
703                                                       timers->stop_atdat);
704             }
705
706             timings->pl_h2d_t += cu_event_elapsed(timers->start_pl_h2d[iloc],
707                                                   timers->stop_pl_h2d[iloc]);
708         }
709     }
710
711     /* add up energies and shift forces (only once at local F wait) */
712     if (LOCAL_I(iloc))
713     {
714         if (bCalcEner)
715         {
716             *e_lj += *nbst.e_lj;
717             *e_el += *nbst.e_el;
718         }
719
720         if (bCalcFshift)
721         {
722             for (i = 0; i < SHIFTS; i++)
723             {
724                 fshift[i][0] += nbst.fshift[i].x;
725                 fshift[i][1] += nbst.fshift[i].y;
726                 fshift[i][2] += nbst.fshift[i].z;
727             }
728         }
729     }
730
731     /* turn off pruning (doesn't matter if this is pair-search step or not) */
732     plist->bDoPrune = false;
733 }
734
735 /*! Return the reference to the nbfp texture. */
736 const struct texture<float, 1, cudaReadModeElementType> &nbnxn_cuda_get_nbfp_texref()
737 {
738     return nbfp_texref;
739 }
740
741 /*! Return the reference to the nbfp_comb texture. */
742 const struct texture<float, 1, cudaReadModeElementType> &nbnxn_cuda_get_nbfp_comb_texref()
743 {
744     return nbfp_comb_texref;
745 }
746
747 /*! Return the reference to the coulomb_tab. */
748 const struct texture<float, 1, cudaReadModeElementType> &nbnxn_cuda_get_coulomb_tab_texref()
749 {
750     return coulomb_tab_texref;
751 }
752
753 /*! Set up the cache configuration for the non-bonded kernels,
754  */
755 void nbnxn_cuda_set_cacheconfig(gmx_device_info_t *devinfo)
756 {
757     cudaError_t stat;
758
759     for (int i = 0; i < eelCuNR; i++)
760     {
761         for (int j = 0; j < evdwCuNR; j++)
762         {
763             if (devinfo->prop.major >= 3)
764             {
765                 /* Default kernel on sm 3.x 48/16 kB Shared/L1 */
766                 cudaFuncSetCacheConfig(nb_kfunc_ener_prune_ptr[i][j], cudaFuncCachePreferShared);
767                 cudaFuncSetCacheConfig(nb_kfunc_ener_noprune_ptr[i][j], cudaFuncCachePreferShared);
768                 cudaFuncSetCacheConfig(nb_kfunc_noener_prune_ptr[i][j], cudaFuncCachePreferShared);
769                 stat = cudaFuncSetCacheConfig(nb_kfunc_noener_noprune_ptr[i][j], cudaFuncCachePreferShared);
770             }
771             else
772             {
773                 /* On Fermi prefer L1 gives 2% higher performance */
774                 /* Default kernel on sm_2.x 16/48 kB Shared/L1 */
775                 cudaFuncSetCacheConfig(nb_kfunc_ener_prune_ptr[i][j], cudaFuncCachePreferL1);
776                 cudaFuncSetCacheConfig(nb_kfunc_ener_noprune_ptr[i][j], cudaFuncCachePreferL1);
777                 cudaFuncSetCacheConfig(nb_kfunc_noener_prune_ptr[i][j], cudaFuncCachePreferL1);
778                 stat = cudaFuncSetCacheConfig(nb_kfunc_noener_noprune_ptr[i][j], cudaFuncCachePreferL1);
779             }
780             CU_RET_ERR(stat, "cudaFuncSetCacheConfig failed");
781         }
782     }
783 }