summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/H5Tconv.c198
1 files 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; u<src->shared->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; elmtno<nelmts; elmtno++) {
- HDmemmove(xbkg, xbuf, dst_memb->size);
- 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; elmtno<nelmts; elmtno++) {
- HDmemmove(xbuf+offset, xbuf+src_memb->offset,
+ for (elmtno=0; elmtno<nelmts; elmtno++) {
+ HDmemmove(xbkg, xbuf, src->shared->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; u<src->shared->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; elmtno<nelmts; elmtno++) {
+ HDmemmove(xbkg, xbuf, dst_memb->size);
+ xbuf += buf_stride;
+ xbkg += bkg_stride;
+ }
+ } else {
+ for (xbuf=buf, elmtno=0; elmtno<nelmts; elmtno++) {
+ HDmemmove(xbuf+offset, xbuf+src_memb->offset,
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; elmtno<nelmts; elmtno++) {
- HDmemmove(xbkg, xbuf, dst_memb->size);
- 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; elmtno<nelmts; elmtno++) {
+ HDmemmove(xbkg, xbuf, dst_memb->size);
+ 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; elmtno<nelmts; elmtno++) {
HDmemmove(xbuf, xbkg, dst->shared->size);
- xbuf += buf_stride ? buf_stride : dst->shared->size;
+ xbuf += buf_stride;
xbkg += bkg_stride;
}
break;