From df1d5505c15e27eca9236952bbfef94a6dc8f20d Mon Sep 17 00:00:00 2001 From: Neil Fortner Date: Fri, 22 Jan 2021 17:00:35 -0600 Subject: Improve performance of multiple calls to H5Sget_select_elem_pointlist (#270) (#275) * Cache the pointer to the next point to process after the last call to H5S__get_select_elem_pointlist. This allows the normal process of iterating over the points in batches to be much more efficient, as the library does not need to traverse the entirety of the preceding points every time the funciton is re-entered. * Update RELEASE.txt for point selection iteration performance fix. --- release_docs/RELEASE.txt | 9 +++++++++ src/H5Spkg.h | 5 +++++ src/H5Spoint.c | 33 ++++++++++++++++++++++++++------- 3 files changed, 40 insertions(+), 7 deletions(-) diff --git a/release_docs/RELEASE.txt b/release_docs/RELEASE.txt index a6beaed..20acd49 100644 --- a/release_docs/RELEASE.txt +++ b/release_docs/RELEASE.txt @@ -178,6 +178,15 @@ New Features Library: -------- + - Improved performance of H5Sget_select_elem_pointlist + + Modified library to cache the point after the last block of points + retrieved by H5Sget_select_elem_pointlist, so a subsequent call to the + same function to retrieve the next block of points from the list can + proceed immediately without needing to iterate over the point list. + + (NAF - 2021/01/19) + - Added H5VL_VERSION macro that indicates the version of the VOL framework implemented by a version of the library. Currently, compatibility checking enforces that the 'version' field in the H5VL_class_t for diff --git a/src/H5Spkg.h b/src/H5Spkg.h index adb528e..159e485 100644 --- a/src/H5Spkg.h +++ b/src/H5Spkg.h @@ -137,6 +137,11 @@ struct H5S_pnt_list_t { H5S_pnt_node_t *head; /* Pointer to head of point list */ H5S_pnt_node_t *tail; /* Pointer to tail of point list */ + + hsize_t last_idx; /* Index of the point after the last returned from H5S__get_select_elem_pointlist() */ + H5S_pnt_node_t *last_idx_pnt; /* Point after the last returned from H5S__get_select_elem_pointlist(). + * If we ever add a way to remove points or add points in the middle of + * the pointlist we will need to invalidate these fields. */ }; /* Information about hyperslab spans */ diff --git a/src/H5Spoint.c b/src/H5Spoint.c index 584624d..966333c 100644 --- a/src/H5Spoint.c +++ b/src/H5Spoint.c @@ -842,6 +842,10 @@ H5S__copy_pnt_list(const H5S_pnt_list_t *src, unsigned rank) H5MM_memcpy(dst->high_bounds, src->high_bounds, (rank * sizeof(hsize_t))); H5MM_memcpy(dst->low_bounds, src->low_bounds, (rank * sizeof(hsize_t))); + /* Clear cached iteration point */ + dst->last_idx = 0; + dst->last_idx_pnt = NULL; + /* Set return value */ ret_value = dst; @@ -1510,6 +1514,7 @@ done: static herr_t H5S__get_select_elem_pointlist(const H5S_t *space, hsize_t startpoint, hsize_t numpoints, hsize_t *buf) { + const hsize_t endpoint = startpoint + numpoints; /* Index of last point in iteration */ H5S_pnt_node_t *node; /* Point node */ unsigned rank; /* Dataspace rank */ @@ -1521,14 +1526,20 @@ H5S__get_select_elem_pointlist(const H5S_t *space, hsize_t startpoint, hsize_t n /* Get the dataspace extent rank */ rank = space->extent.rank; - /* Get the head of the point list */ - node = space->select.sel_info.pnt_lst->head; + /* Check for cached point at the correct index */ + if(space->select.sel_info.pnt_lst->last_idx_pnt + && startpoint == space->select.sel_info.pnt_lst->last_idx) + node = space->select.sel_info.pnt_lst->last_idx_pnt; + else { + /* Get the head of the point list */ + node = space->select.sel_info.pnt_lst->head; - /* Iterate to the first point to return */ - while (node != NULL && startpoint > 0) { - startpoint--; - node = node->next; - } /* end while */ + /* Iterate to the first point to return */ + while (node != NULL && startpoint > 0) { + startpoint--; + node = node->next; + } /* end while */ + } /* end else */ /* Iterate through the node, copying each point's information */ while (node != NULL && numpoints > 0) { @@ -1538,6 +1549,10 @@ H5S__get_select_elem_pointlist(const H5S_t *space, hsize_t startpoint, hsize_t n node = node->next; } /* end while */ + /* Cached next point in iteration */ + space->select.sel_info.pnt_lst->last_idx = endpoint; + space->select.sel_info.pnt_lst->last_idx_pnt = node; + FUNC_LEAVE_NOAPI(SUCCEED) } /* end H5S__get_select_elem_pointlist() */ @@ -2329,6 +2344,10 @@ H5S__point_project_simple(const H5S_t *base_space, H5S_t *new_space, hsize_t *of } /* end for */ } /* end else */ + /* Clear cached iteration point */ + new_space->select.sel_info.pnt_lst->last_idx = 0; + new_space->select.sel_info.pnt_lst->last_idx_pnt = NULL; + /* Number of elements selected will be the same */ new_space->select.num_elem = base_space->select.num_elem; -- cgit v0.12