From 150d5c889f5f071ebe2ddcc8c4fcb1335e10707c Mon Sep 17 00:00:00 2001 From: degomme Date: Thu, 4 Oct 2012 13:35:32 +0200 Subject: [PATCH] generalize non contiguous send method to other MPI types (hvector, indexed, hindexed, and structs, and add tests for those) --- examples/smpi/CMakeLists.txt | 9 + examples/smpi/hvector_test.c | 42 ++++ examples/smpi/indexed_test.c | 48 ++++ examples/smpi/struct_test.c | 67 ++++++ src/smpi/private.h | 30 --- src/smpi/smpi_mpi_dt.c | 404 +++++++++++++++++++++++++++++++-- src/smpi/smpi_mpi_dt_private.h | 137 +++++++++++ 7 files changed, 682 insertions(+), 55 deletions(-) create mode 100644 examples/smpi/hvector_test.c create mode 100644 examples/smpi/indexed_test.c create mode 100644 examples/smpi/struct_test.c diff --git a/examples/smpi/CMakeLists.txt b/examples/smpi/CMakeLists.txt index 7abef72ed9..3bf1d3a35a 100644 --- a/examples/smpi/CMakeLists.txt +++ b/examples/smpi/CMakeLists.txt @@ -27,6 +27,9 @@ if(enable_smpi) add_executable(smpi_traced_simple tracing/smpi_traced_simple.c) add_executable(ttest01 ttest01.c) add_executable(vector_test vector_test.c) + add_executable(hvector_test hvector_test.c) + add_executable(indexed_test indexed_test.c) + add_executable(struct_test struct_test.c) add_executable(mc_bugged1 mc_bugged1.c) add_executable(mc_bugged2 mc_bugged2.c) add_executable(smpi_replay replay/replay.c) @@ -51,6 +54,9 @@ if(enable_smpi) target_link_libraries(smpi_traced_simple m simgrid smpi ) target_link_libraries(ttest01 m simgrid smpi ) target_link_libraries(vector_test m simgrid smpi ) + target_link_libraries(hvector_test m simgrid smpi ) + target_link_libraries(indexed_test m simgrid smpi ) + target_link_libraries(struct_test m simgrid smpi ) target_link_libraries(mc_bugged1 m simgrid smpi ) target_link_libraries(mc_bugged2 m simgrid smpi ) target_link_libraries(smpi_replay m simgrid smpi ) @@ -94,6 +100,9 @@ set(examples_src ${CMAKE_CURRENT_SOURCE_DIR}/barrier.c ${CMAKE_CURRENT_SOURCE_DIR}/bcbench.c ${CMAKE_CURRENT_SOURCE_DIR}/vector_test.c + ${CMAKE_CURRENT_SOURCE_DIR}/hvector_test.c + ${CMAKE_CURRENT_SOURCE_DIR}/indexed_test.c + ${CMAKE_CURRENT_SOURCE_DIR}/struct_test.c ${CMAKE_CURRENT_SOURCE_DIR}/replay/replay.c ${CMAKE_CURRENT_SOURCE_DIR}/tracing/smpi_traced.c ${CMAKE_CURRENT_SOURCE_DIR}/tracing/smpi_traced_simple.c diff --git a/examples/smpi/hvector_test.c b/examples/smpi/hvector_test.c new file mode 100644 index 0000000000..86d1a403d3 --- /dev/null +++ b/examples/smpi/hvector_test.c @@ -0,0 +1,42 @@ +#include +#include "mpi.h" +#define SIZE 4 + +int main(int argc, char **argv) { + + int rank, i, j; + double a[SIZE][SIZE]; + + MPI_Datatype columntype; + + MPI_Init(&argc,&argv); + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + + MPI_Type_hvector(SIZE, 1, SIZE*sizeof(double), MPI_DOUBLE, &columntype); + MPI_Type_commit(&columntype); + + + if (rank == 0) { + for(i=0; i + +int main(int argc, char *argv[]) +{ + int rank, size, i; + MPI_Datatype type, type2; + int blocklen[3] = { 2, 3, 1 }; + int displacement[3] = { 0, 3, 8 }; + int buffer[27]; + MPI_Status status; + + MPI_Init(&argc, &argv); + MPI_Comm_size(MPI_COMM_WORLD, &size); + if (size < 2) + { + printf("Please run with 2 processes.\n"); + MPI_Finalize(); + return 1; + } + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + + MPI_Type_contiguous(3, MPI_INT, &type2); + MPI_Type_commit(&type2); + MPI_Type_indexed(3, blocklen, displacement, type2, &type); + MPI_Type_commit(&type); + + if (rank == 0) + { + for (i=0; i<27; i++) + buffer[i] = i; + MPI_Send(buffer, 1, type, 1, 123, MPI_COMM_WORLD); + } + + if (rank == 1) + { + for (i=0; i<27; i++) + buffer[i] = -1; + MPI_Recv(buffer, 1, type, 0, 123, MPI_COMM_WORLD, &status); + for (i=0; i<27; i++) + printf("buffer[%d] = %d\n", i, buffer[i]); + fflush(stdout); + } + + MPI_Finalize(); + return 0; +} + diff --git a/examples/smpi/struct_test.c b/examples/smpi/struct_test.c new file mode 100644 index 0000000000..5c73e385f3 --- /dev/null +++ b/examples/smpi/struct_test.c @@ -0,0 +1,67 @@ +#include +#include "mpi.h" + +int main( argc, argv ) +int argc; +char **argv; +{ + int rank; + struct { int a;int c; double b;int tab[2][3];} value; + MPI_Datatype mystruct; + int blocklens[3]; + MPI_Aint indices[3]; + MPI_Datatype old_types[3], type2; + int i,j; + + MPI_Init( &argc, &argv ); + + MPI_Comm_rank( MPI_COMM_WORLD, &rank ); + + int tab[2][3]={{1*rank,2*rank,3*rank},{7*rank,8*rank,9*rank}}; + MPI_Type_contiguous(3, MPI_INT, &type2); + MPI_Type_commit(&type2); + + /* One value of each type, and two for the contiguous one */ + blocklens[0] = 1; + blocklens[1] = 1; + blocklens[2] = 2; + /* The base types */ + old_types[0] = MPI_INT; + old_types[1] = MPI_DOUBLE; + old_types[2] = type2; + /* The locations of each element */ + MPI_Address( &value.a, &indices[0] ); + MPI_Address( &value.b, &indices[1] ); + MPI_Address( &tab, &indices[2] ); + /* Make relative */ + indices[2] = indices[2] - indices[0]; + indices[1] = indices[1] - indices[0]; + indices[0] = 0; + + MPI_Type_struct( 3, blocklens, indices, old_types, &mystruct ); + MPI_Type_commit( &mystruct ); + + if (rank == 0){ + value.a=-2; + value.b=8.0; + }else{ + value.a=10000; + value.b=5.0; + } + + MPI_Bcast( &value, 1, mystruct, 0, MPI_COMM_WORLD ); + + printf( "Process %d got %d (-2?) and %lf (8.0?), tab (should be all 0): ", rank, value.a, value.b ); + + for(j=0; j<2;j++ ) + for(i=0; i<3;i++ ) + printf("%d ", tab[j][i]); + + printf("\n"); + + + /* Clean up the type */ + MPI_Type_free( &mystruct ); + MPI_Finalize( ); + return 0; +} diff --git a/src/smpi/private.h b/src/smpi/private.h index ed59446091..6beed4938b 100644 --- a/src/smpi/private.h +++ b/src/smpi/private.h @@ -24,8 +24,6 @@ typedef struct s_smpi_process_data *smpi_process_data_t; #define RECV 0x8 -//***************************************************************************************** - // this struct is here to handle the problem of non-contignous data // for each such structure these function should be implemented (vector // index hvector hindex struct) @@ -34,16 +32,6 @@ typedef struct s_smpi_subtype{ void (*unserialize)(const void * input, void *output, size_t count, void* subtype); } s_smpi_subtype_t; -/*one exemple of implementation for the vector is already here*/ -typedef struct s_smpi_mpi_vector{ - s_smpi_subtype_t base; - size_t block_stride; - size_t block_length; - size_t block_count; - MPI_Datatype old_type; - size_t size_oldtype; -} s_smpi_mpi_vector_t; - typedef struct s_smpi_mpi_datatype{ size_t size; /* this let us know if a serialization is required*/ @@ -55,7 +43,6 @@ typedef struct s_smpi_mpi_datatype{ void *substruct; } s_smpi_mpi_datatype_t; - //***************************************************************************************** typedef struct s_smpi_mpi_request { @@ -129,23 +116,6 @@ void smpi_datatype_create(MPI_Datatype* new_type, int size, int has_subtype, voi void smpi_datatype_free(MPI_Datatype* type); void smpi_datatype_commit(MPI_Datatype* datatype); -void unserialize_vector( const void *contiguous_vector, - void *noncontiguous_vector, - size_t count, - void *type); - -void serialize_vector( const void *noncontiguous_vector, - void *contiguous_vector, - size_t count, - void *type); - -s_smpi_mpi_vector_t* smpi_datatype_vector_create( int block_stride, - int block_length, - int block_count, - MPI_Datatype old_type, - int size_oldtype); - - void smpi_empty_status(MPI_Status * status); MPI_Op smpi_op_new(MPI_User_function * function, int commute); void smpi_op_destroy(MPI_Op op); diff --git a/src/smpi/smpi_mpi_dt.c b/src/smpi/smpi_mpi_dt.c index ec3015c460..a266ec9135 100644 --- a/src/smpi/smpi_mpi_dt.c +++ b/src/smpi/smpi_mpi_dt.c @@ -304,7 +304,7 @@ int smpi_datatype_vector(int count, int blocklen, int stride, MPI_Datatype old_t }else{ /* in this situation the data are contignous thus it's not * required to serialize and unserialize it*/ - smpi_datatype_create(new_type, count * (blocklen) * + smpi_datatype_create(new_type, count * blocklen * smpi_datatype_size(old_type), 0, NULL, @@ -315,6 +315,91 @@ int smpi_datatype_vector(int count, int blocklen, int stride, MPI_Datatype old_t return retval; } + + +/* +Hvector Implementation - Vector with stride in bytes +*/ + + +/* + * Copies noncontiguous data into contiguous memory. + * @param contiguous_hvector - output hvector + * @param noncontiguous_hvector - input hvector + * @param type - pointer contening : + * - stride - stride of between noncontiguous data, in bytes + * - block_length - the width or height of blocked matrix + * - count - the number of rows of matrix + */ +void serialize_hvector( const void *noncontiguous_hvector, + void *contiguous_hvector, + size_t count, + void *type) +{ + s_smpi_mpi_hvector_t* type_c = (s_smpi_mpi_hvector_t*)type; + int i; + char* contiguous_vector_char = (char*)contiguous_hvector; + char* noncontiguous_vector_char = (char*)noncontiguous_hvector; + + for (i = 0; i < type_c->block_count * count; i++) { + memcpy(contiguous_vector_char, + noncontiguous_vector_char, type_c->block_length * type_c->size_oldtype); + + contiguous_vector_char += type_c->block_length*type_c->size_oldtype; + noncontiguous_vector_char += type_c->block_stride; + } +} +/* + * Copies contiguous data into noncontiguous memory. + * @param noncontiguous_vector - output hvector + * @param contiguous_vector - input hvector + * @param type - pointer contening : + * - stride - stride of between noncontiguous data, in bytes + * - block_length - the width or height of blocked matrix + * - count - the number of rows of matrix + */ +void unserialize_hvector( const void *contiguous_vector, + void *noncontiguous_vector, + size_t count, + void *type) +{ + s_smpi_mpi_hvector_t* type_c = (s_smpi_mpi_hvector_t*)type; + int i; + + char* contiguous_vector_char = (char*)contiguous_vector; + char* noncontiguous_vector_char = (char*)noncontiguous_vector; + + for (i = 0; i < type_c->block_count * count; i++) { + memcpy(noncontiguous_vector_char, + contiguous_vector_char, type_c->block_length * type_c->size_oldtype); + + contiguous_vector_char += type_c->block_length*type_c->size_oldtype; + noncontiguous_vector_char += type_c->block_stride; + } +} + +/* + * Create a Sub type vector to be able to serialize and unserialize it + * the structre s_smpi_mpi_vector_t is derived from s_smpi_subtype which + * required the functions unserialize and serialize + * + */ +s_smpi_mpi_hvector_t* smpi_datatype_hvector_create( MPI_Aint block_stride, + int block_length, + int block_count, + MPI_Datatype old_type, + int size_oldtype){ + s_smpi_mpi_hvector_t *new_t= xbt_new(s_smpi_mpi_hvector_t,1); + new_t->base.serialize = &serialize_hvector; + new_t->base.unserialize = &unserialize_hvector; + new_t->block_stride = block_stride; + new_t->block_length = block_length; + new_t->block_count = block_count; + new_t->old_type = old_type; + new_t->size_oldtype = size_oldtype; + return new_t; +} + int smpi_datatype_hvector(int count, int blocklen, MPI_Aint stride, MPI_Datatype old_type, MPI_Datatype* new_type) { int retval; @@ -322,20 +407,115 @@ int smpi_datatype_hvector(int count, int blocklen, MPI_Aint stride, MPI_Datatype if ((old_type->flags & DT_FLAG_COMMITED) != DT_FLAG_COMMITED) { retval = MPI_ERR_TYPE; } else { - /*FIXME: as for the vector the data should be serialized and - * unserialized moreover a structure derived from s_smpi_subtype should - * be created*/ - smpi_datatype_create(new_type, count * ((blocklen * - smpi_datatype_size(old_type))+stride), - 0, - NULL, - DT_FLAG_VECTOR); - retval=MPI_SUCCESS; + if(stride != blocklen*smpi_datatype_size(old_type)){ + s_smpi_mpi_hvector_t* subtype = smpi_datatype_hvector_create( stride, + blocklen, + count, + old_type, + smpi_datatype_size(old_type)); + + smpi_datatype_create(new_type, count * blocklen * + smpi_datatype_size(old_type), + 1, + subtype, + DT_FLAG_VECTOR); + retval=MPI_SUCCESS; + }else{ + smpi_datatype_create(new_type, count * blocklen * + smpi_datatype_size(old_type), + 0, + NULL, + DT_FLAG_VECTOR); + retval=MPI_SUCCESS; + } } return retval; } +/* +Indexed Implementation +*/ + +/* + * Copies noncontiguous data into contiguous memory. + * @param contiguous_indexed - output indexed + * @param noncontiguous_indexed - input indexed + * @param type - pointer contening : + * - stride - stride of between noncontiguous data + * - block_length - the width or height of blocked matrix + * - count - the number of rows of matrix + */ +void serialize_indexed( const void *noncontiguous_indexed, + void *contiguous_indexed, + size_t count, + void *type) +{ + s_smpi_mpi_indexed_t* type_c = (s_smpi_mpi_indexed_t*)type; + int i; + char* contiguous_indexed_char = (char*)contiguous_indexed; + char* noncontiguous_indexed_char = (char*)noncontiguous_indexed; + + for (i = 0; i < type_c->block_count * count; i++) { + memcpy(contiguous_indexed_char, + noncontiguous_indexed_char, type_c->block_lengths[i] * type_c->size_oldtype); + + contiguous_indexed_char += type_c->block_lengths[i]*type_c->size_oldtype; + noncontiguous_indexed_char = (char*)noncontiguous_indexed + type_c->block_indices[i+1]*type_c->size_oldtype; + } +} +/* + * Copies contiguous data into noncontiguous memory. + * @param noncontiguous_indexed - output indexed + * @param contiguous_indexed - input indexed + * @param type - pointer contening : + * - stride - stride of between noncontiguous data + * - block_length - the width or height of blocked matrix + * - count - the number of rows of matrix + */ +void unserialize_indexed( const void *contiguous_indexed, + void *noncontiguous_indexed, + size_t count, + void *type) +{ + s_smpi_mpi_indexed_t* type_c = (s_smpi_mpi_indexed_t*)type; + int i; + + char* contiguous_indexed_char = (char*)contiguous_indexed; + char* noncontiguous_indexed_char = (char*)noncontiguous_indexed; + + for (i = 0; i < type_c->block_count * count; i++) { + memcpy(noncontiguous_indexed_char, + contiguous_indexed_char, type_c->block_lengths[i] * type_c->size_oldtype); + + contiguous_indexed_char += type_c->block_lengths[i]*type_c->size_oldtype; + noncontiguous_indexed_char = (char*)noncontiguous_indexed + type_c->block_indices[i+1]*type_c->size_oldtype; + } +} + +/* + * Create a Sub type indexed to be able to serialize and unserialize it + * the structre s_smpi_mpi_indexed_t is derived from s_smpi_subtype which + * required the functions unserialize and serialize + */ +s_smpi_mpi_indexed_t* smpi_datatype_indexed_create( int* block_lengths, + int* block_indices, + int block_count, + MPI_Datatype old_type, + int size_oldtype){ + s_smpi_mpi_indexed_t *new_t= xbt_new(s_smpi_mpi_indexed_t,1); + new_t->base.serialize = &serialize_indexed; + new_t->base.unserialize = &unserialize_indexed; + //FIXME : copy those or assume they won't be freed ? + new_t->block_lengths = block_lengths; + new_t->block_indices = block_indices; + new_t->block_count = block_count; + new_t->old_type = old_type; + new_t->size_oldtype = size_oldtype; + return new_t; +} + + int smpi_datatype_indexed(int count, int* blocklens, int* indices, MPI_Datatype old_type, MPI_Datatype* new_type) { int i; @@ -349,16 +529,103 @@ int smpi_datatype_indexed(int count, int* blocklens, int* indices, MPI_Datatype if ((old_type->flags & DT_FLAG_COMMITED) != DT_FLAG_COMMITED) { retval = MPI_ERR_TYPE; } else { - /*FIXME: as for the vector the data should be serialized and - * unserialized moreover a structure derived from s_smpi_subtype should - * be created*/ - smpi_datatype_create(new_type, (size) * - smpi_datatype_size(old_type),0, NULL, DT_FLAG_DATA); + s_smpi_mpi_indexed_t* subtype = smpi_datatype_indexed_create( blocklens, + indices, + count, + old_type, + smpi_datatype_size(old_type)); + + smpi_datatype_create(new_type, size * + smpi_datatype_size(old_type),1, subtype, DT_FLAG_DATA); retval=MPI_SUCCESS; } return retval; } + +/* +Hindexed Implementation - Indexed with indices in bytes +*/ + +/* + * Copies noncontiguous data into contiguous memory. + * @param contiguous_hindexed - output hindexed + * @param noncontiguous_hindexed - input hindexed + * @param type - pointer contening : + * - stride - stride of between noncontiguous data + * - block_length - the width or height of blocked matrix + * - count - the number of rows of matrix + */ +void serialize_hindexed( const void *noncontiguous_hindexed, + void *contiguous_hindexed, + size_t count, + void *type) +{ + s_smpi_mpi_hindexed_t* type_c = (s_smpi_mpi_hindexed_t*)type; + int i; + char* contiguous_hindexed_char = (char*)contiguous_hindexed; + char* noncontiguous_hindexed_char = (char*)noncontiguous_hindexed; + + for (i = 0; i < type_c->block_count * count; i++) { + memcpy(contiguous_hindexed_char, + noncontiguous_hindexed_char, type_c->block_lengths[i] * type_c->size_oldtype); + + contiguous_hindexed_char += type_c->block_lengths[i]*type_c->size_oldtype; + noncontiguous_hindexed_char = (char*)noncontiguous_hindexed + type_c->block_indices[i+1]; + } +} +/* + * Copies contiguous data into noncontiguous memory. + * @param noncontiguous_hindexed - output hindexed + * @param contiguous_hindexed - input hindexed + * @param type - pointer contening : + * - stride - stride of between noncontiguous data + * - block_length - the width or height of blocked matrix + * - count - the number of rows of matrix + */ +void unserialize_hindexed( const void *contiguous_hindexed, + void *noncontiguous_hindexed, + size_t count, + void *type) +{ + s_smpi_mpi_hindexed_t* type_c = (s_smpi_mpi_hindexed_t*)type; + int i; + + char* contiguous_hindexed_char = (char*)contiguous_hindexed; + char* noncontiguous_hindexed_char = (char*)noncontiguous_hindexed; + + for (i = 0; i < type_c->block_count * count; i++) { + memcpy(noncontiguous_hindexed_char, + contiguous_hindexed_char, type_c->block_lengths[i] * type_c->size_oldtype); + + contiguous_hindexed_char += type_c->block_lengths[i]*type_c->size_oldtype; + noncontiguous_hindexed_char = (char*)noncontiguous_hindexed + type_c->block_indices[i+1]; + } +} + +/* + * Create a Sub type hindexed to be able to serialize and unserialize it + * the structre s_smpi_mpi_hindexed_t is derived from s_smpi_subtype which + * required the functions unserialize and serialize + */ +s_smpi_mpi_hindexed_t* smpi_datatype_hindexed_create( int* block_lengths, + MPI_Aint* block_indices, + int block_count, + MPI_Datatype old_type, + int size_oldtype){ + s_smpi_mpi_hindexed_t *new_t= xbt_new(s_smpi_mpi_hindexed_t,1); + new_t->base.serialize = &serialize_hindexed; + new_t->base.unserialize = &unserialize_hindexed; + //FIXME : copy those or assume they won't be freed ? + new_t->block_lengths = block_lengths; + new_t->block_indices = block_indices; + new_t->block_count = block_count; + new_t->old_type = old_type; + new_t->size_oldtype = size_oldtype; + return new_t; +} + + int smpi_datatype_hindexed(int count, int* blocklens, MPI_Aint* indices, MPI_Datatype old_type, MPI_Datatype* new_type) { int i; @@ -372,15 +639,99 @@ int smpi_datatype_hindexed(int count, int* blocklens, MPI_Aint* indices, MPI_Dat if ((old_type->flags & DT_FLAG_COMMITED) != DT_FLAG_COMMITED) { retval = MPI_ERR_TYPE; } else { - /*FIXME: as for the vector the data should be serialized and - * unserialized moreover a structure derived from s_smpi_subtype should - * be created*/ - smpi_datatype_create(new_type,(size * smpi_datatype_size(old_type)), 0,NULL, DT_FLAG_DATA); + s_smpi_mpi_hindexed_t* subtype = smpi_datatype_hindexed_create( blocklens, + indices, + count, + old_type, + smpi_datatype_size(old_type)); + + smpi_datatype_create(new_type, size * + smpi_datatype_size(old_type),1, subtype, DT_FLAG_DATA); retval=MPI_SUCCESS; } return retval; } + +/* +struct Implementation - Indexed with indices in bytes +*/ + +/* + * Copies noncontiguous data into contiguous memory. + * @param contiguous_struct - output struct + * @param noncontiguous_struct - input struct + * @param type - pointer contening : + * - stride - stride of between noncontiguous data + * - block_length - the width or height of blocked matrix + * - count - the number of rows of matrix + */ +void serialize_struct( const void *noncontiguous_struct, + void *contiguous_struct, + size_t count, + void *type) +{ + s_smpi_mpi_struct_t* type_c = (s_smpi_mpi_struct_t*)type; + int i; + char* contiguous_struct_char = (char*)contiguous_struct; + char* noncontiguous_struct_char = (char*)noncontiguous_struct; + + for (i = 0; i < type_c->block_count * count; i++) { + memcpy(contiguous_struct_char, + noncontiguous_struct_char, type_c->block_lengths[i] * smpi_datatype_size(type_c->old_types[i])); + contiguous_struct_char += type_c->block_lengths[i]*smpi_datatype_size(type_c->old_types[i]); + noncontiguous_struct_char = (char*)noncontiguous_struct + type_c->block_indices[i+1]; + } +} +/* + * Copies contiguous data into noncontiguous memory. + * @param noncontiguous_struct - output struct + * @param contiguous_struct - input struct + * @param type - pointer contening : + * - stride - stride of between noncontiguous data + * - block_length - the width or height of blocked matrix + * - count - the number of rows of matrix + */ +void unserialize_struct( const void *contiguous_struct, + void *noncontiguous_struct, + size_t count, + void *type) +{ + s_smpi_mpi_struct_t* type_c = (s_smpi_mpi_struct_t*)type; + int i; + + char* contiguous_struct_char = (char*)contiguous_struct; + char* noncontiguous_struct_char = (char*)noncontiguous_struct; + + for (i = 0; i < type_c->block_count * count; i++) { + memcpy(noncontiguous_struct_char, + contiguous_struct_char, type_c->block_lengths[i] * smpi_datatype_size(type_c->old_types[i])); + contiguous_struct_char += type_c->block_lengths[i]*smpi_datatype_size(type_c->old_types[i]); + noncontiguous_struct_char = (char*)noncontiguous_struct + type_c->block_indices[i+1]; + } +} + +/* + * Create a Sub type struct to be able to serialize and unserialize it + * the structre s_smpi_mpi_struct_t is derived from s_smpi_subtype which + * required the functions unserialize and serialize + */ +s_smpi_mpi_struct_t* smpi_datatype_struct_create( int* block_lengths, + MPI_Aint* block_indices, + int block_count, + MPI_Datatype* old_types){ + s_smpi_mpi_struct_t *new_t= xbt_new(s_smpi_mpi_struct_t,1); + new_t->base.serialize = &serialize_struct; + new_t->base.unserialize = &unserialize_struct; + //FIXME : copy those or assume they won't be freed ? + new_t->block_lengths = block_lengths; + new_t->block_indices = block_indices; + new_t->block_count = block_count; + new_t->old_types = old_types; + return new_t; +} + + int smpi_datatype_struct(int count, int* blocklens, MPI_Aint* indices, MPI_Datatype* old_types, MPI_Datatype* new_type) { int i; @@ -394,12 +745,15 @@ int smpi_datatype_struct(int count, int* blocklens, MPI_Aint* indices, MPI_Datat return MPI_ERR_TYPE; size += blocklens[i]*smpi_datatype_size(old_types[i]); } - /*FIXME: as for the vector the data should be serialized and - * unserialized moreover a structure derived from s_smpi_subtype should - * be created*/ - smpi_datatype_create(new_type, size, - 0, NULL, - DT_FLAG_DATA); + + + s_smpi_mpi_struct_t* subtype = smpi_datatype_struct_create( blocklens, + indices, + count, + old_types); + + smpi_datatype_create(new_type, size ,1, subtype, DT_FLAG_DATA); + return MPI_SUCCESS; } diff --git a/src/smpi/smpi_mpi_dt_private.h b/src/smpi/smpi_mpi_dt_private.h index 374f8f8bc5..89fcd659eb 100644 --- a/src/smpi/smpi_mpi_dt_private.h +++ b/src/smpi/smpi_mpi_dt_private.h @@ -32,4 +32,141 @@ extern MPI_Datatype MPI_PTR; + +//***************************************************************************************** + +/* + These are the structures that handle complex data type information, + used for serialization/unserialization of messages +*/ + +typedef struct s_smpi_mpi_vector{ + s_smpi_subtype_t base; + size_t block_stride; + size_t block_length; + size_t block_count; + MPI_Datatype old_type; + size_t size_oldtype; +} s_smpi_mpi_vector_t; + +typedef struct s_smpi_mpi_hvector{ + s_smpi_subtype_t base; + MPI_Aint block_stride; + size_t block_length; + size_t block_count; + MPI_Datatype old_type; + size_t size_oldtype; +} s_smpi_mpi_hvector_t; + +typedef struct s_smpi_mpi_indexed{ + s_smpi_subtype_t base; + int* block_lengths; + int* block_indices; + size_t block_count; + MPI_Datatype old_type; + size_t size_oldtype; +} s_smpi_mpi_indexed_t; + +typedef struct s_smpi_mpi_hindexed{ + s_smpi_subtype_t base; + int* block_lengths; + MPI_Aint* block_indices; + size_t block_count; + MPI_Datatype old_type; + size_t size_oldtype; +} s_smpi_mpi_hindexed_t; + +typedef struct s_smpi_mpi_struct{ + s_smpi_subtype_t base; + int* block_lengths; + MPI_Aint* block_indices; + size_t block_count; + MPI_Datatype* old_types; +} s_smpi_mpi_struct_t; + +/* + Functions to handle serialization/unserialization of messages, 3 for each type of MPI_Type + One for creating the substructure to handle, one for serialization, one for unserialization +*/ + +void unserialize_vector( const void *contiguous_vector, + void *noncontiguous_vector, + size_t count, + void *type); + +void serialize_vector( const void *noncontiguous_vector, + void *contiguous_vector, + size_t count, + void *type); + +s_smpi_mpi_vector_t* smpi_datatype_vector_create( int block_stride, + int block_length, + int block_count, + MPI_Datatype old_type, + int size_oldtype); + +void unserialize_hvector( const void *contiguous_vector, + void *noncontiguous_vector, + size_t count, + void *type); + +void serialize_hvector( const void *noncontiguous_vector, + void *contiguous_vector, + size_t count, + void *type); + +s_smpi_mpi_hvector_t* smpi_datatype_hvector_create( MPI_Aint block_stride, + int block_length, + int block_count, + MPI_Datatype old_type, + int size_oldtype); + + +void unserialize_indexed( const void *contiguous_indexed, + void *noncontiguous_indexed, + size_t count, + void *type); + +void serialize_indexed( const void *noncontiguous_vector, + void *contiguous_vector, + size_t count, + void *type); + +s_smpi_mpi_indexed_t* smpi_datatype_indexed_create(int* block_lengths, + int* block_indices, + int block_count, + MPI_Datatype old_type, + int size_oldtype); + +void unserialize_hindexed( const void *contiguous_indexed, + void *noncontiguous_indexed, + size_t count, + void *type); + +void serialize_hindexed( const void *noncontiguous_vector, + void *contiguous_vector, + size_t count, + void *type); + +s_smpi_mpi_hindexed_t* smpi_datatype_hindexed_create(int* block_lengths, + MPI_Aint* block_indices, + int block_count, + MPI_Datatype old_type, + int size_oldtype); + +void unserialize_struct( const void *contiguous_indexed, + void *noncontiguous_indexed, + size_t count, + void *type); + +void serialize_struct( const void *noncontiguous_vector, + void *contiguous_vector, + size_t count, + void *type); + +s_smpi_mpi_struct_t* smpi_datatype_struct_create(int* block_lengths, + MPI_Aint* block_indices, + int block_count, + MPI_Datatype* old_types); + #endif -- 2.20.1