[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

numrecs isolation modifications



> I will look forward to hearing from you when
> you have modified the source code for
> the variable 'numrecs'.
>
> With warm regards,
>
> Harsh

Harsh:

Attached find a collection of diffs to files in src/librc
relative to the netcdf-3.4 release.

The affected files are nc.h, nc.c, dim.c, v1hpg.c, and putget.m4.

After applying the patch, all accesses to the 'numrecs' field of
'struct NC' goes via three macros. If the macros were functions,
this is what their signatures would be:

        int NC_get_numrecs(const NC *ncp);
                /* returns the current value of numrecs */

        void NC_set_numrecs(NC *ncp, size_t newvalue);
                /* sets the numrecs value to newvalue */

        void NC_increase_numrecs(NC *ncp, size_t least_upper_bound);
                /* if the numrecs value is less than least_upper_bound,
                        set it to least_upper_bound. Otherwise, do nothing */

The macros are defined in nc.h, just below the definition of struct NC.

Without knowing the actual mechanism used to synchronize the numrecs
value between processes, it is not clear to me whether the
NC_increase_numrecs()
entry point is actually needed. It is only used in one place,
putget.c:NCvnrecs(). Whoever does the parallelization should think
carefully about the implementation the loop where this is used.
The issue is avoided entirely when NC_NOFILL is set.

As proof against blunders,
I have compiled and tested this on an SGI using -n64.

Hope this helps.

Good luck.

-glenn



Index: dim.c
===================================================================
RCS file: /upc/share/CVS/netcdf-3/libsrc/dim.c,v
retrieving revision 1.72
diff -c -r1.72 dim.c
*** dim.c       1997/12/12 00:12:43     1.72
--- dim.c       1998/05/13 20:45:28
***************
*** 403,409 ****
        if(sizep != 0)
        {
                if(dimp->size == NC_UNLIMITED)
!                       *sizep = ncp->numrecs;
                else
                        *sizep = dimp->size;    
        }
--- 403,409 ----
        if(sizep != 0)
        {
                if(dimp->size == NC_UNLIMITED)
!                       *sizep = NC_get_numrecs(ncp);
                else
                        *sizep = dimp->size;    
        }
***************
*** 455,461 ****
        if(lenp != 0)
        {
                if(dimp->size == NC_UNLIMITED)
!                       *lenp = ncp->numrecs;
                else
                        *lenp = dimp->size;     
        }
--- 455,461 ----
        if(lenp != 0)
        {
                if(dimp->size == NC_UNLIMITED)
!                       *lenp = NC_get_numrecs(ncp);
                else
                        *lenp = dimp->size;     
        }
Index: nc.c
===================================================================
RCS file: /upc/share/CVS/netcdf-3/libsrc/nc.c,v
retrieving revision 2.113
diff -c -r2.113 nc.c
*** nc.c        1997/12/12 00:12:44     2.113
--- nc.c        1998/05/13 21:21:03
***************
*** 125,131 ****
        ncp->begin_var = ref->begin_var;
        ncp->begin_rec = ref->begin_rec;
        ncp->recsize = ref->recsize;
!       ncp->numrecs = ref->numrecs;
        return ncp;
  err:
        free_NC(ncp);
--- 125,131 ----
        ncp->begin_var = ref->begin_var;
        ncp->begin_rec = ref->begin_rec;
        ncp->recsize = ref->recsize;
!       NC_set_numrecs(ncp, NC_get_numrecs(ref));
        return ncp;
  err:
        free_NC(ncp);
***************
*** 264,270 ****
                ncp->recsize = *last->dsizes * last->xsz;
  
        if(NC_IsNew(ncp))
!               ncp->numrecs = 0;
  
  }
  
--- 264,270 ----
                ncp->recsize = *last->dsizes * last->xsz;
  
        if(NC_IsNew(ncp))
!               NC_set_numrecs(ncp, 0);
  
  }
  
