Move types/ishift.h to pbcutil/
[alexxy/gromacs.git] / src / gromacs / mdlib / nbnxn_cuda / nbnxn_cuda_data_mgmt.cu
1 /*
2  * This file is part of the GROMACS molecular simulation package.
3  *
4  * Copyright (c) 2012,2013,2014, 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 #ifdef HAVE_CONFIG_H
36 #include <config.h>
37 #endif
38
39 #include <assert.h>
40 #include <stdarg.h>
41 #include <stdlib.h>
42 #include <stdio.h>
43
44 #include <cuda.h>
45
46 #include "tables.h"
47 #include "typedefs.h"
48 #include "types/enums.h"
49 #include "types/nb_verlet.h"
50 #include "types/interaction_const.h"
51 #include "types/force_flags.h"
52 #include "../nbnxn_consts.h"
53 #include "gmx_detect_hardware.h"
54
55 #include "nbnxn_cuda_types.h"
56 #include "../../gmxlib/cuda_tools/cudautils.cuh"
57 #include "nbnxn_cuda_data_mgmt.h"
58 #include "pmalloc_cuda.h"
59 #include "gpu_utils.h"
60
61 #include "gromacs/pbcutil/ishift.h"
62 #include "gromacs/utility/common.h"
63 #include "gromacs/utility/cstringutil.h"
64 #include "gromacs/utility/fatalerror.h"
65 #include "gromacs/utility/smalloc.h"
66
67 static bool bUseCudaEventBlockingSync = false; /* makes the CPU thread block */
68
69 /* This is a heuristically determined parameter for the Fermi architecture for
70  * the minimum size of ci lists by multiplying this constant with the # of
71  * multiprocessors on the current device.
72  */
73 static unsigned int gpu_min_ci_balanced_factor = 40;
74
75 /* Functions from nbnxn_cuda.cu */
76 extern void nbnxn_cuda_set_cacheconfig(cuda_dev_info_t *devinfo);
77 extern const struct texture<float, 1, cudaReadModeElementType> &nbnxn_cuda_get_nbfp_texref();
78 extern const struct texture<float, 1, cudaReadModeElementType> &nbnxn_cuda_get_nbfp_comb_texref();
79 extern const struct texture<float, 1, cudaReadModeElementType> &nbnxn_cuda_get_coulomb_tab_texref();
80
81 /* We should actually be using md_print_warn in md_logging.c,
82  * but we can't include mpi.h in CUDA code.
83  */
84 static void md_print_warn(FILE       *fplog,
85                           const char *fmt, ...)
86 {
87     va_list ap;
88
89     if (fplog != NULL)
90     {
91         /* We should only print to stderr on the master node,
92          * in most cases fplog is only set on the master node, so this works.
93          */
94         va_start(ap, fmt);
95         fprintf(stderr, "\n");
96         vfprintf(stderr, fmt, ap);
97         fprintf(stderr, "\n");
98         va_end(ap);
99
100         va_start(ap, fmt);
101         fprintf(fplog, "\n");
102         vfprintf(fplog, fmt, ap);
103         fprintf(fplog, "\n");
104         va_end(ap);
105     }
106 }
107
108
109 /* Fw. decl. */
110 static void nbnxn_cuda_clear_e_fshift(nbnxn_cuda_ptr_t cu_nb);
111
112
113 /*! Tabulates the Ewald Coulomb force and initializes the size/scale
114     and the table GPU array. If called with an already allocated table,
115     it just re-uploads the table.
116  */
117 static void init_ewald_coulomb_force_table(cu_nbparam_t          *nbp,
118                                            const cuda_dev_info_t *dev_info)
119 {
120     float       *ftmp, *coul_tab;
121     int          tabsize;
122     double       tabscale;
123     cudaError_t  stat;
124
125     tabsize     = GPU_EWALD_COULOMB_FORCE_TABLE_SIZE;
126     /* Subtract 2 iso 1 to avoid access out of range due to rounding */
127     tabscale    = (tabsize - 2) / sqrt(nbp->rcoulomb_sq);
128
129     pmalloc((void**)&ftmp, tabsize*sizeof(*ftmp));
130
131     table_spline3_fill_ewald_lr(ftmp, NULL, NULL, tabsize,
132                                 1/tabscale, nbp->ewald_beta, v_q_ewald_lr);
133
134     /* If the table pointer == NULL the table is generated the first time =>
135        the array pointer will be saved to nbparam and the texture is bound.
136      */
137     coul_tab = nbp->coulomb_tab;
138     if (coul_tab == NULL)
139     {
140         stat = cudaMalloc((void **)&coul_tab, tabsize*sizeof(*coul_tab));
141         CU_RET_ERR(stat, "cudaMalloc failed on coul_tab");
142
143         nbp->coulomb_tab = coul_tab;
144
145 #ifdef TEXOBJ_SUPPORTED
146         /* Only device CC >= 3.0 (Kepler and later) support texture objects */
147         if (dev_info->prop.major >= 3)
148         {
149             cudaResourceDesc rd;
150             memset(&rd, 0, sizeof(rd));
151             rd.resType                  = cudaResourceTypeLinear;
152             rd.res.linear.devPtr        = nbp->coulomb_tab;
153             rd.res.linear.desc.f        = cudaChannelFormatKindFloat;
154             rd.res.linear.desc.x        = 32;
155             rd.res.linear.sizeInBytes   = tabsize*sizeof(*coul_tab);
156
157             cudaTextureDesc td;
158             memset(&td, 0, sizeof(td));
159             td.readMode                 = cudaReadModeElementType;
160             stat = cudaCreateTextureObject(&nbp->coulomb_tab_texobj, &rd, &td, NULL);
161             CU_RET_ERR(stat, "cudaCreateTextureObject on coulomb_tab_texobj failed");
162         }
163         else
164 #endif
165         {
166             GMX_UNUSED_VALUE(dev_info);
167             cudaChannelFormatDesc cd   = cudaCreateChannelDesc<float>();
168             stat = cudaBindTexture(NULL, &nbnxn_cuda_get_coulomb_tab_texref(),
169                                    coul_tab, &cd, tabsize*sizeof(*coul_tab));
170             CU_RET_ERR(stat, "cudaBindTexture on coulomb_tab_texref failed");
171         }
172     }
173
174     cu_copy_H2D(coul_tab, ftmp, tabsize*sizeof(*coul_tab));
175
176     nbp->coulomb_tab_size     = tabsize;
177     nbp->coulomb_tab_scale    = tabscale;
178
179     pfree(ftmp);
180 }
181
182
183 /*! Initializes the atomdata structure first time, it only gets filled at
184     pair-search. */
185 static void init_atomdata_first(cu_atomdata_t *ad, int ntypes)
186 {
187     cudaError_t stat;
188
189     ad->ntypes  = ntypes;
190     stat        = cudaMalloc((void**)&ad->shift_vec, SHIFTS*sizeof(*ad->shift_vec));
191     CU_RET_ERR(stat, "cudaMalloc failed on ad->shift_vec");
192     ad->bShiftVecUploaded = false;
193
194     stat = cudaMalloc((void**)&ad->fshift, SHIFTS*sizeof(*ad->fshift));
195     CU_RET_ERR(stat, "cudaMalloc failed on ad->fshift");
196
197     stat = cudaMalloc((void**)&ad->e_lj, sizeof(*ad->e_lj));
198     CU_RET_ERR(stat, "cudaMalloc failed on ad->e_lj");
199     stat = cudaMalloc((void**)&ad->e_el, sizeof(*ad->e_el));
200     CU_RET_ERR(stat, "cudaMalloc failed on ad->e_el");
201
202     /* initialize to NULL poiters to data that is not allocated here and will
203        need reallocation in nbnxn_cuda_init_atomdata */
204     ad->xq = NULL;
205     ad->f  = NULL;
206
207     /* size -1 indicates that the respective array hasn't been initialized yet */
208     ad->natoms = -1;
209     ad->nalloc = -1;
210 }
211
212 /*! Selects the Ewald kernel type, analytical on SM 3.0 and later, tabulated on
213     earlier GPUs, single or twin cut-off. */
214 static int pick_ewald_kernel_type(bool                   bTwinCut,
215                                   const cuda_dev_info_t *dev_info)
216 {
217     bool bUseAnalyticalEwald, bForceAnalyticalEwald, bForceTabulatedEwald;
218     int  kernel_type;
219
220     /* Benchmarking/development environment variables to force the use of
221        analytical or tabulated Ewald kernel. */
222     bForceAnalyticalEwald = (getenv("GMX_CUDA_NB_ANA_EWALD") != NULL);
223     bForceTabulatedEwald  = (getenv("GMX_CUDA_NB_TAB_EWALD") != NULL);
224
225     if (bForceAnalyticalEwald && bForceTabulatedEwald)
226     {
227         gmx_incons("Both analytical and tabulated Ewald CUDA non-bonded kernels "
228                    "requested through environment variables.");
229     }
230
231     /* By default, on SM 3.0 and later use analytical Ewald, on earlier tabulated. */
232     if ((dev_info->prop.major >= 3 || bForceAnalyticalEwald) && !bForceTabulatedEwald)
233     {
234         bUseAnalyticalEwald = true;
235
236         if (debug)
237         {
238             fprintf(debug, "Using analytical Ewald CUDA kernels\n");
239         }
240     }
241     else
242     {
243         bUseAnalyticalEwald = false;
244
245         if (debug)
246         {
247             fprintf(debug, "Using tabulated Ewald CUDA kernels\n");
248         }
249     }
250
251     /* Use twin cut-off kernels if requested by bTwinCut or the env. var.
252        forces it (use it for debugging/benchmarking only). */
253     if (!bTwinCut && (getenv("GMX_CUDA_NB_EWALD_TWINCUT") == NULL))
254     {
255         kernel_type = bUseAnalyticalEwald ? eelCuEWALD_ANA : eelCuEWALD_TAB;
256     }
257     else
258     {
259         kernel_type = bUseAnalyticalEwald ? eelCuEWALD_ANA_TWIN : eelCuEWALD_TAB_TWIN;
260     }
261
262     return kernel_type;
263 }
264
265 /*! Copies all parameters related to the cut-off from ic to nbp */
266 static void set_cutoff_parameters(cu_nbparam_t              *nbp,
267                                   const interaction_const_t *ic)
268 {
269     nbp->ewald_beta       = ic->ewaldcoeff_q;
270     nbp->sh_ewald         = ic->sh_ewald;
271     nbp->epsfac           = ic->epsfac;
272     nbp->two_k_rf         = 2.0 * ic->k_rf;
273     nbp->c_rf             = ic->c_rf;
274     nbp->rvdw_sq          = ic->rvdw * ic->rvdw;
275     nbp->rcoulomb_sq      = ic->rcoulomb * ic->rcoulomb;
276     nbp->rlist_sq         = ic->rlist * ic->rlist;
277
278     nbp->sh_lj_ewald      = ic->sh_lj_ewald;
279     nbp->ewaldcoeff_lj    = ic->ewaldcoeff_lj;
280
281     nbp->rvdw_switch      = ic->rvdw_switch;
282     nbp->dispersion_shift = ic->dispersion_shift;
283     nbp->repulsion_shift  = ic->repulsion_shift;
284     nbp->vdw_switch       = ic->vdw_switch;
285 }
286
287 /*! Initializes the nonbonded parameter data structure. */
288 static void init_nbparam(cu_nbparam_t              *nbp,
289                          const interaction_const_t *ic,
290                          const nbnxn_atomdata_t    *nbat,
291                          const cuda_dev_info_t     *dev_info)
292 {
293     cudaError_t stat;
294     int         ntypes, nnbfp, nnbfp_comb;
295
296     ntypes  = nbat->ntype;
297
298     set_cutoff_parameters(nbp, ic);
299
300     if (ic->vdwtype == evdwCUT)
301     {
302         switch (ic->vdw_modifier)
303         {
304             case eintmodNONE:
305             case eintmodPOTSHIFT:
306                 nbp->vdwtype = evdwCuCUT;
307                 break;
308             case eintmodFORCESWITCH:
309                 nbp->vdwtype = evdwCuFSWITCH;
310                 break;
311             case eintmodPOTSWITCH:
312                 nbp->vdwtype = evdwCuPSWITCH;
313                 break;
314             default:
315                 gmx_incons("The requested VdW interaction modifier is not implemented in the CUDA GPU accelerated kernels!");
316                 break;
317         }
318     }
319     else if (ic->vdwtype == evdwPME)
320     {
321         if (ic->ljpme_comb_rule == ljcrGEOM)
322         {
323             assert(nbat->comb_rule == ljcrGEOM);
324             nbp->vdwtype = evdwCuEWALDGEOM;
325         }
326         else
327         {
328             assert(nbat->comb_rule == ljcrLB);
329             nbp->vdwtype = evdwCuEWALDLB;
330         }
331     }
332     else
333     {
334         gmx_incons("The requested VdW type is not implemented in the CUDA GPU accelerated kernels!");
335     }
336
337     if (ic->eeltype == eelCUT)
338     {
339         nbp->eeltype = eelCuCUT;
340     }
341     else if (EEL_RF(ic->eeltype))
342     {
343         nbp->eeltype = eelCuRF;
344     }
345     else if ((EEL_PME(ic->eeltype) || ic->eeltype == eelEWALD))
346     {
347         /* Initially rcoulomb == rvdw, so it's surely not twin cut-off. */
348         nbp->eeltype = pick_ewald_kernel_type(false, dev_info);
349     }
350     else
351     {
352         /* Shouldn't happen, as this is checked when choosing Verlet-scheme */
353         gmx_incons("The requested electrostatics type is not implemented in the CUDA GPU accelerated kernels!");
354     }
355
356     /* generate table for PME */
357     nbp->coulomb_tab = NULL;
358     if (nbp->eeltype == eelCuEWALD_TAB || nbp->eeltype == eelCuEWALD_TAB_TWIN)
359     {
360         init_ewald_coulomb_force_table(nbp, dev_info);
361     }
362
363     nnbfp      = 2*ntypes*ntypes;
364     nnbfp_comb = 2*ntypes;
365
366     stat  = cudaMalloc((void **)&nbp->nbfp, nnbfp*sizeof(*nbp->nbfp));
367     CU_RET_ERR(stat, "cudaMalloc failed on nbp->nbfp");
368     cu_copy_H2D(nbp->nbfp, nbat->nbfp, nnbfp*sizeof(*nbp->nbfp));
369
370
371     if (ic->vdwtype == evdwPME)
372     {
373         stat  = cudaMalloc((void **)&nbp->nbfp_comb, nnbfp_comb*sizeof(*nbp->nbfp_comb));
374         CU_RET_ERR(stat, "cudaMalloc failed on nbp->nbfp_comb");
375         cu_copy_H2D(nbp->nbfp_comb, nbat->nbfp_comb, nnbfp_comb*sizeof(*nbp->nbfp_comb));
376     }
377
378 #ifdef TEXOBJ_SUPPORTED
379     /* Only device CC >= 3.0 (Kepler and later) support texture objects */
380     if (dev_info->prop.major >= 3)
381     {
382         cudaResourceDesc rd;
383         cudaTextureDesc  td;
384
385         memset(&rd, 0, sizeof(rd));
386         rd.resType                  = cudaResourceTypeLinear;
387         rd.res.linear.devPtr        = nbp->nbfp;
388         rd.res.linear.desc.f        = cudaChannelFormatKindFloat;
389         rd.res.linear.desc.x        = 32;
390         rd.res.linear.sizeInBytes   = nnbfp*sizeof(*nbp->nbfp);
391
392         memset(&td, 0, sizeof(td));
393         td.readMode                 = cudaReadModeElementType;
394         stat = cudaCreateTextureObject(&nbp->nbfp_texobj, &rd, &td, NULL);
395         CU_RET_ERR(stat, "cudaCreateTextureObject on nbfp_texobj failed");
396
397         if (ic->vdwtype == evdwPME)
398         {
399             memset(&rd, 0, sizeof(rd));
400             rd.resType                  = cudaResourceTypeLinear;
401             rd.res.linear.devPtr        = nbp->nbfp_comb;
402             rd.res.linear.desc.f        = cudaChannelFormatKindFloat;
403             rd.res.linear.desc.x        = 32;
404             rd.res.linear.sizeInBytes   = nnbfp_comb*sizeof(*nbp->nbfp_comb);
405
406             memset(&td, 0, sizeof(td));
407             td.readMode = cudaReadModeElementType;
408             stat        = cudaCreateTextureObject(&nbp->nbfp_comb_texobj, &rd, &td, NULL);
409             CU_RET_ERR(stat, "cudaCreateTextureObject on nbfp_comb_texobj failed");
410         }
411     }
412     else
413 #endif
414     {
415         cudaChannelFormatDesc cd = cudaCreateChannelDesc<float>();
416         stat = cudaBindTexture(NULL, &nbnxn_cuda_get_nbfp_texref(),
417                                nbp->nbfp, &cd, nnbfp*sizeof(*nbp->nbfp));
418         CU_RET_ERR(stat, "cudaBindTexture on nbfp_texref failed");
419
420         if (ic->vdwtype == evdwPME)
421         {
422             stat = cudaBindTexture(NULL, &nbnxn_cuda_get_nbfp_comb_texref(),
423                                    nbp->nbfp_comb, &cd, nnbfp_comb*sizeof(*nbp->nbfp_comb));
424             CU_RET_ERR(stat, "cudaBindTexture on nbfp_comb_texref failed");
425         }
426     }
427 }
428
429 /*! Re-generate the GPU Ewald force table, resets rlist, and update the
430  *  electrostatic type switching to twin cut-off (or back) if needed. */
431 void nbnxn_cuda_pme_loadbal_update_param(nbnxn_cuda_ptr_t           cu_nb,
432                                          const interaction_const_t *ic)
433 {
434     cu_nbparam_t *nbp = cu_nb->nbparam;
435
436     set_cutoff_parameters(nbp, ic);
437
438     nbp->eeltype        = pick_ewald_kernel_type(ic->rcoulomb != ic->rvdw,
439                                                  cu_nb->dev_info);
440
441     init_ewald_coulomb_force_table(cu_nb->nbparam, cu_nb->dev_info);
442 }
443
444 /*! Initializes the pair list data structure. */
445 static void init_plist(cu_plist_t *pl)
446 {
447     /* initialize to NULL pointers to data that is not allocated here and will
448        need reallocation in nbnxn_cuda_init_pairlist */
449     pl->sci     = NULL;
450     pl->cj4     = NULL;
451     pl->excl    = NULL;
452
453     /* size -1 indicates that the respective array hasn't been initialized yet */
454     pl->na_c        = -1;
455     pl->nsci        = -1;
456     pl->sci_nalloc  = -1;
457     pl->ncj4        = -1;
458     pl->cj4_nalloc  = -1;
459     pl->nexcl       = -1;
460     pl->excl_nalloc = -1;
461     pl->bDoPrune    = false;
462 }
463
464 /*! Initializes the timer data structure. */
465 static void init_timers(cu_timers_t *t, bool bUseTwoStreams)
466 {
467     cudaError_t stat;
468     int         eventflags = ( bUseCudaEventBlockingSync ? cudaEventBlockingSync : cudaEventDefault );
469
470     stat = cudaEventCreateWithFlags(&(t->start_atdat), eventflags);
471     CU_RET_ERR(stat, "cudaEventCreate on start_atdat failed");
472     stat = cudaEventCreateWithFlags(&(t->stop_atdat), eventflags);
473     CU_RET_ERR(stat, "cudaEventCreate on stop_atdat failed");
474
475     /* The non-local counters/stream (second in the array) are needed only with DD. */
476     for (int i = 0; i <= (bUseTwoStreams ? 1 : 0); i++)
477     {
478         stat = cudaEventCreateWithFlags(&(t->start_nb_k[i]), eventflags);
479         CU_RET_ERR(stat, "cudaEventCreate on start_nb_k failed");
480         stat = cudaEventCreateWithFlags(&(t->stop_nb_k[i]), eventflags);
481         CU_RET_ERR(stat, "cudaEventCreate on stop_nb_k failed");
482
483
484         stat = cudaEventCreateWithFlags(&(t->start_pl_h2d[i]), eventflags);
485         CU_RET_ERR(stat, "cudaEventCreate on start_pl_h2d failed");
486         stat = cudaEventCreateWithFlags(&(t->stop_pl_h2d[i]), eventflags);
487         CU_RET_ERR(stat, "cudaEventCreate on stop_pl_h2d failed");
488
489         stat = cudaEventCreateWithFlags(&(t->start_nb_h2d[i]), eventflags);
490         CU_RET_ERR(stat, "cudaEventCreate on start_nb_h2d failed");
491         stat = cudaEventCreateWithFlags(&(t->stop_nb_h2d[i]), eventflags);
492         CU_RET_ERR(stat, "cudaEventCreate on stop_nb_h2d failed");
493
494         stat = cudaEventCreateWithFlags(&(t->start_nb_d2h[i]), eventflags);
495         CU_RET_ERR(stat, "cudaEventCreate on start_nb_d2h failed");
496         stat = cudaEventCreateWithFlags(&(t->stop_nb_d2h[i]), eventflags);
497         CU_RET_ERR(stat, "cudaEventCreate on stop_nb_d2h failed");
498     }
499 }
500
501 /*! Initializes the timings data structure. */
502 static void init_timings(wallclock_gpu_t *t)
503 {
504     int i, j;
505
506     t->nb_h2d_t = 0.0;
507     t->nb_d2h_t = 0.0;
508     t->nb_c     = 0;
509     t->pl_h2d_t = 0.0;
510     t->pl_h2d_c = 0;
511     for (i = 0; i < 2; i++)
512     {
513         for (j = 0; j < 2; j++)
514         {
515             t->ktime[i][j].t = 0.0;
516             t->ktime[i][j].c = 0;
517         }
518     }
519 }
520
521 void nbnxn_cuda_init(FILE                 *fplog,
522                      nbnxn_cuda_ptr_t     *p_cu_nb,
523                      const gmx_gpu_info_t *gpu_info,
524                      const gmx_gpu_opt_t  *gpu_opt,
525                      int                   my_gpu_index,
526                      gmx_bool              bLocalAndNonlocal)
527 {
528     cudaError_t       stat;
529     nbnxn_cuda_ptr_t  nb;
530     char              sbuf[STRLEN];
531     bool              bStreamSync, bNoStreamSync, bTMPIAtomics, bX86, bOldDriver;
532     int               cuda_drv_ver;
533
534     assert(gpu_info);
535
536     if (p_cu_nb == NULL)
537     {
538         return;
539     }
540
541     snew(nb, 1);
542     snew(nb->atdat, 1);
543     snew(nb->nbparam, 1);
544     snew(nb->plist[eintLocal], 1);
545     if (bLocalAndNonlocal)
546     {
547         snew(nb->plist[eintNonlocal], 1);
548     }
549
550     nb->bUseTwoStreams = bLocalAndNonlocal;
551
552     snew(nb->timers, 1);
553     snew(nb->timings, 1);
554
555     /* init nbst */
556     pmalloc((void**)&nb->nbst.e_lj, sizeof(*nb->nbst.e_lj));
557     pmalloc((void**)&nb->nbst.e_el, sizeof(*nb->nbst.e_el));
558     pmalloc((void**)&nb->nbst.fshift, SHIFTS * sizeof(*nb->nbst.fshift));
559
560     init_plist(nb->plist[eintLocal]);
561
562     /* set device info, just point it to the right GPU among the detected ones */
563     nb->dev_info = &gpu_info->cuda_dev[get_gpu_device_id(gpu_info, gpu_opt, my_gpu_index)];
564
565     /* local/non-local GPU streams */
566     stat = cudaStreamCreate(&nb->stream[eintLocal]);
567     CU_RET_ERR(stat, "cudaStreamCreate on stream[eintLocal] failed");
568     if (nb->bUseTwoStreams)
569     {
570         init_plist(nb->plist[eintNonlocal]);
571
572         /* CUDA stream priority available in the CUDA RT 5.5 API.
573          * Note that the device we're running on does not have to support
574          * priorities, because we are querying the priority range which in this
575          * case will be a single value.
576          */
577 #if CUDA_VERSION >= 5500
578         {
579             int highest_priority;
580             stat = cudaDeviceGetStreamPriorityRange(NULL, &highest_priority);
581             CU_RET_ERR(stat, "cudaDeviceGetStreamPriorityRange failed");
582
583             stat = cudaStreamCreateWithPriority(&nb->stream[eintNonlocal],
584                                                 cudaStreamDefault,
585                                                 highest_priority);
586             CU_RET_ERR(stat, "cudaStreamCreateWithPriority on stream[eintNonlocal] failed");
587         }
588 #else
589         stat = cudaStreamCreate(&nb->stream[eintNonlocal]);
590         CU_RET_ERR(stat, "cudaStreamCreate on stream[eintNonlocal] failed");
591 #endif
592     }
593
594     /* init events for sychronization (timing disabled for performance reasons!) */
595     stat = cudaEventCreateWithFlags(&nb->nonlocal_done, cudaEventDisableTiming);
596     CU_RET_ERR(stat, "cudaEventCreate on nonlocal_done failed");
597     stat = cudaEventCreateWithFlags(&nb->misc_ops_done, cudaEventDisableTiming);
598     CU_RET_ERR(stat, "cudaEventCreate on misc_ops_one failed");
599
600     /* On GPUs with ECC enabled, cudaStreamSynchronize shows a large overhead
601      * (which increases with shorter time/step) caused by a known CUDA driver bug.
602      * To work around the issue we'll use an (admittedly fragile) memory polling
603      * waiting to preserve performance. This requires support for atomic
604      * operations and only works on x86/x86_64.
605      * With polling wait event-timing also needs to be disabled.
606      *
607      * The overhead is greatly reduced in API v5.0 drivers and the improvement
608      * is independent of runtime version. Hence, with API v5.0 drivers and later
609      * we won't switch to polling.
610      *
611      * NOTE: Unfortunately, this is known to fail when GPUs are shared by (t)MPI,
612      * ranks so we will also disable it in that case.
613      */
614
615     bStreamSync    = getenv("GMX_CUDA_STREAMSYNC") != NULL;
616     bNoStreamSync  = getenv("GMX_NO_CUDA_STREAMSYNC") != NULL;
617
618 #ifdef TMPI_ATOMICS
619     bTMPIAtomics = true;
620 #else
621     bTMPIAtomics = false;
622 #endif
623
624 #ifdef GMX_TARGET_X86
625     bX86 = true;
626 #else
627     bX86 = false;
628 #endif
629
630     if (bStreamSync && bNoStreamSync)
631     {
632         gmx_fatal(FARGS, "Conflicting environment variables: both GMX_CUDA_STREAMSYNC and GMX_NO_CUDA_STREAMSYNC defined");
633     }
634
635     stat = cudaDriverGetVersion(&cuda_drv_ver);
636     CU_RET_ERR(stat, "cudaDriverGetVersion failed");
637
638     bOldDriver = (cuda_drv_ver < 5000);
639
640     if ((nb->dev_info->prop.ECCEnabled == 1) && bOldDriver)
641     {
642         /* Polling wait should be used instead of cudaStreamSynchronize only if:
643          *   - ECC is ON & driver is old (checked above),
644          *   - we're on x86/x86_64,
645          *   - atomics are available, and
646          *   - GPUs are not being shared.
647          */
648         bool bShouldUsePollSync = (bX86 && bTMPIAtomics &&
649                                    (gmx_count_gpu_dev_shared(gpu_opt) < 1));
650
651         if (bStreamSync)
652         {
653             nb->bUseStreamSync = true;
654
655             /* only warn if polling should be used */
656             if (bShouldUsePollSync)
657             {
658                 md_print_warn(fplog,
659                               "NOTE: Using a GPU with ECC enabled and CUDA driver API version <5.0, but\n"
660                               "      cudaStreamSynchronize waiting is forced by the GMX_CUDA_STREAMSYNC env. var.\n");
661             }
662         }
663         else
664         {
665             nb->bUseStreamSync = !bShouldUsePollSync;
666
667             if (bShouldUsePollSync)
668             {
669                 md_print_warn(fplog,
670                               "NOTE: Using a GPU with ECC enabled and CUDA driver API version <5.0, known to\n"
671                               "      cause performance loss. Switching to the alternative polling GPU wait.\n"
672                               "      If you encounter issues, switch back to standard GPU waiting by setting\n"
673                               "      the GMX_CUDA_STREAMSYNC environment variable.\n");
674             }
675             else
676             {
677                 /* Tell the user that the ECC+old driver combination can be bad */
678                 sprintf(sbuf,
679                         "NOTE: Using a GPU with ECC enabled and CUDA driver API version <5.0.\n"
680                         "      A known bug in this driver version can cause performance loss.\n"
681                         "      However, the polling wait workaround can not be used because\n%s\n"
682                         "      Consider updating the driver or turning ECC off.",
683                         (bX86 && bTMPIAtomics) ?
684                         "      GPU(s) are being oversubscribed." :
685                         "      atomic operations are not supported by the platform/CPU+compiler.");
686                 md_print_warn(fplog, sbuf);
687             }
688         }
689     }
690     else
691     {
692         if (bNoStreamSync)
693         {
694             nb->bUseStreamSync = false;
695
696             md_print_warn(fplog,
697                           "NOTE: Polling wait for GPU synchronization requested by GMX_NO_CUDA_STREAMSYNC\n");
698         }
699         else
700         {
701             /* no/off ECC, cudaStreamSynchronize not turned off by env. var. */
702             nb->bUseStreamSync = true;
703         }
704     }
705
706     /* CUDA timing disabled as event timers don't work:
707        - with multiple streams = domain-decomposition;
708        - with the polling waiting hack (without cudaStreamSynchronize);
709        - when turned off by GMX_DISABLE_CUDA_TIMING.
710      */
711     nb->bDoTime = (!nb->bUseTwoStreams && nb->bUseStreamSync &&
712                    (getenv("GMX_DISABLE_CUDA_TIMING") == NULL));
713
714     if (nb->bDoTime)
715     {
716         init_timers(nb->timers, nb->bUseTwoStreams);
717         init_timings(nb->timings);
718     }
719
720     /* set the kernel type for the current GPU */
721     /* pick L1 cache configuration */
722     nbnxn_cuda_set_cacheconfig(nb->dev_info);
723
724     *p_cu_nb = nb;
725
726     if (debug)
727     {
728         fprintf(debug, "Initialized CUDA data structures.\n");
729     }
730 }
731
732 void nbnxn_cuda_init_const(nbnxn_cuda_ptr_t                cu_nb,
733                            const interaction_const_t      *ic,
734                            const nonbonded_verlet_group_t *nbv_group)
735 {
736     init_atomdata_first(cu_nb->atdat, nbv_group[0].nbat->ntype);
737     init_nbparam(cu_nb->nbparam, ic, nbv_group[0].nbat, cu_nb->dev_info);
738
739     /* clear energy and shift force outputs */
740     nbnxn_cuda_clear_e_fshift(cu_nb);
741 }
742
743 void nbnxn_cuda_init_pairlist(nbnxn_cuda_ptr_t        cu_nb,
744                               const nbnxn_pairlist_t *h_plist,
745                               int                     iloc)
746 {
747     char          sbuf[STRLEN];
748     cudaError_t   stat;
749     bool          bDoTime    = cu_nb->bDoTime;
750     cudaStream_t  stream     = cu_nb->stream[iloc];
751     cu_plist_t   *d_plist    = cu_nb->plist[iloc];
752
753     if (d_plist->na_c < 0)
754     {
755         d_plist->na_c = h_plist->na_ci;
756     }
757     else
758     {
759         if (d_plist->na_c != h_plist->na_ci)
760         {
761             sprintf(sbuf, "In cu_init_plist: the #atoms per cell has changed (from %d to %d)",
762                     d_plist->na_c, h_plist->na_ci);
763             gmx_incons(sbuf);
764         }
765     }
766
767     if (bDoTime)
768     {
769         stat = cudaEventRecord(cu_nb->timers->start_pl_h2d[iloc], stream);
770         CU_RET_ERR(stat, "cudaEventRecord failed");
771     }
772
773     cu_realloc_buffered((void **)&d_plist->sci, h_plist->sci, sizeof(*d_plist->sci),
774                         &d_plist->nsci, &d_plist->sci_nalloc,
775                         h_plist->nsci,
776                         stream, true);
777
778     cu_realloc_buffered((void **)&d_plist->cj4, h_plist->cj4, sizeof(*d_plist->cj4),
779                         &d_plist->ncj4, &d_plist->cj4_nalloc,
780                         h_plist->ncj4,
781                         stream, true);
782
783     cu_realloc_buffered((void **)&d_plist->excl, h_plist->excl, sizeof(*d_plist->excl),
784                         &d_plist->nexcl, &d_plist->excl_nalloc,
785                         h_plist->nexcl,
786                         stream, true);
787
788     if (bDoTime)
789     {
790         stat = cudaEventRecord(cu_nb->timers->stop_pl_h2d[iloc], stream);
791         CU_RET_ERR(stat, "cudaEventRecord failed");
792     }
793
794     /* need to prune the pair list during the next step */
795     d_plist->bDoPrune = true;
796 }
797
798 void nbnxn_cuda_upload_shiftvec(nbnxn_cuda_ptr_t        cu_nb,
799                                 const nbnxn_atomdata_t *nbatom)
800 {
801     cu_atomdata_t *adat  = cu_nb->atdat;
802     cudaStream_t   ls    = cu_nb->stream[eintLocal];
803
804     /* only if we have a dynamic box */
805     if (nbatom->bDynamicBox || !adat->bShiftVecUploaded)
806     {
807         cu_copy_H2D_async(adat->shift_vec, nbatom->shift_vec,
808                           SHIFTS * sizeof(*adat->shift_vec), ls);
809         adat->bShiftVecUploaded = true;
810     }
811 }
812
813 /*! Clears the first natoms_clear elements of the GPU nonbonded force output array. */
814 static void nbnxn_cuda_clear_f(nbnxn_cuda_ptr_t cu_nb, int natoms_clear)
815 {
816     cudaError_t    stat;
817     cu_atomdata_t *adat  = cu_nb->atdat;
818     cudaStream_t   ls    = cu_nb->stream[eintLocal];
819
820     stat = cudaMemsetAsync(adat->f, 0, natoms_clear * sizeof(*adat->f), ls);
821     CU_RET_ERR(stat, "cudaMemsetAsync on f falied");
822 }
823
824 /*! Clears nonbonded shift force output array and energy outputs on the GPU. */
825 static void nbnxn_cuda_clear_e_fshift(nbnxn_cuda_ptr_t cu_nb)
826 {
827     cudaError_t    stat;
828     cu_atomdata_t *adat  = cu_nb->atdat;
829     cudaStream_t   ls    = cu_nb->stream[eintLocal];
830
831     stat = cudaMemsetAsync(adat->fshift, 0, SHIFTS * sizeof(*adat->fshift), ls);
832     CU_RET_ERR(stat, "cudaMemsetAsync on fshift falied");
833     stat = cudaMemsetAsync(adat->e_lj, 0, sizeof(*adat->e_lj), ls);
834     CU_RET_ERR(stat, "cudaMemsetAsync on e_lj falied");
835     stat = cudaMemsetAsync(adat->e_el, 0, sizeof(*adat->e_el), ls);
836     CU_RET_ERR(stat, "cudaMemsetAsync on e_el falied");
837 }
838
839 void nbnxn_cuda_clear_outputs(nbnxn_cuda_ptr_t cu_nb, int flags)
840 {
841     nbnxn_cuda_clear_f(cu_nb, cu_nb->atdat->natoms);
842     /* clear shift force array and energies if the outputs were
843        used in the current step */
844     if (flags & GMX_FORCE_VIRIAL)
845     {
846         nbnxn_cuda_clear_e_fshift(cu_nb);
847     }
848 }
849
850 void nbnxn_cuda_init_atomdata(nbnxn_cuda_ptr_t        cu_nb,
851                               const nbnxn_atomdata_t *nbat)
852 {
853     cudaError_t    stat;
854     int            nalloc, natoms;
855     bool           realloced;
856     bool           bDoTime   = cu_nb->bDoTime;
857     cu_timers_t   *timers    = cu_nb->timers;
858     cu_atomdata_t *d_atdat   = cu_nb->atdat;
859     cudaStream_t   ls        = cu_nb->stream[eintLocal];
860
861     natoms    = nbat->natoms;
862     realloced = false;
863
864     if (bDoTime)
865     {
866         /* time async copy */
867         stat = cudaEventRecord(timers->start_atdat, ls);
868         CU_RET_ERR(stat, "cudaEventRecord failed");
869     }
870
871     /* need to reallocate if we have to copy more atoms than the amount of space
872        available and only allocate if we haven't initialized yet, i.e d_atdat->natoms == -1 */
873     if (natoms > d_atdat->nalloc)
874     {
875         nalloc = over_alloc_small(natoms);
876
877         /* free up first if the arrays have already been initialized */
878         if (d_atdat->nalloc != -1)
879         {
880             cu_free_buffered(d_atdat->f, &d_atdat->natoms, &d_atdat->nalloc);
881             cu_free_buffered(d_atdat->xq);
882             cu_free_buffered(d_atdat->atom_types);
883         }
884
885         stat = cudaMalloc((void **)&d_atdat->f, nalloc*sizeof(*d_atdat->f));
886         CU_RET_ERR(stat, "cudaMalloc failed on d_atdat->f");
887         stat = cudaMalloc((void **)&d_atdat->xq, nalloc*sizeof(*d_atdat->xq));
888         CU_RET_ERR(stat, "cudaMalloc failed on d_atdat->xq");
889
890         stat = cudaMalloc((void **)&d_atdat->atom_types, nalloc*sizeof(*d_atdat->atom_types));
891         CU_RET_ERR(stat, "cudaMalloc failed on d_atdat->atom_types");
892
893         d_atdat->nalloc = nalloc;
894         realloced       = true;
895     }
896
897     d_atdat->natoms       = natoms;
898     d_atdat->natoms_local = nbat->natoms_local;
899
900     /* need to clear GPU f output if realloc happened */
901     if (realloced)
902     {
903         nbnxn_cuda_clear_f(cu_nb, nalloc);
904     }
905
906     cu_copy_H2D_async(d_atdat->atom_types, nbat->type,
907                       natoms*sizeof(*d_atdat->atom_types), ls);
908
909     if (bDoTime)
910     {
911         stat = cudaEventRecord(timers->stop_atdat, ls);
912         CU_RET_ERR(stat, "cudaEventRecord failed");
913     }
914 }
915
916 void nbnxn_cuda_free(nbnxn_cuda_ptr_t cu_nb)
917 {
918     cudaError_t      stat;
919     cu_atomdata_t   *atdat;
920     cu_nbparam_t    *nbparam;
921     cu_plist_t      *plist, *plist_nl;
922     cu_timers_t     *timers;
923
924     if (cu_nb == NULL)
925     {
926         return;
927     }
928
929     atdat       = cu_nb->atdat;
930     nbparam     = cu_nb->nbparam;
931     plist       = cu_nb->plist[eintLocal];
932     plist_nl    = cu_nb->plist[eintNonlocal];
933     timers      = cu_nb->timers;
934
935     if (nbparam->eeltype == eelCuEWALD_TAB || nbparam->eeltype == eelCuEWALD_TAB_TWIN)
936     {
937
938 #ifdef TEXOBJ_SUPPORTED
939         /* Only device CC >= 3.0 (Kepler and later) support texture objects */
940         if (cu_nb->dev_info->prop.major >= 3)
941         {
942             stat = cudaDestroyTextureObject(nbparam->coulomb_tab_texobj);
943             CU_RET_ERR(stat, "cudaDestroyTextureObject on coulomb_tab_texobj failed");
944         }
945         else
946 #endif
947         {
948             stat = cudaUnbindTexture(nbnxn_cuda_get_coulomb_tab_texref());
949             CU_RET_ERR(stat, "cudaUnbindTexture on coulomb_tab_texref failed");
950         }
951         cu_free_buffered(nbparam->coulomb_tab, &nbparam->coulomb_tab_size);
952     }
953
954     stat = cudaEventDestroy(cu_nb->nonlocal_done);
955     CU_RET_ERR(stat, "cudaEventDestroy failed on timers->nonlocal_done");
956     stat = cudaEventDestroy(cu_nb->misc_ops_done);
957     CU_RET_ERR(stat, "cudaEventDestroy failed on timers->misc_ops_done");
958
959     if (cu_nb->bDoTime)
960     {
961         stat = cudaEventDestroy(timers->start_atdat);
962         CU_RET_ERR(stat, "cudaEventDestroy failed on timers->start_atdat");
963         stat = cudaEventDestroy(timers->stop_atdat);
964         CU_RET_ERR(stat, "cudaEventDestroy failed on timers->stop_atdat");
965
966         /* The non-local counters/stream (second in the array) are needed only with DD. */
967         for (int i = 0; i <= (cu_nb->bUseTwoStreams ? 1 : 0); i++)
968         {
969             stat = cudaEventDestroy(timers->start_nb_k[i]);
970             CU_RET_ERR(stat, "cudaEventDestroy failed on timers->start_nb_k");
971             stat = cudaEventDestroy(timers->stop_nb_k[i]);
972             CU_RET_ERR(stat, "cudaEventDestroy failed on timers->stop_nb_k");
973
974             stat = cudaEventDestroy(timers->start_pl_h2d[i]);
975             CU_RET_ERR(stat, "cudaEventDestroy failed on timers->start_pl_h2d");
976             stat = cudaEventDestroy(timers->stop_pl_h2d[i]);
977             CU_RET_ERR(stat, "cudaEventDestroy failed on timers->stop_pl_h2d");
978
979             stat = cudaStreamDestroy(cu_nb->stream[i]);
980             CU_RET_ERR(stat, "cudaStreamDestroy failed on stream");
981
982             stat = cudaEventDestroy(timers->start_nb_h2d[i]);
983             CU_RET_ERR(stat, "cudaEventDestroy failed on timers->start_nb_h2d");
984             stat = cudaEventDestroy(timers->stop_nb_h2d[i]);
985             CU_RET_ERR(stat, "cudaEventDestroy failed on timers->stop_nb_h2d");
986
987             stat = cudaEventDestroy(timers->start_nb_d2h[i]);
988             CU_RET_ERR(stat, "cudaEventDestroy failed on timers->start_nb_d2h");
989             stat = cudaEventDestroy(timers->stop_nb_d2h[i]);
990             CU_RET_ERR(stat, "cudaEventDestroy failed on timers->stop_nb_d2h");
991         }
992     }
993
994 #ifdef TEXOBJ_SUPPORTED
995     /* Only device CC >= 3.0 (Kepler and later) support texture objects */
996     if (cu_nb->dev_info->prop.major >= 3)
997     {
998         stat = cudaDestroyTextureObject(nbparam->nbfp_texobj);
999         CU_RET_ERR(stat, "cudaDestroyTextureObject on nbfp_texobj failed");
1000     }
1001     else
1002 #endif
1003     {
1004         stat = cudaUnbindTexture(nbnxn_cuda_get_nbfp_texref());
1005         CU_RET_ERR(stat, "cudaUnbindTexture on nbfp_texref failed");
1006     }
1007     cu_free_buffered(nbparam->nbfp);
1008
1009     if (nbparam->vdwtype == evdwCuEWALDGEOM || nbparam->vdwtype == evdwCuEWALDLB)
1010     {
1011 #ifdef TEXOBJ_SUPPORTED
1012         /* Only device CC >= 3.0 (Kepler and later) support texture objects */
1013         if (cu_nb->dev_info->prop.major >= 3)
1014         {
1015             stat = cudaDestroyTextureObject(nbparam->nbfp_comb_texobj);
1016             CU_RET_ERR(stat, "cudaDestroyTextureObject on nbfp_comb_texobj failed");
1017         }
1018         else
1019 #endif
1020         {
1021             stat = cudaUnbindTexture(nbnxn_cuda_get_nbfp_comb_texref());
1022             CU_RET_ERR(stat, "cudaUnbindTexture on nbfp_comb_texref failed");
1023         }
1024         cu_free_buffered(nbparam->nbfp_comb);
1025     }
1026
1027     stat = cudaFree(atdat->shift_vec);
1028     CU_RET_ERR(stat, "cudaFree failed on atdat->shift_vec");
1029     stat = cudaFree(atdat->fshift);
1030     CU_RET_ERR(stat, "cudaFree failed on atdat->fshift");
1031
1032     stat = cudaFree(atdat->e_lj);
1033     CU_RET_ERR(stat, "cudaFree failed on atdat->e_lj");
1034     stat = cudaFree(atdat->e_el);
1035     CU_RET_ERR(stat, "cudaFree failed on atdat->e_el");
1036
1037     cu_free_buffered(atdat->f, &atdat->natoms, &atdat->nalloc);
1038     cu_free_buffered(atdat->xq);
1039     cu_free_buffered(atdat->atom_types, &atdat->ntypes);
1040
1041     cu_free_buffered(plist->sci, &plist->nsci, &plist->sci_nalloc);
1042     cu_free_buffered(plist->cj4, &plist->ncj4, &plist->cj4_nalloc);
1043     cu_free_buffered(plist->excl, &plist->nexcl, &plist->excl_nalloc);
1044     if (cu_nb->bUseTwoStreams)
1045     {
1046         cu_free_buffered(plist_nl->sci, &plist_nl->nsci, &plist_nl->sci_nalloc);
1047         cu_free_buffered(plist_nl->cj4, &plist_nl->ncj4, &plist_nl->cj4_nalloc);
1048         cu_free_buffered(plist_nl->excl, &plist_nl->nexcl, &plist->excl_nalloc);
1049     }
1050
1051     sfree(atdat);
1052     sfree(nbparam);
1053     sfree(plist);
1054     if (cu_nb->bUseTwoStreams)
1055     {
1056         sfree(plist_nl);
1057     }
1058     sfree(timers);
1059     sfree(cu_nb->timings);
1060     sfree(cu_nb);
1061
1062     if (debug)
1063     {
1064         fprintf(debug, "Cleaned up CUDA data structures.\n");
1065     }
1066 }
1067
1068 void cu_synchstream_atdat(nbnxn_cuda_ptr_t cu_nb, int iloc)
1069 {
1070     cudaError_t  stat;
1071     cudaStream_t stream = cu_nb->stream[iloc];
1072
1073     stat = cudaStreamWaitEvent(stream, cu_nb->timers->stop_atdat, 0);
1074     CU_RET_ERR(stat, "cudaStreamWaitEvent failed");
1075 }
1076
1077 wallclock_gpu_t * nbnxn_cuda_get_timings(nbnxn_cuda_ptr_t cu_nb)
1078 {
1079     return (cu_nb != NULL && cu_nb->bDoTime) ? cu_nb->timings : NULL;
1080 }
1081
1082 void nbnxn_cuda_reset_timings(nbnxn_cuda_ptr_t cu_nb)
1083 {
1084     if (cu_nb->bDoTime)
1085     {
1086         init_timings(cu_nb->timings);
1087     }
1088 }
1089
1090 int nbnxn_cuda_min_ci_balanced(nbnxn_cuda_ptr_t cu_nb)
1091 {
1092     return cu_nb != NULL ?
1093            gpu_min_ci_balanced_factor*cu_nb->dev_info->prop.multiProcessorCount : 0;
1094
1095 }
1096
1097 gmx_bool nbnxn_cuda_is_kernel_ewald_analytical(const nbnxn_cuda_ptr_t cu_nb)
1098 {
1099     return ((cu_nb->nbparam->eeltype == eelCuEWALD_ANA) ||
1100             (cu_nb->nbparam->eeltype == eelCuEWALD_ANA_TWIN));
1101 }