<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; font-family: Calibri, sans-serif; font-size: 14px; color: rgb(0, 0, 0);">
<div>
<div>I don’t think the other arguments should be skipped or ignored — specifying an invalid varid or dimid or ncid should be an error no matter what the request size is.</div>
<div><br>
</div>
<div>I think that the start value is a special case (and not really that special depending on how you look at it). In a parallel case, each rank will typically be handling a certain number of values in the “field” or variable.  The total size of the variable
 is the sum of the number of values handled by each rank and the “start” value for each rank is the sum of the number of values handled by previous ranks.</div>
<div><br>
</div>
<div>As an example, assume there are four ranks and each handles 10 values.  Then have that the total size of the variable is 40 and the start values are 0, 10, 20, 30 with request sizes of 10, 10, 10, 10. </div>
<div><br>
</div>
<div>Now, if  we have a similar variable which exists on ranks 0 and 3 with request sizes of 20, 0, 0, 20. The total size is still 40 and the start values are 0, 20, 20, 20 and everything works fine.</div>
<div><br>
</div>
<div>If we now have a similar variable which only exists on ranks 1 and 2, and request sizes of 0, 20, 20, 0.  The total size is still 40 and the start values are 0, 0, 20, 40.  </div>
<div><br>
</div>
<div>This uses consistent logic and no special cases in the users application code.  However, this causes a failure in the nc_put_vara call due to the error check that “error if start >= size”.  There should be no issue if the error check were instead changed
 to “start > size” since the following check would still catch the overflow case — “start + count > size”</div>
