summaryrefslogtreecommitdiffstats
path: root/src/H5Tconv.c
diff options
context:
space:
mode:
authorRaymond Lu <songyulu@hdfgroup.org>2007-06-19 20:05:24 (GMT)
committerRaymond Lu <songyulu@hdfgroup.org>2007-06-19 20:05:24 (GMT)
commit6017d0c70fda2a36cf963193e979f0548cb0c954 (patch)
treebc54a1f86fb94fe5dcecd2ba8b2b2623c5c38a77 /src/H5Tconv.c
parent32d09759bdf082d1a5d87903a58b0ed6c03dbe8c (diff)
downloadhdf5-6017d0c70fda2a36cf963193e979f0548cb0c954.zip
hdf5-6017d0c70fda2a36cf963193e979f0548cb0c954.tar.gz
hdf5-6017d0c70fda2a36cf963193e979f0548cb0c954.tar.bz2
[svn-r13884] The second step of optimization for compound data for the Chicago
company. The I/O is optimized when the source and destination members are a subset of each other one way or another, 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; }; or struct destination { struct source { TYPE1 A; --> TYPE1 A; TYPE2 B; --> TYPE2 B; TYPE3 C; --> TYPE3 C; }; TYPE4 D; TYPE5 E; }; The optimization is simply moving data from the source to the appropriate places in the buffer and bypass the reading of the background data and data conversion. Tested on smirom, liberty, sol, and copper.
Diffstat (limited to 'src/H5Tconv.c')
-rw-r--r--src/H5Tconv.c158
1 files changed, 127 insertions, 31 deletions
diff --git a/src/H5Tconv.c b/src/H5Tconv.c
index a0ca3da..9dd7b30 100644
--- a/src/H5Tconv.c
+++ b/src/H5Tconv.c
@@ -35,7 +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_subset_t smembs_subset; /*are source and dest members a subset of each other? */
} H5T_conv_struct_t;
/* Conversion data for H5T_conv_enum() */
@@ -1704,8 +1704,8 @@ done:
* 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:
+ * source and destination members are a subset of each other, 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;
@@ -1713,6 +1713,14 @@ done:
* }; TYPE4 D;
* TYPE5 E;
* };
+ * or
+ * struct destination { struct source {
+ * 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.
*
@@ -1722,7 +1730,8 @@ static herr_t
H5T_conv_struct_init (H5T_t *src, H5T_t *dst, H5T_cdata_t *cdata, hid_t dxpl_id)
{
H5T_conv_struct_t *priv = (H5T_conv_struct_t*)(cdata->priv);
- int *src2dst = NULL;
+ int *src2dst = NULL;
+ unsigned src_nmembs, dst_nmembs;
unsigned i, j;
H5T_t *type = NULL;
hid_t tid;
@@ -1730,23 +1739,23 @@ H5T_conv_struct_init (H5T_t *src, H5T_t *dst, H5T_cdata_t *cdata, hid_t dxpl_id)
FUNC_ENTER_NOAPI_NOINIT(H5T_conv_struct_init);
+ src_nmembs = src->shared->u.compnd.nmembs;
+ dst_nmembs = dst->shared->u.compnd.nmembs;
+
if (!priv) {
/*
* Allocate private data structure and arrays.
*/
if (NULL==(priv=cdata->priv=H5MM_calloc(sizeof(H5T_conv_struct_t))) ||
- NULL==(priv->src2dst=H5MM_malloc(src->shared->u.compnd.nmembs *
- sizeof(int))) ||
- NULL==(priv->src_memb_id=H5MM_malloc(src->shared->u.compnd.nmembs *
- sizeof(hid_t))) ||
- NULL==(priv->dst_memb_id=H5MM_malloc(dst->shared->u.compnd.nmembs *
- sizeof(hid_t))))
+ NULL==(priv->src2dst=H5MM_malloc(src_nmembs * sizeof(int))) ||
+ NULL==(priv->src_memb_id=H5MM_malloc(src_nmembs * sizeof(hid_t))) ||
+ NULL==(priv->dst_memb_id=H5MM_malloc(dst_nmembs * sizeof(hid_t))))
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;
+ /* The flag of special optimization to indicate if source members and destination
+ * members are a subset of each other. Initialize it to FALSE */
+ priv->smembs_subset = H5T_SUBSET_FALSE;
/*
* Insure that members are sorted.
@@ -1761,9 +1770,9 @@ H5T_conv_struct_init (H5T_t *src, H5T_t *dst, H5T_cdata_t *cdata, hid_t dxpl_id)
* source and destination member data type so we can look up the
* member data type conversion functions later.
*/
- for (i=0; i<src->shared->u.compnd.nmembs; i++) {
+ for (i=0; i<src_nmembs; i++) {
src2dst[i] = -1;
- for (j=0; j<dst->shared->u.compnd.nmembs; j++) {
+ for (j=0; j<dst_nmembs; j++) {
if (!HDstrcmp (src->shared->u.compnd.memb[i].name,
dst->shared->u.compnd.memb[j].name)) {
src2dst[i] = j;
@@ -1782,11 +1791,6 @@ 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 {
@@ -1806,7 +1810,7 @@ H5T_conv_struct_init (H5T_t *src, H5T_t *dst, H5T_cdata_t *cdata, hid_t dxpl_id)
sizeof(H5T_path_t*))))
HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed");
- for (i=0; i<src->shared->u.compnd.nmembs; i++) {
+ for (i=0; i<src_nmembs; i++) {
if (src2dst[i]>=0) {
H5T_path_t *tpath = H5T_path_find(src->shared->u.compnd.memb[i].type,
dst->shared->u.compnd.memb[src2dst[i]].type, NULL, NULL, dxpl_id, FALSE);
@@ -1819,18 +1823,39 @@ 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;
-
}
}
/* Check if we need a background buffer */
- if (H5T_detect_class(src,H5T_COMPOUND)==TRUE || H5T_detect_class(dst,H5T_COMPOUND)==TRUE)
+ if (H5T_detect_class(src,H5T_COMPOUND)==TRUE || H5T_detect_class(dst,H5T_COMPOUND)==TRUE) {
cdata->need_bkg = H5T_BKG_YES;
+ if(src_nmembs < dst_nmembs) {
+ priv->smembs_subset = H5T_SUBSET_SRC;
+ for (i=0; i<src_nmembs; i++) {
+ /* If any of source members doesn't have counterpart in the same order or
+ * there's conversion between members, don't do the optimization. */
+ if(src2dst[i] != i || (src->shared->u.compnd.memb[i].offset !=
+ dst->shared->u.compnd.memb[i].offset) || (priv->memb_path[i])->is_noop ==
+ FALSE)
+ priv->smembs_subset = H5T_SUBSET_FALSE;
+ }
+ } else if(dst_nmembs < src_nmembs) {
+ priv->smembs_subset = H5T_SUBSET_DST;
+ for (i=0; i<dst_nmembs; i++) {
+ /* If any of source members doesn't have counterpart in the same order or
+ * there's conversion between members, don't do the optimization. */
+ if(src2dst[i] != i || (src->shared->u.compnd.memb[i].offset !=
+ dst->shared->u.compnd.memb[i].offset) || (priv->memb_path[i])->is_noop ==
+ FALSE)
+ priv->smembs_subset = H5T_SUBSET_FALSE;
+ }
+ } else /* If the numbers of source and dest members are equal and no conversion is needed,
+ * the case should have been handled as noop earlier in H5Dio.c. */
+ ;
+
+ }
+
cdata->recalc = FALSE;
done:
@@ -1839,6 +1864,49 @@ done:
/*-------------------------------------------------------------------------
+ * Function: H5T_conv_struct_subset
+ *
+ * Purpose: A quick way to return a field in a struct private in this
+ * file. The flag SMEMBS_SUBSET indicates whether the source
+ * members are a subset of destination or the destination
+ * members are a subset of the source, 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;
+ * };
+ *
+ * Return: One of the value from H5T_subset_t.
+ *
+ * Programmer: Raymond Lu
+ * 8 June 2007
+ *
+ * Modifications:
+ *-------------------------------------------------------------------------
+ */
+H5T_subset_t
+H5T_conv_struct_subset(const H5T_cdata_t *cdata)
+{
+ H5T_conv_struct_t *priv;
+ H5T_subset_t ret_value=FALSE; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5T_conv_struct_subset);
+
+ assert(cdata);
+ assert(cdata->priv);
+
+ priv = (H5T_conv_struct_t*)(cdata->priv);
+ ret_value = priv->smembs_subset;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value);
+}
+
+
+/*-------------------------------------------------------------------------
* Function: H5T_conv_struct
*
* Purpose: Converts between compound data types. This is a soft
@@ -2109,9 +2177,9 @@ done:
* 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:
+ * Optimize a special case when the source and destination members
+ * are a subset of each other, 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;
@@ -2257,7 +2325,7 @@ H5T_conv_struct_opt(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
buf_stride = src->shared->size;
}
- if(priv->smembs_subset == TRUE) {
+ if(priv->smembs_subset == H5T_SUBSET_SRC) {
/* 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;
@@ -2286,6 +2354,34 @@ H5T_conv_struct_opt(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
xbkg += bkg_stride;
}
}
+ } else if(priv->smembs_subset == H5T_SUBSET_DST) {
+ /* If the optimization flag is set to indicate destination members are a subset
+ * and in the top of the source, simply copy the source members to background
+ * buffer. */
+ xbuf = buf;
+ xbkg = bkg;
+
+ if(src->shared->size <= dst->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.
+ */
+ for (elmtno=0; elmtno<nelmts; elmtno++) {
+ HDmemmove(xbkg, xbuf, src->shared->size);
+
+ /* Update pointers */
+ xbuf += buf_stride;
+ xbkg += bkg_stride;
+ }
+ } else {
+ for (elmtno=0; elmtno<nelmts; elmtno++) {
+ HDmemmove(xbkg, xbuf, dst->shared->size);
+
+ /* Update pointers */
+ xbuf += buf_stride;
+ xbkg += bkg_stride;
+ }
+ }
} else {
/*
* For each member where the destination is not larger than the