diff --git a/ompi/datatype/ompi_datatype_create_darray.c b/ompi/datatype/ompi_datatype_create_darray.c index 9034f205c7..6ca81cf867 100644 --- a/ompi/datatype/ompi_datatype_create_darray.c +++ b/ompi/datatype/ompi_datatype_create_darray.c @@ -247,8 +247,7 @@ int32_t ompi_datatype_create_darray(int size, } - /* set displacement and UB correctly. Use struct instead of - resized for same reason as subarray */ + /* set displacement and UB correctly. Please read the comment in subarray */ { ptrdiff_t displs[3], tmp_size; ompi_datatype_t *types[3]; @@ -267,9 +266,13 @@ int32_t ompi_datatype_create_darray(int size, for (i = 0 ; i < ndims ; i++) { displs[2] *= gsize_array[i]; } - types[0] = MPI_LB; types[1] = lastType; types[2] = MPI_UB; + if(oldtype->super.flags & (OPAL_DATATYPE_FLAG_USER_LB | OPAL_DATATYPE_FLAG_USER_UB) ) { + types[0] = MPI_LB; types[1] = lastType; types[2] = MPI_UB; - rc = ompi_datatype_create_struct(3, blength, displs, types, newtype); + rc = ompi_datatype_create_struct(3, blength, displs, types, newtype); + } else { + ompi_datatype_create_resized(lastType, displs[0], displs[2], newtype); + } ompi_datatype_destroy(&lastType); /* need to destroy the old type even in error condition, so don't check return code from above until after cleanup. */ diff --git a/ompi/datatype/ompi_datatype_create_subarray.c b/ompi/datatype/ompi_datatype_create_subarray.c index c628fe26d1..d9bf3ea06c 100644 --- a/ompi/datatype/ompi_datatype_create_subarray.c +++ b/ompi/datatype/ompi_datatype_create_subarray.c @@ -40,6 +40,12 @@ int32_t ompi_datatype_create_subarray(int ndims, int32_t i, step, end_loop; MPI_Aint size, displ, extent; + /** + * If the oldtype contains the original MPI_LB and MPI_UB markers then we + * are forced to follow the MPI standard suggestion and reset these 2 + * markers (MPI 3.0 page 96 line 37). Otherwise we can simply resize the + * datatype. + */ ompi_datatype_type_extent( oldtype, &extent ); /* If the ndims is zero then return the NULL datatype */ @@ -85,12 +91,12 @@ int32_t ompi_datatype_create_subarray(int ndims, replace_subarray_type: /** - * We cannot use resized here. Resized will only set the soft lb and ub markers - * without moving the real data inside. What we need is to force the displacement - * of the data upward to the right position AND set the LB and UB. A type - * struct is the function we need. + * Resized will only set the soft lb and ub markers without moving the real + * data inside. Thus, in case the original data contains the hard markers + * (MPI_LB or MPI_UB) we must force the displacement of the data upward to + * the right position AND set the hard markers LB and UB. */ - { + if( oldtype->super.flags & (OPAL_DATATYPE_FLAG_USER_LB | OPAL_DATATYPE_FLAG_USER_UB) ) { MPI_Aint displs[3]; MPI_Datatype types[3]; int blength[3] = { 1, 1, 1 }; @@ -98,6 +104,8 @@ int32_t ompi_datatype_create_subarray(int ndims, displs[0] = 0; displs[1] = displ * extent; displs[2] = size * extent; types[0] = MPI_LB; types[1] = last_type; types[2] = MPI_UB; ompi_datatype_create_struct( 3, blength, displs, types, newtype ); + } else { + ompi_datatype_create_resized(last_type, 0, size * extent, newtype); } ompi_datatype_destroy( &last_type );