From 7594a2c491e20a01bbb70e7caa18fa5f7facea20 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Sun, 2 Oct 2011 23:44:11 -0400 Subject: [PATCH] add OpenMP support for multi-neigbor lists --- src/neigh_half_multi.cpp | 134 +++++++++++++++++++++++++-------------- 1 file changed, 86 insertions(+), 48 deletions(-) diff --git a/src/neigh_half_multi.cpp b/src/neigh_half_multi.cpp index 04e25931be..319a32f10f 100644 --- a/src/neigh_half_multi.cpp +++ b/src/neigh_half_multi.cpp @@ -14,8 +14,13 @@ #include "neighbor.h" #include "neigh_list.h" #include "atom.h" +#include "comm.h" #include "error.h" +#if defined(_OPENMP) +#include +#endif + using namespace LAMMPS_NS; /* ---------------------------------------------------------------------- @@ -28,15 +33,24 @@ using namespace LAMMPS_NS; void Neighbor::half_multi_no_newton(NeighList *list) { + // bin local & ghost atoms + + bin_atoms(); + + const int nthreads = comm->nthreads; + const int nlocal = (includegroup) ? atom->nfirst : atom->nlocal; + + NEIGH_OMP_INIT; +#if defined(_OPENMP) +#pragma omp parallel default(none) shared(list) +#endif + NEIGH_OMP_SETUP(nlocal); + int i,j,k,n,itype,jtype,ibin,which,ns; double xtmp,ytmp,ztmp,delx,dely,delz,rsq; int *neighptr,*s; double *cutsq,*distsq; - // bin local & ghost atoms - - bin_atoms(); - // loop over each atom, storing neighbors int **special = atom->special; @@ -47,31 +61,33 @@ void Neighbor::half_multi_no_newton(NeighList *list) int *type = atom->type; int *mask = atom->mask; int *molecule = atom->molecule; - int nlocal = atom->nlocal; int molecular = atom->molecular; - if (includegroup) nlocal = atom->nfirst; int *ilist = list->ilist; int *numneigh = list->numneigh; int **firstneigh = list->firstneigh; - int **pages = list->pages; int *nstencil_multi = list->nstencil_multi; int **stencil_multi = list->stencil_multi; double **distsq_multi = list->distsq_multi; - int inum = 0; - int npage = 0; + // each thread works on its own page + int npage = tid; int npnt = 0; - for (i = 0; i < nlocal; i++) { + for (i = ifrom; i < ito; i++) { if (pgsize - npnt < oneatom) { npnt = 0; - npage++; - if (npage == list->maxpage) pages = list->add_pages(); + npage += nthreads; + // only one thread at a time may check whether we + // need new neighbor list pages and then add to them. +#if defined(_OPENMP) +#pragma omp critical +#endif + if (npage >= list->maxpage) list->add_pages(nthreads); } - neighptr = &pages[npage][npnt]; + neighptr = &(list->pages[npage][npnt]); n = 0; itype = type[i]; @@ -112,15 +128,15 @@ void Neighbor::half_multi_no_newton(NeighList *list) } } - ilist[inum++] = i; + ilist[i] = i; firstneigh[i] = neighptr; numneigh[i] = n; npnt += n; if (n > oneatom || npnt >= pgsize) error->one(FLERR,"Neighbor list overflow, boost neigh_modify one or page"); } - - list->inum = inum; + NEIGH_OMP_CLOSE; + list->inum = nlocal; } /* ---------------------------------------------------------------------- @@ -132,15 +148,24 @@ void Neighbor::half_multi_no_newton(NeighList *list) void Neighbor::half_multi_newton(NeighList *list) { + // bin local & ghost atoms + + bin_atoms(); + + const int nthreads = comm->nthreads; + const int nlocal = (includegroup) ? atom->nfirst : atom->nlocal; + + NEIGH_OMP_INIT; +#if defined(_OPENMP) +#pragma omp parallel default(none) shared(list) +#endif + NEIGH_OMP_SETUP(nlocal); + int i,j,k,n,itype,jtype,ibin,which,ns; double xtmp,ytmp,ztmp,delx,dely,delz,rsq; int *neighptr,*s; double *cutsq,*distsq; - // bin local & ghost atoms - - bin_atoms(); - // loop over each atom, storing neighbors int **special = atom->special; @@ -151,31 +176,33 @@ void Neighbor::half_multi_newton(NeighList *list) int *type = atom->type; int *mask = atom->mask; int *molecule = atom->molecule; - int nlocal = atom->nlocal; int molecular = atom->molecular; - if (includegroup) nlocal = atom->nfirst; int *ilist = list->ilist; int *numneigh = list->numneigh; int **firstneigh = list->firstneigh; - int **pages = list->pages; int *nstencil_multi = list->nstencil_multi; int **stencil_multi = list->stencil_multi; double **distsq_multi = list->distsq_multi; - int inum = 0; - int npage = 0; + // each thread works on its own page + int npage = tid; int npnt = 0; - for (i = 0; i < nlocal; i++) { + for (i = ifrom; i < ito; i++) { if (pgsize - npnt < oneatom) { npnt = 0; - npage++; - if (npage == list->maxpage) pages = list->add_pages(); + npage += nthreads; + // only one thread at a time may check whether we + // need new neighbor list pages and then add to them. +#if defined(_OPENMP) +#pragma omp critical +#endif + if (npage >= list->maxpage) list->add_pages(nthreads); } - neighptr = &pages[npage][npnt]; + neighptr = &(list->pages[npage][npnt]); n = 0; itype = type[i]; @@ -241,15 +268,15 @@ void Neighbor::half_multi_newton(NeighList *list) } } - ilist[inum++] = i; + ilist[i] = i; firstneigh[i] = neighptr; numneigh[i] = n; npnt += n; if (n > oneatom || npnt >= pgsize) error->one(FLERR,"Neighbor list overflow, boost neigh_modify one or page"); } - - list->inum = inum; + NEIGH_OMP_CLOSE; + list->inum = nlocal; } /* ---------------------------------------------------------------------- @@ -261,15 +288,24 @@ void Neighbor::half_multi_newton(NeighList *list) void Neighbor::half_multi_newton_tri(NeighList *list) { + // bin local & ghost atoms + + bin_atoms(); + + const int nthreads = comm->nthreads; + const int nlocal = (includegroup) ? atom->nfirst : atom->nlocal; + + NEIGH_OMP_INIT; +#if defined(_OPENMP) +#pragma omp parallel default(none) shared(list) +#endif + NEIGH_OMP_SETUP(nlocal); + int i,j,k,n,itype,jtype,ibin,which,ns; double xtmp,ytmp,ztmp,delx,dely,delz,rsq; int *neighptr,*s; double *cutsq,*distsq; - // bin local & ghost atoms - - bin_atoms(); - // loop over each atom, storing neighbors int **special = atom->special; @@ -280,31 +316,33 @@ void Neighbor::half_multi_newton_tri(NeighList *list) int *type = atom->type; int *mask = atom->mask; int *molecule = atom->molecule; - int nlocal = atom->nlocal; int molecular = atom->molecular; - if (includegroup) nlocal = atom->nfirst; int *ilist = list->ilist; int *numneigh = list->numneigh; int **firstneigh = list->firstneigh; - int **pages = list->pages; int *nstencil_multi = list->nstencil_multi; int **stencil_multi = list->stencil_multi; double **distsq_multi = list->distsq_multi; - int inum = 0; - int npage = 0; + // each thread works on its own page + int npage = tid; int npnt = 0; - for (i = 0; i < nlocal; i++) { + for (i = ifrom; i < ito; i++) { if (pgsize - npnt < oneatom) { npnt = 0; - npage++; - if (npage == list->maxpage) pages = list->add_pages(); + npage += nthreads; + // only one thread at a time may check whether we + // need new neighbor list pages and then add to them. +#if defined(_OPENMP) +#pragma omp critical +#endif + if (npage >= list->maxpage) list->add_pages(nthreads); } - neighptr = &pages[npage][npnt]; + neighptr = &(list->pages[npage][npnt]); n = 0; itype = type[i]; @@ -354,13 +392,13 @@ void Neighbor::half_multi_newton_tri(NeighList *list) } } - ilist[inum++] = i; + ilist[i] = i; firstneigh[i] = neighptr; numneigh[i] = n; npnt += n; if (n > oneatom || npnt >= pgsize) error->one(FLERR,"Neighbor list overflow, boost neigh_modify one or page"); } - - list->inum = inum; + NEIGH_OMP_CLOSE; + list->inum = nlocal; }