From b08afe35a41fc89bfa2d4ad7d412b4c91a25dacf Mon Sep 17 00:00:00 2001 From: Raymond Lu Date: Wed, 23 May 2007 17:43:03 -0500 Subject: [svn-r13803] Optimization of reading compound data. Optimize a special case when the source members are a subset of destination, and the order is the same, and no conversion is needed. For example: struct source { struct destination { TYPE1 A; --> TYPE1 A; TYPE2 B; --> TYPE2 B; TYPE3 C; --> TYPE3 C; }; TYPE4 D; TYPE5 E; }; The optimization is simply moving data to the appropriate places in the buffer. This optimization work is for the Chicago company. Tested on sol, copper, smirom, liberty. --- src/H5Tconv.c | 198 +++++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 139 insertions(+), 59 deletions(-) diff --git a/src/H5Tconv.c b/src/H5Tconv.c index 3a94bb2..f2b410e 100644 --- a/src/H5Tconv.c +++ b/src/H5Tconv.c @@ -35,6 +35,7 @@ typedef struct H5T_conv_struct_t { hid_t *src_memb_id; /*source member type ID's */ hid_t *dst_memb_id; /*destination member type ID's */ H5T_path_t **memb_path; /*conversion path for each member */ + hbool_t smembs_subset; /*are source members a subset and in the top of dest? */ } H5T_conv_struct_t; /* Conversion data for H5T_conv_enum() */ @@ -1701,7 +1702,20 @@ done: * Monday, January 26, 1998 * * Modifications: - * + * Raymond Lu, 3 May 2007 + * Added the detection for a special optimization case when the + * source members are a subset of destination, and the order is + * the same, and no conversion is needed. For example: + * struct source { struct destination { + * TYPE1 A; --> TYPE1 A; + * TYPE2 B; --> TYPE2 B; + * TYPE3 C; --> TYPE3 C; + * }; TYPE4 D; + * TYPE5 E; + * }; + * The optimization is simply moving data to the appropriate + * places in the buffer. + * *------------------------------------------------------------------------- */ static herr_t @@ -1730,6 +1744,10 @@ H5T_conv_struct_init (H5T_t *src, H5T_t *dst, H5T_cdata_t *cdata, hid_t dxpl_id) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); src2dst = priv->src2dst; + /* The flag of special optimization to indicate if source members are a subset + * and in the top of the destination. Initialize it to TRUE */ + priv->smembs_subset = TRUE; + /* * Insure that members are sorted. */ @@ -1764,6 +1782,11 @@ H5T_conv_struct_init (H5T_t *src, H5T_t *dst, H5T_cdata_t *cdata, hid_t dxpl_id) assert (tid>=0); priv->dst_memb_id[src2dst[i]] = tid; } + + /* If any of source member doesn't have counterpart in the same order, + * don't do the special optimization. */ + if(src2dst[i] != i || (src->shared->u.compnd.memb[i].offset != dst->shared->u.compnd.memb[i].offset)) + priv->smembs_subset = FALSE; } } else { @@ -1796,6 +1819,11 @@ H5T_conv_struct_init (H5T_t *src, H5T_t *dst, H5T_cdata_t *cdata, hid_t dxpl_id) cdata->priv = priv = H5MM_xfree (priv); HGOTO_ERROR (H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "unable to convert member data type"); } + + /* If any of source member needs conversion, don't do the special optimization. */ + if(priv->smembs_subset && ((priv->memb_path[i])->is_noop == FALSE)) + priv->smembs_subset = FALSE; + } } @@ -2003,9 +2031,9 @@ H5T_conv_struct(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts, xbkg += bkg_stride; } - /* If the bkg_stride was set to -(dst->shared->size), make it positive now */ - if(buf_stride==0 && dst->shared->size>src->shared->size) - bkg_stride=dst->shared->size; + /* If the bkg_stride was set to -(dst->shared->size), make it positive now */ + if(buf_stride==0 && dst->shared->size>src->shared->size) + bkg_stride=dst->shared->size; /* * Copy the background buffer back into the in-place conversion @@ -2079,6 +2107,21 @@ done: * multiple of BKG_STRIDE in the BKG buffer; otherwise the * BKG buffer is assumed to be a packed array of destination * datatype. + * + * Raymond Lu, 3 May 2007 + * Optimize a special case when the source members are a subset of + * destination, and the order is the same, and no conversion is needed. + * For example: + * struct source { struct destination { + * TYPE1 A; --> TYPE1 A; + * TYPE2 B; --> TYPE2 B; + * TYPE3 C; --> TYPE3 C; + * }; TYPE4 D; + * TYPE5 E; + * }; + * The optimization is simply moving data to the appropriate + * places in the buffer. + * *------------------------------------------------------------------------- */ herr_t @@ -2098,9 +2141,10 @@ H5T_conv_struct_opt(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t offset; /*byte offset wrt struct */ size_t elmtno; /*element counter */ unsigned u; /*counters */ - int i; /*counters */ + int i; /*counters */ H5T_conv_struct_t *priv = NULL; /*private data */ - herr_t ret_value=SUCCEED; /* Return value */ + hbool_t no_stride = FALSE; /*flag to indicate no stride */ + herr_t ret_value=SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5T_conv_struct_opt, FAIL); @@ -2208,79 +2252,115 @@ H5T_conv_struct_opt(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, * otherwise assume BKG buffer is the packed destination datatype. */ if (!buf_stride || !bkg_stride) bkg_stride = dst->shared->size; + if (!buf_stride) { + no_stride = TRUE; + buf_stride = src->shared->size; + } - /* - * For each member where the destination is not larger than the - * source, stride through all the elements converting only that member - * in each element and then copying the element to its final - * destination in the bkg buffer. Otherwise move the element as far - * left as possible in the buffer. - */ - for (u=0, offset=0; ushared->u.compnd.nmembs; u++) { - if (src2dst[u]<0) continue; /*subsetting*/ - src_memb = src->shared->u.compnd.memb + u; - dst_memb = dst->shared->u.compnd.memb + src2dst[u]; - - if (dst_memb->size <= src_memb->size) { - xbuf = buf + src_memb->offset; - xbkg = bkg + dst_memb->offset; - if (H5T_convert(priv->memb_path[u], - priv->src_memb_id[u], - priv->dst_memb_id[src2dst[u]], nelmts, - buf_stride ? buf_stride : src->shared->size, - bkg_stride, xbuf, xbkg, - dxpl_id)<0) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to convert compound data type member"); + if(priv->smembs_subset == TRUE) { + /* If the optimization flag is set to indicate source members are a subset and + * in the top of the destination, simply copy the source members to background buffer. */ + xbuf = buf; + xbkg = bkg; + if(dst->shared->size <= src->shared->size) { + /* This is to deal with a very special situation when the fields and their + * offset for both source and destination are identical but the datatype + * sizes of source and destination are different. The library still + * considers these two types different and does conversion. It happens + * in table API test (hdf5/hl/test/test_table.c) when a table field is + * deleted. + */ for (elmtno=0; elmtnosize); - xbuf += buf_stride ? buf_stride : src->shared->size; + HDmemmove(xbkg, xbuf, dst->shared->size); + + /* Update pointers */ + xbuf += buf_stride; xbkg += bkg_stride; } } else { - for (xbuf=buf, elmtno=0; elmtnooffset, + for (elmtno=0; elmtnoshared->size); + + /* Update pointers */ + xbuf += buf_stride; + xbkg += bkg_stride; + } + } + } else { + /* + * For each member where the destination is not larger than the + * source, stride through all the elements converting only that member + * in each element and then copying the element to its final + * destination in the bkg buffer. Otherwise move the element as far + * left as possible in the buffer. + */ + for (u=0, offset=0; ushared->u.compnd.nmembs; u++) { + if (src2dst[u]<0) continue; /*subsetting*/ + src_memb = src->shared->u.compnd.memb + u; + dst_memb = dst->shared->u.compnd.memb + src2dst[u]; + + if (dst_memb->size <= src_memb->size) { + xbuf = buf + src_memb->offset; + xbkg = bkg + dst_memb->offset; + if (H5T_convert(priv->memb_path[u], + priv->src_memb_id[u], + priv->dst_memb_id[src2dst[u]], nelmts, + buf_stride, bkg_stride, xbuf, xbkg, dxpl_id)<0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to convert compound data type member"); + for (elmtno=0; elmtnosize); + xbuf += buf_stride; + xbkg += bkg_stride; + } + } else { + for (xbuf=buf, elmtno=0; elmtnooffset, src_memb->size); - xbuf += buf_stride ? buf_stride : src->shared->size; + xbuf += buf_stride; + } + offset += src_memb->size; } - offset += src_memb->size; } - } - /* - * Work from right to left, converting those members that weren't - * converted in the previous loop (those members where the destination - * is larger than the source) and them to their final position in the - * bkg buffer. - */ - for (i=src->shared->u.compnd.nmembs-1; i>=0; --i) { - if (src2dst[i]<0) - continue; - src_memb = src->shared->u.compnd.memb + i; - dst_memb = dst->shared->u.compnd.memb + src2dst[i]; - - if (dst_memb->size > src_memb->size) { - offset -= src_memb->size; - xbuf = buf + offset; - xbkg = bkg + dst_memb->offset; - if (H5T_convert(priv->memb_path[i], + /* + * Work from right to left, converting those members that weren't + * converted in the previous loop (those members where the destination + * is larger than the source) and them to their final position in the + * bkg buffer. + */ + for (i=src->shared->u.compnd.nmembs-1; i>=0; --i) { + if (src2dst[i]<0) + continue; + src_memb = src->shared->u.compnd.memb + i; + dst_memb = dst->shared->u.compnd.memb + src2dst[i]; + + if (dst_memb->size > src_memb->size) { + offset -= src_memb->size; + xbuf = buf + offset; + xbkg = bkg + dst_memb->offset; + if (H5T_convert(priv->memb_path[i], priv->src_memb_id[i], priv->dst_memb_id[src2dst[i]], nelmts, - buf_stride ? buf_stride : src->shared->size, + buf_stride, bkg_stride, xbuf, xbkg, dxpl_id)<0) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to convert compound data type member"); - for (elmtno=0; elmtnosize); - xbuf += buf_stride ? buf_stride : src->shared->size; - xbkg += bkg_stride; + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to convert compound data type member"); + for (elmtno=0; elmtnosize); + xbuf += buf_stride; + xbkg += bkg_stride; + } } } } + if(no_stride) + buf_stride = dst->shared->size; + /* Move background buffer into result buffer */ for (xbuf=buf, xbkg=bkg, elmtno=0; elmtnoshared->size); - xbuf += buf_stride ? buf_stride : dst->shared->size; + xbuf += buf_stride; xbkg += bkg_stride; } break; -- cgit v0.12