***************
*** 278,283 ****
--- 278,284 ----
  {
        int status = NC_NOERR;
        const void *xp;
+       size_t nrecs = NC_get_numrecs(ncp);
  
        assert(!NC_indef(ncp));
  
***************
*** 289,300 ****
        if(status != NC_NOERR)
                return status;
  
!       status = ncx_get_size_t(&xp, &ncp->numrecs);
  
        (void) ncp->nciop->rel(ncp->nciop, NC_NUMRECS_OFFSET, 0);
  
        if(status == NC_NOERR)
                fClr(ncp->flags, NC_NDIRTY);
  
        return status;
  }
--- 290,304 ----
        if(status != NC_NOERR)
                return status;
  
!       status = ncx_get_size_t(&xp, &nrecs);
  
        (void) ncp->nciop->rel(ncp->nciop, NC_NUMRECS_OFFSET, 0);
  
        if(status == NC_NOERR)
+       {
+               NC_set_numrecs(ncp, nrecs);
                fClr(ncp->flags, NC_NDIRTY);
+       }
  
        return status;
  }
***************
*** 318,324 ****
        if(status != NC_NOERR)
                return status;
  
!       status = ncx_put_size_t(&xp, &ncp->numrecs);
  
        (void) ncp->nciop->rel(ncp->nciop, NC_NUMRECS_OFFSET, RGN_MODIFIED);
  
--- 322,331 ----
        if(status != NC_NOERR)
                return status;
  
!       {
!               const size_t nrecs = NC_get_numrecs(ncp);
!               status = ncx_put_size_t(&xp, &nrecs);
!       }
  
        (void) ncp->nciop->rel(ncp->nciop, NC_NUMRECS_OFFSET, RGN_MODIFIED);
  
***************
*** 433,440 ****
  {
        NC_var ** const gnu_varpp = (NC_var **)gnu->vars.value;
  
        int recno = 0;
!       for(; recno < old->numrecs; recno++)
        {
                int varid = (int)old->vars.nelems;
                for(; varid < (int)gnu->vars.nelems; varid++)
--- 440,448 ----
  {
        NC_var ** const gnu_varpp = (NC_var **)gnu->vars.value;
  
+       const int old_nrecs = (int) NC_get_numrecs(old);
        int recno = 0;
!       for(; recno < old_nrecs; recno++)
        {
                int varid = (int)old->vars.nelems;
                for(; varid < (int)gnu->vars.nelems; varid++)
***************
*** 501,509 ****
        NC_var *old_varp;
        off_t gnu_off;
        off_t old_off;
        
        /* Don't parallelize this loop */
!       for(recno = (int)old->numrecs -1; recno >= 0; recno--)
        {
        /* Don't parallelize this loop */
        for(varid = (int)old->vars.nelems -1; varid >= 0; varid--)
--- 509,518 ----
        NC_var *old_varp;
        off_t gnu_off;
        off_t old_off;
+       const size_t old_nrecs = NC_get_numrecs(old);
        
        /* Don't parallelize this loop */
!       for(recno = (int)old_nrecs -1; recno >= 0; recno--)
        {
        /* Don't parallelize this loop */
        for(varid = (int)old->vars.nelems -1; varid >= 0; varid--)
***************
*** 535,541 ****
        }
        }
  
!       gnu->numrecs = old->numrecs;
  
        return NC_NOERR;
  }
--- 544,550 ----
        }
        }
  
!       NC_set_numrecs(gnu, old_nrecs);
  
        return NC_NOERR;
  }
***************
*** 655,661 ****
        off_t old_off;
        
  
!       for(recno = 0; recno < old->numrecs; recno++)
        {
        for(varid = 0; (size_t) varid < gnu->vars.nelems; varid++)
        {
--- 664,671 ----
        off_t old_off;
        
  
!       const size_t old_nrecs = NC_get_numrecs(old);
!       for(recno = 0; recno < old_nrecs; recno++)
        {
        for(varid = 0; (size_t) varid < gnu->vars.nelems; varid++)
        {
***************
*** 700,706 ****
        }
        }
  
!       gnu->numrecs = old->numrecs;
  
        return NC_NOERR;
  }
--- 710,716 ----
        }
        }
  
!       NC_set_numrecs(gnu, old_nrecs);
  
        return NC_NOERR;
  }
