diff --git a/opal/datatype/opal_datatype_optimize.c b/opal/datatype/opal_datatype_optimize.c index 336e11f0560..2e661b95daa 100644 --- a/opal/datatype/opal_datatype_optimize.c +++ b/opal/datatype/opal_datatype_optimize.c @@ -163,6 +163,12 @@ opal_datatype_optimize_short( opal_datatype_t* pData, if( 0 == last.count ) { /* first data of the datatype */ last = *current; continue; /* next data */ + } else { /* can we merge it in order to decrease count */ + if( (ptrdiff_t)last.blocklen * (ptrdiff_t)opal_datatype_basicDatatypes[last.common.type]->size == last.extent ) { + last.extent *= last.count; + last.blocklen *= last.count; + last.count = 1; + } } /* are the two elements compatible: aka they have very similar values and they @@ -176,27 +182,27 @@ opal_datatype_optimize_short( opal_datatype_t* pData, last.common.type = OPAL_DATATYPE_UINT1; } - if( 1 == last.count ) { - /* we can ignore the extent of the element with count == 1 and merge them together if their displacements match */ + if( (last.extent * (ptrdiff_t)last.count + last.disp) == current->disp ) { if( 1 == current->count ) { - last.extent = current->disp - last.disp; last.count++; continue; } - /* can we compute a matching displacement ? */ - if( (last.disp + current->extent) == current->disp ) { - last.extent = current->extent; - last.count = current->count + 1; + if( last.extent == current->extent ) { + last.count += current->count; continue; } } - if( (last.extent * (ptrdiff_t)last.count + last.disp) == current->disp ) { + if( 1 == last.count ) { + /* we can ignore the extent of the element with count == 1 and merge them together if their displacements match */ if( 1 == current->count ) { + last.extent = current->disp - last.disp; last.count++; continue; } - if( last.extent == current->extent ) { - last.count += current->count; + /* can we compute a matching displacement ? */ + if( (last.disp + current->extent) == current->disp ) { + last.extent = current->extent; + last.count = current->count + last.count; continue; } } diff --git a/opal/datatype/opal_datatype_pack.c b/opal/datatype/opal_datatype_pack.c index f21adcccb34..6dc0b81a253 100644 --- a/opal/datatype/opal_datatype_pack.c +++ b/opal/datatype/opal_datatype_pack.c @@ -121,6 +121,7 @@ opal_pack_homogeneous_contig_with_gaps_function( opal_convertor_t* pConv, * how much we should jump between elements. */ assert( (pData->flags & OPAL_DATATYPE_FLAG_CONTIGUOUS) && ((ptrdiff_t)pData->size != extent) ); + assert( pData->opt_desc.used <= 1 ); DO_DEBUG( opal_output( 0, "pack_homogeneous_contig( pBaseBuf %p, iov_count %d )\n", (void*)pConv->pBaseBuf, *out_size ); ); if( stack[1].type != opal_datatype_uint1.id ) { diff --git a/test/datatype/to_self.c b/test/datatype/to_self.c index 073fe4f0b57..2ba3eb92163 100644 --- a/test/datatype/to_self.c +++ b/test/datatype/to_self.c @@ -24,6 +24,26 @@ extern void ompi_datatype_dump( MPI_Datatype ddt ); #define MPI_DDT_DUMP(ddt) #endif /* OPEN_MPI */ +static MPI_Datatype +create_merged_contig_with_gaps(int count) /* count of the basic datatype */ +{ + int array_of_blocklengths[] = {1, 1, 1}; + MPI_Aint array_of_displacements[] = {0, 8, 16}; + MPI_Datatype array_of_types[] = {MPI_DOUBLE, MPI_LONG, MPI_CHAR}; + MPI_Datatype type; + + MPI_Type_create_struct(3, array_of_blocklengths, + array_of_displacements, array_of_types, + &type); + if( 1 < count ) { + MPI_Datatype temp = type; + MPI_Type_contiguous(count, temp, &type); + } + MPI_Type_commit(&type); + MPI_DDT_DUMP( type ); + return type; +} + /* Create a non-contiguous resized datatype */ struct structure { double not_transfered; @@ -183,11 +203,12 @@ create_indexed_gap_optimized_ddt( void ) /******************************************************************** *******************************************************************/ -#define DO_CONTIG 0x00000001 -#define DO_CONSTANT_GAP 0x00000002 -#define DO_INDEXED_GAP 0x00000004 -#define DO_OPTIMIZED_INDEXED_GAP 0x00000008 -#define DO_STRUCT_CONSTANT_GAP_RESIZED 0x00000010 +#define DO_CONTIG 0x00000001 +#define DO_CONSTANT_GAP 0x00000002 +#define DO_INDEXED_GAP 0x00000004 +#define DO_OPTIMIZED_INDEXED_GAP 0x00000008 +#define DO_STRUCT_CONSTANT_GAP_RESIZED 0x00000010 +#define DO_STRUCT_MERGED_WITH_GAP_RESIZED 0x00000020 #define DO_PACK 0x01000000 #define DO_UNPACK 0x02000000 @@ -483,7 +504,7 @@ static int do_test_for_ddt( int doop, MPI_Datatype sddt, MPI_Datatype rddt, int int main( int argc, char* argv[] ) { - int run_tests = 0xffff; /* do all datatype tests by default */ + int run_tests = DO_STRUCT_MERGED_WITH_GAP_RESIZED; /* do all datatype tests by default */ int rank, size; MPI_Datatype ddt; @@ -544,6 +565,14 @@ int main( int argc, char* argv[] ) MPI_Type_free( &ddt ); } + if( run_tests & DO_STRUCT_MERGED_WITH_GAP_RESIZED ) { + printf( "\nstruct constant gap resized\n\n" ); + ddt = create_merged_contig_with_gaps( 1 ); + MPI_DDT_DUMP( ddt ); + do_test_for_ddt( run_tests, ddt, ddt, MAX_LENGTH ); + MPI_Type_free( &ddt ); + } + MPI_Finalize (); exit(0); }