Sort all includes in src/gromacs
[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 #include "gmxpre.h"
36
37 #include "nbnxn_cuda_data_mgmt.h"
38
39 #include "config.h"
40
41 #include <assert.h>
42 #include <stdarg.h>
43 #include <stdio.h>
44 #include <stdlib.h>
45
46 #include <cuda.h>
47
48 #include "gromacs/gmxlib/cuda_tools/cudautils.cuh"
49 #include "gromacs/legacyheaders/gmx_detect_hardware.h"
50 #include "gromacs/legacyheaders/gpu_utils.h"
51 #include "gromacs/legacyheaders/pmalloc_cuda.h"
52 #include "gromacs/legacyheaders/tables.h"
53 #include "gromacs/legacyheaders/typedefs.h"
54 #include "gromacs/legacyheaders/types/enums.h"
55 #include "gromacs/legacyheaders/types/force_flags.h"
56 #include "gromacs/legacyheaders/types/interaction_const.h"
57 #include "gromacs/mdlib/nb_verlet.h"
58 #include "gromacs/mdlib/nbnxn_consts.h"
59 #include "gromacs/pbcutil/ishift.h"
60 #include "gromacs/utility/common.h"
61 #include "gromacs/utility/cstringutil.h"
62 #include "gromacs/utility/fatalerror.h"
63 #include "gromacs/utility/smalloc.h"
64
65 #include "nbnxn_cuda_types.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(const nonbonded_verlet_t    *nbv,
432                                          const interaction_const_t   *ic)
433 {
434     if (!nbv || nbv->grp[0].kernel_type != nbnxnk8x8x8_CUDA)
435     {
436         return;
437     }
438     nbnxn_cuda_ptr_t cu_nb = nbv->cu_nbv;
439     cu_nbparam_t    *nbp   = cu_nb->nbparam;
440
441     set_cutoff_parameters(nbp, ic);
442
443     nbp->eeltype        = pick_ewald_kernel_type(ic->rcoulomb != ic->rvdw,
444                                                  cu_nb->dev_info);
445
446     init_ewald_coulomb_force_table(cu_nb->nbparam, cu_nb->dev_info);
447 }
448
449 /*! Initializes the pair list data structure. */
450 static void init_plist(cu_plist_t *pl)
451 {
452     /* initialize to NULL pointers to data that is not allocated here and will
453        need reallocation in nbnxn_cuda_init_pairlist */
454     pl->sci     = NULL;
455     pl->cj4     = NULL;
456     pl->excl    = NULL;
457
458     /* size -1 indicates that the respective array hasn't been initialized yet */
459     pl->na_c        = -1;
460     pl->nsci        = -1;
461     pl->sci_nalloc  = -1;
462     pl->ncj4        = -1;
463     pl->cj4_nalloc  = -1;
464     pl->nexcl       = -1;
465     pl->excl_nalloc = -1;
466     pl->bDoPrune    = false;
467 }
468
469 /*! Initializes the timer data structure. */
470 static void init_timers(cu_timers_t *t, bool bUseTwoStreams)
471 {
472     cudaError_t stat;
473     int         eventflags = ( bUseCudaEventBlockingSync ? cudaEventBlockingSync : cudaEventDefault );
474
475     stat = cudaEventCreateWithFlags(&(t->start_atdat), eventflags);
476     CU_RET_ERR(stat, "cudaEventCreate on start_atdat failed");
477     stat = cudaEventCreateWithFlags(&(t->stop_atdat), eventflags);
478     CU_RET_ERR(stat, "cudaEventCreate on stop_atdat failed");
479
480     /* The non-local counters/stream (second in the array) are needed only with DD. */
481     for (int i = 0; i <= (bUseTwoStreams ? 1 : 0); i++)
482     {
483         stat = cudaEventCreateWithFlags(&(t->start_nb_k[i]), eventflags);
484         CU_RET_ERR(stat, "cudaEventCreate on start_nb_k failed");
485         stat = cudaEventCreateWithFlags(&(t->stop_nb_k[i]), eventflags);
486         CU_RET_ERR(stat, "cudaEventCreate on stop_nb_k failed");
487
488
489         stat = cudaEventCreateWithFlags(&(t->start_pl_h2d[i]), eventflags);
490         CU_RET_ERR(stat, "cudaEventCreate on start_pl_h2d failed");
491         stat = cudaEventCreateWithFlags(&(t->stop_pl_h2d[i]), eventflags);
492         CU_RET_ERR(stat, "cudaEventCreate on stop_pl_h2d failed");
493
494         stat = cudaEventCreateWithFlags(&(t->start_nb_h2d[i]), eventflags);
495         CU_RET_ERR(stat, "cudaEventCreate on start_nb_h2d failed");
496         stat = cudaEventCreateWithFlags(&(t->stop_nb_h2d[i]), eventflags);
497         CU_RET_ERR(stat, "cudaEventCreate on stop_nb_h2d failed");
498
499         stat = cudaEventCreateWithFlags(&(t->start_nb_d2h[i]), eventflags);
500         CU_RET_ERR(stat, "cudaEventCreate on start_nb_d2h failed");
501         stat = cudaEventCreateWithFlags(&(t->stop_nb_d2h[i]), eventflags);
502         CU_RET_ERR(stat, "cudaEventCreate on stop_nb_d2h failed");
503     }
504 }
505
506 /*! Initializes the timings data structure. */
507 static void init_timings(wallclock_gpu_t *t)
508 {
509     int i, j;
510
511     t->nb_h2d_t = 0.0;
512     t->nb_d2h_t = 0.0;
513     t->nb_c     = 0;
514     t->pl_h2d_t = 0.0;
515     t->pl_h2d_c = 0;
516     for (i = 0; i < 2; i++)
517     {
518         for (j = 0; j < 2; j++)
519         {
520             t->ktime[i][j].t = 0.0;
521             t->ktime[i][j].c = 0;
522         }
523     }
524 }
525
526 void nbnxn_cuda_init(FILE                 *fplog,
527                      nbnxn_cuda_ptr_t     *p_cu_nb,
528                      const gmx_gpu_info_t *gpu_info,
529                      const gmx_gpu_opt_t  *gpu_opt,
530                      int                   my_gpu_index,
531                      gmx_bool              bLocalAndNonlocal)
532 {
533     cudaError_t       stat;
534     nbnxn_cuda_ptr_t  nb;
535     char              sbuf[STRLEN];
536     bool              bStreamSync, bNoStreamSync, bTMPIAtomics, bX86, bOldDriver;
537     int               cuda_drv_ver;
538
539     assert(gpu_info);
540
541     if (p_cu_nb == NULL)
542     {
543         return;
544     }
545
546     snew(nb, 1);
547     snew(nb->atdat, 1);
548     snew(nb->nbparam, 1);
549     snew(nb->plist[eintLocal], 1);
550     if (bLocalAndNonlocal)
551     {
552         snew(nb->plist[eintNonlocal], 1);
553     }
554
555     nb->bUseTwoStreams = bLocalAndNonlocal;
556
557     snew(nb->timers, 1);
558     snew(nb->timings, 1);
559
560     /* init nbst */
561     pmalloc((void**)&nb->nbst.e_lj, sizeof(*nb->nbst.e_lj));
562     pmalloc((void**)&nb->nbst.e_el, sizeof(*nb->nbst.e_el));
563     pmalloc((void**)&nb->nbst.fshift, SHIFTS * sizeof(*nb->nbst.fshift));
564
565     init_plist(nb->plist[eintLocal]);
566
567     /* set device info, just point it to the right GPU among the detected ones */
568     nb->dev_info = &gpu_info->cuda_dev[get_gpu_device_id(gpu_info, gpu_opt, my_gpu_index)];
569
570     /* local/non-local GPU streams */
571     stat = cudaStreamCreate(&nb->stream[eintLocal]);
572     CU_RET_ERR(stat, "cudaStreamCreate on stream[eintLocal] failed");
573     if (nb->bUseTwoStreams)
574     {
575         init_plist(nb->plist[eintNonlocal]);
576
577         /* CUDA stream priority available in the CUDA RT 5.5 API.
578          * Note that the device we're running on does not have to support
579          * priorities, because we are querying the priority range which in this
580          * case will be a single value.
581          */
582 #if CUDA_VERSION >= 5500
583         {
584             int highest_priority;
585             stat = cudaDeviceGetStreamPriorityRange(NULL, &highest_priority);
586             CU_RET_ERR(stat, "cudaDeviceGetStreamPriorityRange failed");
587
588             stat = cudaStreamCreateWithPriority(&nb->stream[eintNonlocal],
589                                                 cudaStreamDefault,
590                                                 highest_priority);
591             CU_RET_ERR(stat, "cudaStreamCreateWithPriority on stream[eintNonlocal] failed");
592         }
593 #else
594         stat = cudaStreamCreate(&nb->stream[eintNonlocal]);
595         CU_RET_ERR(stat, "cudaStreamCreate on stream[eintNonlocal] failed");
596 #endif
597     }
598
599     /* init events for sychronization (timing disabled for performance reasons!) */
600     stat = cudaEventCreateWithFlags(&nb->nonlocal_done, cudaEventDisableTiming);
601     CU_RET_ERR(stat, "cudaEventCreate on nonlocal_done failed");
602     stat = cudaEventCreateWithFlags(&nb->misc_ops_done, cudaEventDisableTiming);
603     CU_RET_ERR(stat, "cudaEventCreate on misc_ops_one failed");
604
605     /* On GPUs with ECC enabled, cudaStreamSynchronize shows a large overhead
606      * (which increases with shorter time/step) caused by a known CUDA driver bug.
607      * To work around the issue we'll use an (admittedly fragile) memory polling
608      * waiting to preserve performance. This requires support for atomic
609      * operations and only works on x86/x86_64.
610      * With polling wait event-timing also needs to be disabled.
611      *
612      * The overhead is greatly reduced in API v5.0 drivers and the improvement
613      * is independent of runtime version. Hence, with API v5.0 drivers and later
614      * we won't switch to polling.
615      *
616      * NOTE: Unfortunately, this is known to fail when GPUs are shared by (t)MPI,
617      * ranks so we will also disable it in that case.
618      */
619
620     bStreamSync    = getenv("GMX_CUDA_STREAMSYNC") != NULL;
621     bNoStreamSync  = getenv("GMX_NO_CUDA_STREAMSYNC") != NULL;
622
623 #ifdef TMPI_ATOMICS
624     bTMPIAtomics = true;
625 #else
626     bTMPIAtomics = false;
627 #endif
628
629 #ifdef GMX_TARGET_X86
630     bX86 = true;
631 #else
632     bX86 = false;
633 #endif
634
635     if (bStreamSync && bNoStreamSync)
636     {
637         gmx_fatal(FARGS, "Conflicting environment variables: both GMX_CUDA_STREAMSYNC and GMX_NO_CUDA_STREAMSYNC defined");
638     }
639
640     stat = cudaDriverGetVersion(&cuda_drv_ver);
641     CU_RET_ERR(stat, "cudaDriverGetVersion failed");
642
643     bOldDriver = (cuda_drv_ver < 5000);
644
645     if ((nb->dev_info->prop.ECCEnabled == 1) && bOldDriver)
646     {
647         /* Polling wait should be used instead of cudaStreamSynchronize only if:
648          *   - ECC is ON & driver is old (checked above),
649          *   - we're on x86/x86_64,
650          *   - atomics are available, and
651          *   - GPUs are not being shared.
652          */
653         bool bShouldUsePollSync = (bX86 && bTMPIAtomics &&
654                                    (gmx_count_gpu_dev_shared(gpu_opt) < 1));
655
656         if (bStreamSync)
657         {
658             nb->bUseStreamSync = true;
659
660             /* only warn if polling should be used */
661             if (bShouldUsePollSync)
662             {
663                 md_print_warn(fplog,
664                               "NOTE: Using a GPU with ECC enabled and CUDA driver API version <5.0, but\n"
665                               "      cudaStreamSynchronize waiting is forced by the GMX_CUDA_STREAMSYNC env. var.\n");
666             }
667         }
668         else
669         {
670             nb->bUseStreamSync = !bShouldUsePollSync;
671
672             if (bShouldUsePollSync)
673             {
674                 md_print_warn(fplog,
675                               "NOTE: Using a GPU with ECC enabled and CUDA driver API version <5.0, known to\n"
676                               "      cause performance loss. Switching to the alternative polling GPU wait.\n"
677                               "      If you encounter issues, switch back to standard GPU waiting by setting\n"
678                               "      the GMX_CUDA_STREAMSYNC environment variable.\n");
679             }
680             else
681             {
682                 /* Tell the user that the ECC+old driver combination can be bad */
683                 sprintf(sbuf,
684                         "NOTE: Using a GPU with ECC enabled and CUDA driver API version <5.0.\n"
685                         "      A known bug in this driver version can cause performance loss.\n"
686                         "      However, the polling wait workaround can not be used because\n%s\n"
687                         "      Consider updating the driver or turning ECC off.",
688                         (bX86 && bTMPIAtomics) ?
689                         "      GPU(s) are being oversubscribed." :
690                         "      atomic operations are not supported by the platform/CPU+compiler.");
691                 md_print_warn(fplog, sbuf);
692             }
693         }
694     }
695     else
696     {
697         if (bNoStreamSync)
698         {
699             nb->bUseStreamSync = false;
700
701             md_print_warn(fplog,
702                           "NOTE: Polling wait for GPU synchronization requested by GMX_NO_CUDA_STREAMSYNC\n");
703         }
704         else
705         {
706             /* no/off ECC, cudaStreamSynchronize not turned off by env. var. */
707             nb->bUseStreamSync = true;
708         }
709     }
710
711     /* CUDA timing disabled as event timers don't work:
712        - with multiple streams = domain-decomposition;
713        - with the polling waiting hack (without cudaStreamSynchronize);
714        - when turned off by GMX_DISABLE_CUDA_TIMING.
715      */
716     nb->bDoTime = (!nb->bUseTwoStreams && nb->bUseStreamSync &&
717                    (getenv("GMX_DISABLE_CUDA_TIMING") == NULL));
718
719     if (nb->bDoTime)
720     {
721         init_timers(nb->timers, nb->bUseTwoStreams);
722         init_timings(nb->timings);
723     }
724
725     /* set the kernel type for the current GPU */
726     /* pick L1 cache configuration */
727     nbnxn_cuda_set_cacheconfig(nb->dev_info);
728
729     *p_cu_nb = nb;
730
731     if (debug)
732     {
733         fprintf(debug, "Initialized CUDA data structures.\n");
734     }
735 }
736
737 void nbnxn_cuda_init_const(nbnxn_cuda_ptr_t                cu_nb,
738                            const interaction_const_t      *ic,
739                            const nonbonded_verlet_group_t *nbv_group)
740 {
741     init_atomdata_first(cu_nb->atdat, nbv_group[0].nbat->ntype);
742     init_nbparam(cu_nb->nbparam, ic, nbv_group[0].nbat, cu_nb->dev_info);
743
744     /* clear energy and shift force outputs */
745     nbnxn_cuda_clear_e_fshift(cu_nb);
746 }
747
748 void nbnxn_cuda_init_pairlist(nbnxn_cuda_ptr_t        cu_nb,
749                               const nbnxn_pairlist_t *h_plist,
750                               int                     iloc)
751 {
752     char          sbuf[STRLEN];
753     cudaError_t   stat;
754     bool          bDoTime    = cu_nb->bDoTime;
755     cudaStream_t  stream     = cu_nb->stream[iloc];
756     cu_plist_t   *d_plist    = cu_nb->plist[iloc];
757
758     if (d_plist->na_c < 0)
759     {
760         d_plist->na_c = h_plist->na_ci;
761     }
762     else
763     {
764         if (d_plist->na_c != h_plist->na_ci)
765         {
766             sprintf(sbuf, "In cu_init_plist: the #atoms per cell has changed (from %d to %d)",
767                     d_plist->na_c, h_plist->na_ci);
768             gmx_incons(sbuf);
769         }
770     }
771
772     if (bDoTime)
773     {
774         stat = cudaEventRecord(cu_nb->timers->start_pl_h2d[iloc], stream);
775         CU_RET_ERR(stat, "cudaEventRecord failed");
776     }
777
778     cu_realloc_buffered((void **)&d_plist->sci, h_plist->sci, sizeof(*d_plist->sci),
779                         &d_plist->nsci, &d_plist->sci_nalloc,
780                         h_plist->nsci,
781                         stream, true);
782
783     cu_realloc_buffered((void **)&d_plist->cj4, h_plist->cj4, sizeof(*d_plist->cj4),
784                         &d_plist->ncj4, &d_plist->cj4_nalloc,
785                         h_plist->ncj4,
786                         stream, true);
787
788     cu_realloc_buffered((void **)&d_plist->excl, h_plist->excl, sizeof(*d_plist->excl),
789                         &d_plist->nexcl, &d_plist->excl_nalloc,
790                         h_plist->nexcl,
791                         stream, true);
792
793     if (bDoTime)
794     {
795         stat = cudaEventRecord(cu_nb->timers->stop_pl_h2d[iloc], stream);
796         CU_RET_ERR(stat, "cudaEventRecord failed");
797     }
798
799     /* need to prune the pair list during the next step */
800     d_plist->bDoPrune = true;
801 }
802
803 void nbnxn_cuda_upload_shiftvec(nbnxn_cuda_ptr_t        cu_nb,
804                                 const nbnxn_atomdata_t *nbatom)
805 {
806     cu_atomdata_t *adat  = cu_nb->atdat;
807     cudaStream_t   ls    = cu_nb->stream[eintLocal];
808
809     /* only if we have a dynamic box */
810     if (nbatom->bDynamicBox || !adat->bShiftVecUploaded)
811     {
812         cu_copy_H2D_async(adat->shift_vec, nbatom->shift_vec,
813                           SHIFTS * sizeof(*adat->shift_vec), ls);
814         adat->bShiftVecUploaded = true;
815     }
816 }
817
818 /*! Clears the first natoms_clear elements of the GPU nonbonded force output array. */
819 static void nbnxn_cuda_clear_f(nbnxn_cuda_ptr_t cu_nb, int natoms_clear)
820 {
821     cudaError_t    stat;
822     cu_atomdata_t *adat  = cu_nb->atdat;
823     cudaStream_t   ls    = cu_nb->stream[eintLocal];
824
825     stat = cudaMemsetAsync(adat->f, 0, natoms_clear * sizeof(*adat->f), ls);
826     CU_RET_ERR(stat, "cudaMemsetAsync on f falied");
827 }
828
829 /*! Clears nonbonded shift force output array and energy outputs on the GPU. */
830 static void nbnxn_cuda_clear_e_fshift(nbnxn_cuda_ptr_t cu_nb)
831 {
832     cudaError_t    stat;
833     cu_atomdata_t *adat  = cu_nb->atdat;
834     cudaStream_t   ls    = cu_nb->stream[eintLocal];
835
836     stat = cudaMemsetAsync(adat->fshift, 0, SHIFTS * sizeof(*adat->fshift), ls);
837     CU_RET_ERR(stat, "cudaMemsetAsync on fshift falied");
838     stat = cudaMemsetAsync(adat->e_lj, 0, sizeof(*adat->e_lj), ls);
839     CU_RET_ERR(stat, "cudaMemsetAsync on e_lj falied");
840     stat = cudaMemsetAsync(adat->e_el, 0, sizeof(*adat->e_el), ls);
841     CU_RET_ERR(stat, "cudaMemsetAsync on e_el falied");
842 }
843
844 void nbnxn_cuda_clear_outputs(nbnxn_cuda_ptr_t cu_nb, int flags)
845 {
846     nbnxn_cuda_clear_f(cu_nb, cu_nb->atdat->natoms);
847     /* clear shift force array and energies if the outputs were
848        used in the current step */
849     if (flags & GMX_FORCE_VIRIAL)
850     {
851         nbnxn_cuda_clear_e_fshift(cu_nb);
852     }
853 }
854
855 void nbnxn_cuda_init_atomdata(nbnxn_cuda_ptr_t        cu_nb,
856                               const nbnxn_atomdata_t *nbat)
857 {
858     cudaError_t    stat;
859     int            nalloc, natoms;
860     bool           realloced;
861     bool           bDoTime   = cu_nb->bDoTime;
862     cu_timers_t   *timers    = cu_nb->timers;
863     cu_atomdata_t *d_atdat   = cu_nb->atdat;
864     cudaStream_t   ls        = cu_nb->stream[eintLocal];
865
866     natoms    = nbat->natoms;
867     realloced = false;
868
869     if (bDoTime)
870     {
871         /* time async copy */
872         stat = cudaEventRecord(timers->start_atdat, ls);
873         CU_RET_ERR(stat, "cudaEventRecord failed");
874     }
875
876     /* need to reallocate if we have to copy more atoms than the amount of space
877        available and only allocate if we haven't initialized yet, i.e d_atdat->natoms == -1 */
878     if (natoms > d_atdat->nalloc)
879     {
880         nalloc = over_alloc_small(natoms);
881
882         /* free up first if the arrays have already been initialized */
883         if (d_atdat->nalloc != -1)
884         {
885             cu_free_buffered(d_atdat->f, &d_atdat->natoms, &d_atdat->nalloc);
886             cu_free_buffered(d_atdat->xq);
887             cu_free_buffered(d_atdat->atom_types);
888         }
889
890         stat = cudaMalloc((void **)&d_atdat->f, nalloc*sizeof(*d_atdat->f));
891         CU_RET_ERR(stat, "cudaMalloc failed on d_atdat->f");
892         stat = cudaMalloc((void **)&d_atdat->xq, nalloc*sizeof(*d_atdat->xq));
893         CU_RET_ERR(stat, "cudaMalloc failed on d_atdat->xq");
894
895         stat = cudaMalloc((void **)&d_atdat->atom_types, nalloc*sizeof(*d_atdat->atom_types));
896         CU_RET_ERR(stat, "cudaMalloc failed on d_atdat->atom_types");
897
898         d_atdat->nalloc = nalloc;
899         realloced       = true;
900     }
901
902     d_atdat->natoms       = natoms;
903     d_atdat->natoms_local = nbat->natoms_local;
904
905     /* need to clear GPU f output if realloc happened */
906     if (realloced)
907     {
908         nbnxn_cuda_clear_f(cu_nb, nalloc);
909     }
910
911     cu_copy_H2D_async(d_atdat->atom_types, nbat->type,
912                       natoms*sizeof(*d_atdat->atom_types), ls);
913
914     if (bDoTime)
915     {
916         stat = cudaEventRecord(timers->stop_atdat, ls);
917         CU_RET_ERR(stat, "cudaEventRecord failed");
918     }
919 }
920
921 void nbnxn_cuda_free(nbnxn_cuda_ptr_t cu_nb)
922 {
923     cudaError_t      stat;
924     cu_atomdata_t   *atdat;
925     cu_nbparam_t    *nbparam;
926     cu_plist_t      *plist, *plist_nl;
927     cu_timers_t     *timers;
928
929     if (cu_nb == NULL)
930     {
931         return;
932     }
933
934     atdat       = cu_nb->atdat;
935     nbparam     = cu_nb->nbparam;
936     plist       = cu_nb->plist[eintLocal];
937     plist_nl    = cu_nb->plist[eintNonlocal];
938     timers      = cu_nb->timers;
939
940     if (nbparam->eeltype == eelCuEWALD_TAB || nbparam->eeltype == eelCuEWALD_TAB_TWIN)
941     {
942
943 #ifdef TEXOBJ_SUPPORTED
944         /* Only device CC >= 3.0 (Kepler and later) support texture objects */
945         if (cu_nb->dev_info->prop.major >= 3)
946         {
947             stat = cudaDestroyTextureObject(nbparam->coulomb_tab_texobj);
948             CU_RET_ERR(stat, "cudaDestroyTextureObject on coulomb_tab_texobj failed");
949         }
950         else
951 #endif
952         {
953             stat = cudaUnbindTexture(nbnxn_cuda_get_coulomb_tab_texref());
954             CU_RET_ERR(stat, "cudaUnbindTexture on coulomb_tab_texref failed");
955         }
956         cu_free_buffered(nbparam->coulomb_tab, &nbparam->coulomb_tab_size);
957     }
958
959     stat = cudaEventDestroy(cu_nb->nonlocal_done);
960     CU_RET_ERR(stat, "cudaEventDestroy failed on timers->nonlocal_done");
961     stat = cudaEventDestroy(cu_nb->misc_ops_done);
962     CU_RET_ERR(stat, "cudaEventDestroy failed on timers->misc_ops_done");
963
964     if (cu_nb->bDoTime)
965     {
966         stat = cudaEventDestroy(timers->start_atdat);
967         CU_RET_ERR(stat, "cudaEventDestroy failed on timers->start_atdat");
968         stat = cudaEventDestroy(timers->stop_atdat);
969         CU_RET_ERR(stat, "cudaEventDestroy failed on timers->stop_atdat");
970
971         /* The non-local counters/stream (second in the array) are needed only with DD. */
972         for (int i = 0; i <= (cu_nb->bUseTwoStreams ? 1 : 0); i++)
973         {
974             stat = cudaEventDestroy(timers->start_nb_k[i]);
975             CU_RET_ERR(stat, "cudaEventDestroy failed on timers->start_nb_k");
976             stat = cudaEventDestroy(timers->stop_nb_k[i]);
977             CU_RET_ERR(stat, "cudaEventDestroy failed on timers->stop_nb_k");
978
979             stat = cudaEventDestroy(timers->start_pl_h2d[i]);
980             CU_RET_ERR(stat, "cudaEventDestroy failed on timers->start_pl_h2d");
981             stat = cudaEventDestroy(timers->stop_pl_h2d[i]);
982             CU_RET_ERR(stat, "cudaEventDestroy failed on timers->stop_pl_h2d");
983
984             stat = cudaStreamDestroy(cu_nb->stream[i]);
985             CU_RET_ERR(stat, "cudaStreamDestroy failed on stream");
986
987             stat = cudaEventDestroy(timers->start_nb_h2d[i]);
988             CU_RET_ERR(stat, "cudaEventDestroy failed on timers->start_nb_h2d");
989             stat = cudaEventDestroy(timers->stop_nb_h2d[i]);
990             CU_RET_ERR(stat, "cudaEventDestroy failed on timers->stop_nb_h2d");
991
992             stat = cudaEventDestroy(timers->start_nb_d2h[i]);
993             CU_RET_ERR(stat, "cudaEventDestroy failed on timers->start_nb_d2h");
994             stat = cudaEventDestroy(timers->stop_nb_d2h[i]);
995             CU_RET_ERR(stat, "cudaEventDestroy failed on timers->stop_nb_d2h");
996         }
997     }
998
999 #ifdef TEXOBJ_SUPPORTED
1000     /* Only device CC >= 3.0 (Kepler and later) support texture objects */
1001     if (cu_nb->dev_info->prop.major >= 3)
1002     {
1003         stat = cudaDestroyTextureObject(nbparam->nbfp_texobj);
1004         CU_RET_ERR(stat, "cudaDestroyTextureObject on nbfp_texobj failed");
1005     }
1006     else
1007 #endif
1008     {
1009         stat = cudaUnbindTexture(nbnxn_cuda_get_nbfp_texref());
1010         CU_RET_ERR(stat, "cudaUnbindTexture on nbfp_texref failed");
1011     }
1012     cu_free_buffered(nbparam->nbfp);
1013
1014     if (nbparam->vdwtype == evdwCuEWALDGEOM || nbparam->vdwtype == evdwCuEWALDLB)
1015     {
1016 #ifdef TEXOBJ_SUPPORTED
1017         /* Only device CC >= 3.0 (Kepler and later) support texture objects */
1018         if (cu_nb->dev_info->prop.major >= 3)
1019         {
1020             stat = cudaDestroyTextureObject(nbparam->nbfp_comb_texobj);
1021             CU_RET_ERR(stat, "cudaDestroyTextureObject on nbfp_comb_texobj failed");
1022         }
1023         else
1024 #endif
1025         {
1026             stat = cudaUnbindTexture(nbnxn_cuda_get_nbfp_comb_texref());
1027             CU_RET_ERR(stat, "cudaUnbindTexture on nbfp_comb_texref failed");
1028         }
1029         cu_free_buffered(nbparam->nbfp_comb);
1030     }
1031
1032     stat = cudaFree(atdat->shift_vec);
1033     CU_RET_ERR(stat, "cudaFree failed on atdat->shift_vec");
1034     stat = cudaFree(atdat->fshift);
1035     CU_RET_ERR(stat, "cudaFree failed on atdat->fshift");
1036
1037     stat = cudaFree(atdat->e_lj);
1038     CU_RET_ERR(stat, "cudaFree failed on atdat->e_lj");
1039     stat = cudaFree(atdat->e_el);
1040     CU_RET_ERR(stat, "cudaFree failed on atdat->e_el");
1041
1042     cu_free_buffered(atdat->f, &atdat->natoms, &atdat->nalloc);
1043     cu_free_buffered(atdat->xq);
1044     cu_free_buffered(atdat->atom_types, &atdat->ntypes);
1045
1046     cu_free_buffered(plist->sci, &plist->nsci, &plist->sci_nalloc);
1047     cu_free_buffered(plist->cj4, &plist->ncj4, &plist->cj4_nalloc);
1048     cu_free_buffered(plist->excl, &plist->nexcl, &plist->excl_nalloc);
1049     if (cu_nb->bUseTwoStreams)
1050     {
1051         cu_free_buffered(plist_nl->sci, &plist_nl->nsci, &plist_nl->sci_nalloc);
1052         cu_free_buffered(plist_nl->cj4, &plist_nl->ncj4, &plist_nl->cj4_nalloc);
1053         cu_free_buffered(plist_nl->excl, &plist_nl->nexcl, &plist->excl_nalloc);
1054     }
1055
1056     sfree(atdat);
1057     sfree(nbparam);
1058     sfree(plist);
1059     if (cu_nb->bUseTwoStreams)
1060     {
1061         sfree(plist_nl);
1062     }
1063     sfree(timers);
1064     sfree(cu_nb->timings);
1065     sfree(cu_nb);
1066
1067     if (debug)
1068     {
1069         fprintf(debug, "Cleaned up CUDA data structures.\n");
1070     }
1071 }
1072
1073 void cu_synchstream_atdat(nbnxn_cuda_ptr_t cu_nb, int iloc)
1074 {
1075     cudaError_t  stat;
1076     cudaStream_t stream = cu_nb->stream[iloc];
1077
1078     stat = cudaStreamWaitEvent(stream, cu_nb->timers->stop_atdat, 0);
1079     CU_RET_ERR(stat, "cudaStreamWaitEvent failed");
1080 }
1081
1082 wallclock_gpu_t * nbnxn_cuda_get_timings(nbnxn_cuda_ptr_t cu_nb)
1083 {
1084     return (cu_nb != NULL && cu_nb->bDoTime) ? cu_nb->timings : NULL;
1085 }
1086
1087 void nbnxn_cuda_reset_timings(nonbonded_verlet_t* nbv)
1088 {
1089     if (nbv->cu_nbv && nbv->cu_nbv->bDoTime)
1090     {
1091         init_timings(nbv->cu_nbv->timings);
1092     }
1093 }
1094
1095 int nbnxn_cuda_min_ci_balanced(nbnxn_cuda_ptr_t cu_nb)
1096 {
1097     return cu_nb != NULL ?
1098            gpu_min_ci_balanced_factor*cu_nb->dev_info->prop.multiProcessorCount : 0;
1099
1100 }
1101
1102 gmx_bool nbnxn_cuda_is_kernel_ewald_analytical(const nbnxn_cuda_ptr_t cu_nb)
1103 {
1104     return ((cu_nb->nbparam->eeltype == eelCuEWALD_ANA) ||
1105             (cu_nb->nbparam->eeltype == eelCuEWALD_ANA_TWIN));
1106 }