Index: nc.h
===================================================================
RCS file: /upc/share/CVS/netcdf-3/libsrc/nc.h,v
retrieving revision 2.69
diff -c -r2.69 nc.h
*** nc.h        1997/12/08 22:04:45     2.69
--- nc.h        1998/05/13 22:17:40
***************
*** 282,287 ****
--- 282,296 ----
  #define NC_doNsync(ncp) \
        fIsSet((ncp)->flags, NC_NSYNC)
  
+ #define NC_get_numrecs(ncp) \
+       ((ncp)->numrecs)
+ 
+ #define NC_set_numrecs(ncp, nrecs) \
+       {((ncp)->numrecs = (nrecs));}
+ 
+ #define NC_increase_numrecs(ncp, nrecs) \
+       {if((nrecs) > (ncp)->numrecs) ((ncp)->numrecs = (nrecs));}
+ 
  /* Begin defined in nc.c */
  
  extern int
Index: putget.m4
===================================================================
RCS file: /upc/share/CVS/netcdf-3/libsrc/putget.m4,v
retrieving revision 2.46
diff -c -r2.46 putget.m4
*** putget.m4   1997/12/17 18:16:33     2.46
--- putget.m4   1998/05/13 22:15:05
***************
*** 336,342 ****
  {
        int status = NC_NOERR;
  
!       if(numrecs > ncp->numrecs)
        {
  
  
--- 336,342 ----
  {
        int status = NC_NOERR;
  
!       if(numrecs > NC_get_numrecs(ncp))
        {
  
  
***************
*** 352,374 ****
  
                if(!NC_dofill(ncp))
                {
!                       /* Go directly to jail, do not pass go */
!                       ncp->numrecs = numrecs;
                }
                else
                {
!                       size_t unfilled = numrecs - ncp->numrecs;
!                       size_t ii;
!                       
!                       for(ii = 0; ii < unfilled; ii++, ncp->numrecs++)
                        {
                                status = NCfillrecord(ncp,
                                        (const NC_var *const*)ncp->vars.value,
!                                       ncp->numrecs);
                                if(status != NC_NOERR)
                                {
                                        break;
                                }
                        }
                        if(status != NC_NOERR)
                                return status;
--- 352,374 ----
  
                if(!NC_dofill(ncp))
                {
!                       /* Simply set the new numrecs value */
!                       NC_set_numrecs(ncp, numrecs);
                }
                else
                {
!                       /* Fill each record out to numrecs */
!                       size_t cur_nrecs;
!                       while((cur_nrecs = NC_get_numrecs(ncp)) < numrecs)
                        {
                                status = NCfillrecord(ncp,
                                        (const NC_var *const*)ncp->vars.value,
!                                       cur_nrecs);
                                if(status != NC_NOERR)
                                {
                                        break;
                                }
+                               NC_increase_numrecs(ncp, cur_nrecs +1);
                        }
                        if(status != NC_NOERR)
                                return status;
***************
*** 400,406 ****
        {
                if(*coord > X_INT_MAX)
                        return NC_EINVALCOORDS; /* sanity check */
!               if(NC_readonly(ncp) && *coord >= ncp->numrecs)
                {
                        if(!NC_doNsync(ncp))
                                return NC_EINVALCOORDS;
--- 400,406 ----
        {
                if(*coord > X_INT_MAX)
                        return NC_EINVALCOORDS; /* sanity check */
!               if(NC_readonly(ncp) && *coord >= NC_get_numrecs(ncp))
                {
                        if(!NC_doNsync(ncp))
                                return NC_EINVALCOORDS;
***************
*** 410,416 ****
                                const int status = read_numrecs(ncp);
                                if(status != NC_NOERR)
                                        return status;
!                               if(*coord >= ncp->numrecs)
                                        return NC_EINVALCOORDS;
                        }
                }
--- 410,416 ----
                                const int status = read_numrecs(ncp);
                                if(status != NC_NOERR)
                                        return status;
!                               if(*coord >= NC_get_numrecs(ncp))
                                        return NC_EINVALCOORDS;
                        }
                }
***************
*** 1410,1416 ****
  
        if(IS_RECVAR(varp))
        {
!               if(*start + *edges > ncp->numrecs)
                        return NC_EEDGE;
                if(varp->ndims == 1 && ncp->recsize <= varp->len)
                {
--- 1410,1416 ----
  
        if(IS_RECVAR(varp))
        {
!               if(*start + *edges > NC_get_numrecs(ncp))
                        return NC_EEDGE;
                if(varp->ndims == 1 && ncp->recsize <= varp->len)
                {
***************
*** 1584,1601 ****
                        && ncp->recsize <= varp->len)
        {
                /* one dimensional && the only record variable  */
!               return(putNCv_$1(ncp, varp, coord_zero, ncp->numrecs, value));
        }
        /* else */
  
        {
        ALLOC_ONSTACK(coord, size_t, varp->ndims);
        size_t elemsPerRec = 1;
        (void) memset(coord, 0, varp->ndims * sizeof(size_t));
        /* TODO: fix dsizes to avoid this nonsense */
        if(varp->ndims > 1)
                elemsPerRec = varp->dsizes[1];
!       while(*coord < ncp->numrecs)
        {
                const int lstatus = putNCv_$1(ncp, varp, coord, elemsPerRec,
                                 value);
--- 1584,1603 ----
                        && ncp->recsize <= varp->len)
        {
                /* one dimensional && the only record variable  */
!               return(putNCv_$1(ncp, varp, coord_zero, NC_get_numrecs(ncp),
!                       value));
        }
        /* else */
  
        {
        ALLOC_ONSTACK(coord, size_t, varp->ndims);
        size_t elemsPerRec = 1;
+       const size_t nrecs = NC_get_numrecs(ncp);
        (void) memset(coord, 0, varp->ndims * sizeof(size_t));
        /* TODO: fix dsizes to avoid this nonsense */
        if(varp->ndims > 1)
                elemsPerRec = varp->dsizes[1];
!       while(*coord < nrecs)
        {
                const int lstatus = putNCv_$1(ncp, varp, coord, elemsPerRec,
                                 value);
***************
*** 1673,1690 ****
                        && ncp->recsize <= varp->len)
        {
                /* one dimensional && the only record variable  */
!               return(getNCv_$1(ncp, varp, coord_zero, ncp->numrecs, value));
        }
        /* else */
  
        {
        ALLOC_ONSTACK(coord, size_t, varp->ndims);
        size_t elemsPerRec = 1;
        (void) memset(coord, 0, varp->ndims * sizeof(size_t));
        /* TODO: fix dsizes to avoid this nonsense */
        if(varp->ndims > 1)
                elemsPerRec = varp->dsizes[1];
!       while(*coord < ncp->numrecs)
        {
                const int lstatus = getNCv_$1(ncp, varp, coord, elemsPerRec,
                                value);
--- 1675,1694 ----
                        && ncp->recsize <= varp->len)
        {
                /* one dimensional && the only record variable  */
!               return(getNCv_$1(ncp, varp, coord_zero, NC_get_numrecs(ncp),
!                       value));
        }
        /* else */
  
        {
        ALLOC_ONSTACK(coord, size_t, varp->ndims);
        size_t elemsPerRec = 1;
+       const size_t nrecs = NC_get_numrecs(ncp);
        (void) memset(coord, 0, varp->ndims * sizeof(size_t));
        /* TODO: fix dsizes to avoid this nonsense */
        if(varp->ndims > 1)
                elemsPerRec = varp->dsizes[1];
!       while(*coord < nrecs)
        {
                const int lstatus = getNCv_$1(ncp, varp, coord, elemsPerRec,
                                value);
***************
*** 1821,1827 ****
                        myedges[idim] = edges != NULL
                                ? edges[idim]
                                : idim == 0 && IS_RECVAR (varp)
!                               ? ncp->numrecs - mystart[idim]
                                : varp->shape[idim] - mystart[idim];
                        mystride[idim] = stride != NULL
                                ? stride[idim]
--- 1825,1831 ----
                        myedges[idim] = edges != NULL
                                ? edges[idim]
                                : idim == 0 && IS_RECVAR (varp)
!                               ? NC_get_numrecs(ncp) - mystart[idim]
                                : varp->shape[idim] - mystart[idim];
                        mystride[idim] = stride != NULL
                                ? stride[idim]
***************
*** 2003,2009 ****
                {
                        size_t dimlen = 
                                idim == 0 && IS_RECVAR (varp)
!                                       ? ncp->numrecs : varp->shape[idim];
                        if (mystart[idim] >= dimlen)
                        {
                                status = NC_EINVALCOORDS;
--- 2007,2014 ----
                {
                        size_t dimlen = 
                                idim == 0 && IS_RECVAR (varp)
!                                       ? NC_get_numrecs(ncp)
!                                         : varp->shape[idim];
                        if (mystart[idim] >= dimlen)
                        {
                                status = NC_EINVALCOORDS;
***************
*** 2562,2568 ****
                return NC_EINDEFINE;
        }
  
!       if(recnum >= ncp->numrecs)
        {
                return NC_EINVALCOORDS;
        }
--- 2567,2573 ----
                return NC_EINDEFINE;
        }
  
!       if(recnum >= NC_get_numrecs(ncp))
        {
                return NC_EINVALCOORDS;
        }
***************
*** 2642,2650 ****
         */
        {
        ALLOC_ONSTACK(coord, size_t, invp->ndims);
        (void) memcpy(coord, invp->shape, invp->ndims * sizeof(size_t));
        if(IS_RECVAR(invp))
!               *coord = inncp->numrecs;
        
        {
        size_t ii = 0;
--- 2647,2656 ----
         */
        {
        ALLOC_ONSTACK(coord, size_t, invp->ndims);
+       const size_t nrecs = NC_get_numrecs(inncp);
        (void) memcpy(coord, invp->shape, invp->ndims * sizeof(size_t));
        if(IS_RECVAR(invp))
!               *coord = nrecs;
        
        {
        size_t ii = 0;
***************
*** 2670,2680 ****
        }
        /* else */
  
!       status = NCvnrecs(outncp, inncp->numrecs);
        if(status != NC_NOERR)
                goto done;
  
!       for( /*NADA*/; *coord < inncp->numrecs; (*coord)++)
        {
                status = NCxvarcpy(inncp, invp, coord,
                                outncp, outvp, coord,
--- 2676,2686 ----
        }
        /* else */
  
!       status = NCvnrecs(outncp, nrecs);
        if(status != NC_NOERR)
                goto done;
  
!       for( /*NADA*/; *coord < nrecs; (*coord)++)
        {
                status = NCxvarcpy(inncp, invp, coord,
                                outncp, outvp, coord,
Index: v1hpg.c
===================================================================
RCS file: /upc/share/CVS/netcdf-3/libsrc/v1hpg.c,v
retrieving revision 1.49
diff -c -r1.49 v1hpg.c
*** v1hpg.c     1997/12/18 20:03:28     1.49
--- v1hpg.c     1998/05/13 21:25:19
***************
*** 1202,1210 ****
        if(status != ENOERR)
                goto release;
  
!       status = ncx_put_size_t(&ps.pos, &ncp->numrecs);
        if(status != ENOERR)
                goto release;
  
        assert((char *)ps.pos < (char *)ps.end);
  
--- 1202,1213 ----
        if(status != ENOERR)
                goto release;
  
!       {
!       const size_t nrecs = NC_get_numrecs(ncp);
!       status = ncx_put_size_t(&ps.pos, &nrecs);
        if(status != ENOERR)
                goto release;
+       }
  
        assert((char *)ps.pos < (char *)ps.end);
  
***************
*** 1287,1295 ****
                }
        }
        
!       status = ncx_get_size_t((const void **)(&gs.pos), &ncp->numrecs);
        if(status != ENOERR)
                goto unwind_get;
  
        assert((char *)gs.pos < (char *)gs.end);
  
--- 1290,1302 ----
                }
        }
        
!       {
!       size_t nrecs = 0;
!       status = ncx_get_size_t((const void **)(&gs.pos), &nrecs);
        if(status != ENOERR)
                goto unwind_get;
+       NC_set_numrecs(ncp, nrecs);
+       }
  
        assert((char *)gs.pos < (char *)gs.end);