<div><br>
</div>
<div>
<blockquote style="margin:0 0 0 40px; border:none; padding:0px;">
<div>if (start[d2] >= (hssize_t)fdims[d2])</div>
<div>   BAIL_QUIET(NC_EINVALCOORDS);</div>
<div>if (start[d2] + count[d2] > fdims[d2])</div>
<div>   BAIL_QUIET(NC_EEDGE);</div>
<div><br>
</div>
</blockquote>
<div>I don’t see a similar argument for ignoring invalid ncid and varid.  I would also still throw an error if start > size even if request size is 0; I’m just suggesting that it should not be an error for “start == size”.</div>
</div>
<div><br>
</div>
<div>The discussion on the netcdf list is <a href="https://github.com/Unidata/netcdf-c/pull/243">https://github.com/Unidata/netcdf-c/pull/243</a></div>
<div><br>
</div>
<div>..Greg</div>
<div>
<div id="">
<div>-- </div>
<div>"A supercomputer is a device for turning compute-bound problems into I/O-bound problems”</div>
<div><br>
</div>
<div><br>
</div>
</div>
</div>
</div>
<div><br>
</div>
<div>On 4/1/16, 12:57 PM, "Wei-keng Liao" <<a href="mailto:wkliao@eecs.northwestern.edu">wkliao@eecs.northwestern.edu</a>> wrote:</div>
<div><br>
</div>
<blockquote id="MAC_OUTLOOK_ATTRIBUTION_BLOCKQUOTE" style="BORDER-LEFT: #b5c4df 5 solid; PADDING:0 0 0 5; MARGIN:0 0 0 5;">
<div>Hi, Greg</div>
<div><br>
</div>
<div>Thanks. We will see how this request is taken by netCDF group.</div>
<div><br>
</div>
<div>Just would like to know more of your view to this problem.</div>
<div>Technically, the start value of the last process in your case</div>
<div>is out of bound. Because the request size is zero, it makes</div>
<div>sense to skip the request. However, what happens to other</div>
<div>arguments, should they be ignored as well? Not just arguments</div>
<div>of stride and imap, but also ncid and varid. In other words, should</div>
<div>an API ignore or report an error if an invalid ncid or varid is</div>
<div>used? I wonder if there is any application relying on netCDF</div>
<div>error report of NC_EINVALCOORDS for their internal checking</div>
<div>for any particular purpose.</div>
<div><br>
</div>
<div>Wei-keng</div>
<div><br>
</div>
<div>On Mar 31, 2016, at 1:53 PM, Sjaardema, Gregory D wrote:</div>
<div><br>
</div>
<blockquote id="MAC_OUTLOOK_ATTRIBUTION_BLOCKQUOTE" style="BORDER-LEFT: #b5c4df 5 solid; PADDING:0 0 0 5; MARGIN:0 0 0 5;">
<div>I have a similar patch submitted to NetCDF team.  The same test occurs three times in the nc4hdf.c file; two times without the count[]==0 check, one time with it.  If they accept the pull request, I will then resubmit this to the pnetcdf group.</div>
<div></div>
<div>Thanks,</div>
<div>..Greg</div>
<div></div>
<div>-- </div>
<div>"A supercomputer is a device for turning compute-bound problems into I/O-bound problems”</div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div>On 3/31/16, 12:35 PM, "Wei-keng Liao" <<a href="mailto:wkliao@eecs.northwestern.edu">wkliao@eecs.northwestern.edu</a>> wrote:</div>
<div></div>
<blockquote id="MAC_OUTLOOK_ATTRIBUTION_BLOCKQUOTE" style="BORDER-LEFT: #b5c4df 5 solid; PADDING:0 0 0 5; MARGIN:0 0 0 5;">
<div>Hi, Greg</div>
<div></div>
<div>This out-of-bound check is unfortunately enforced by netCDF even if count is zero.</div>
<div>There is a comment mentioned at the top of that function. PnetCDF tries to conform</div>
<div>with netCDF on returning error codes, and hence enforces the same check.</div>
<div></div>
<div>A while ago when I revised this part of codes, I tried to skip this check for</div>
<div>zero-length request, but found that will cause many fails for the internal test</div>
<div>programs. Unless netCDF changes its error checking on this, PnetCDF will keep</div>
<div>this the same. Here is a small program I tested against netCDF that can generate</div>
<div>the same error.</div>
<div></div>
<div></div>
<div>#include <stdio.h></div>
<div>#include <stdlib.h></div>
<div>#include <netcdf.h></div>
<div></div>
<div>#define ERR {if(err!=NC_NOERR){printf("Error at line=%d: %s\n", __LINE__, nc_strerror(err));}}</div>
<div></div>
<div>int main(int argc, char** argv) {</div>
<div>   int err, ncid, varid, dimid, buf[10];</div>
<div>   size_t start, count;</div>
<div></div>
<div>   err = nc_create("testfile.nc", NC_WRITE, &ncid); ERR</div>
<div>   err = nc_def_dim(ncid, "dim", 10, &dimid); ERR</div>
<div>   err = nc_def_var(ncid, "var", NC_INT, 1, &dimid, &varid); ERR</div>
<div>   err = nc_enddef(ncid); ERR</div>
<div></div>
<div>   start = 10;</div>
<div>   count = 0;</div>
<div>   err = nc_put_vara_int(ncid, varid, &start, &count, buf); ERR</div>
<div>   err = nc_close(ncid); ERR</div>
<div>   return 0;</div>
<div>}</div>
<div></div>
<div></div>
<div></div>
<div>Wei-keng</div>
<div></div>
<div>On Mar 31, 2016, at 12:43 PM, Sjaardema, Gregory D wrote:</div>
<div></div>
<blockquote id="MAC_OUTLOOK_ATTRIBUTION_BLOCKQUOTE" style="BORDER-LEFT: #b5c4df 5 solid; PADDING:0 0 0 5; MARGIN:0 0 0 5;">
<div>The following code is in filetype.c, function `NC_start_count_stride_ck`</div>
<div></div>
<blockquote id="MAC_OUTLOOK_ATTRIBUTION_BLOCKQUOTE" style="BORDER-LEFT: #b5c4df 5 solid; PADDING:0 0 0 5; MARGIN:0 0 0 5;">
<div>    for (; i<varp->ndims; i++) {</div>
<div>        if (start[i] < 0 || start[i] >= varp->shape[i])</div>
<div>            DEBUG_RETURN_ERROR(NC_EINVALCOORDS)</div>
<div></div>
<div>        if (varp->shape[i] < 0) DEBUG_RETURN_ERROR(NC_EEDGE)</div>
<div></div>
<div>        if (count != NULL) {</div>
<div>            if (count[i] < 0) /* no negative count[] */</div>
<div>                DEBUG_RETURN_ERROR(NC_ENEGATIVECNT)</div>
<div></div>
<div>            if (stride == NULL) { /* for vara APIs */</div>
<div>                if (count[i] > varp->shape[i] ||</div>
<div>                    start[i] + count[i] > varp->shape[i])</div>
<div>                    DEBUG_RETURN_ERROR(NC_EEDGE)</div>
<div>            }</div>
<div>            else { /* for vars APIs */</div>
<div>                if (count[i] > 0 &&</div>
<div>                    start[i] + (count[i]-1) * stride[i] >= varp->shape[i])</div>
<div>                    DEBUG_RETURN_ERROR(NC_EEDGE)</div>
<div>                if (stride[i] == 0) DEBUG_RETURN_ERROR(NC_ESTRIDE)</div>
<div>            }</div>
<div>        }</div>
<div>        /* else is for var1 APIs */</div>
<div></div>
</blockquote>
<div>There is an issue when the process with the highest rank has zero items to output.  As an example, if I have 4 mpi processes which are each writing the following amount of data:</div>
<div>* rank 0: 0 items</div>
<div>* rank 1: 2548 items</div>
<div>* rank 2: 4352 items</div>
<div>* rank 3: 0 items.</div>
<div></div>
<div>I will define the variable to have a length of 6900 items (0 + 2548 + 4352 + 0).  When I am outputting data to the variable, each rank will call nc_put_vara_longlong with the following start and count values:</div>
<div>* rank 0: start = 0, count = 0</div>
<div>* rank 1: start = 0, count = 2548</div>
<div>* rank 2: start = 2548, count = 4352</div>
<div>* rank 3: start = 6900, count = 0.</div>
<div></div>
<div>In each case, the `start` for rank N is equal to `start` for rank N-1 + `count` for rank N-1.  This all works ok until the highest rank is writing 0 items.  In that case, the `start` value for that rank is equal to the total size of the variable and the
 check in the code fragment shown above fails since `start[i] == varp->shape[i]`.</div>
<div></div>
<div>This could be fixed in the application code by checking whether the `count` is zero and if so, then set `start` to 0 also, but I think that is a kluge that should not be required.
</div>
<div></div>
<div>My suggestion is to make the test be:</div>
<div>```</div>
<div>  if (start[i] < 0 || (start[i] >= varp->shape[i] && count[i] > 0))</div>
<div>```</div>
<div>This is in version 1.7.0.  It also appears in 1.6.1 in the function Nccoordck.</div>
<div></div>
<div>..Greg</div>
<div></div>
<div>-- </div>
<div>"A supercomputer is a device for turning compute-bound problems into I/O-bound problems”</div>
</blockquote>
<div></div>
</blockquote>
</blockquote>
<div><br>
</div>
<div><br>
</div>
</blockquote>
</body>
</html>