From 8a4ded6ee6330d304e1d3f69100eb7ec55c5fd9c Mon Sep 17 00:00:00 2001 From: Augustin Degomme Date: Fri, 3 Oct 2014 19:35:54 +0200 Subject: [PATCH] Implement MPI_Keyval_create, MPI_Keyval_free, MPI_Attr_get, MPI_Attr_put, MPI_Attr_delete calls --- src/smpi/private.h | 17 +++++ src/smpi/smpi_base.c | 61 +++++++++++++++ src/smpi/smpi_comm.c | 76 +++++++++++++++++++ src/smpi/smpi_pmpi.c | 68 ++++++++++++----- .../smpi/mpich3-test/attr/CMakeLists.txt | 24 +++--- teshsuite/smpi/mpich3-test/attr/testlist | 17 +++-- 6 files changed, 223 insertions(+), 40 deletions(-) diff --git a/src/smpi/private.h b/src/smpi/private.h index b02770769c..3757eade3a 100644 --- a/src/smpi/private.h +++ b/src/smpi/private.h @@ -113,6 +113,11 @@ typedef struct s_smpi_mpi_request { #endif } s_smpi_mpi_request_t; +typedef struct s_smpi_mpi_key_elem { + MPI_Copy_function* copy_fn; + MPI_Delete_function* delete_fn; +} s_smpi_mpi_key_elem_t; +typedef struct s_smpi_mpi_key_elem *smpi_key_elem; void smpi_process_destroy(void); void smpi_process_finalize(void); @@ -251,6 +256,7 @@ int smpi_comm_size(MPI_Comm comm); void smpi_comm_get_name(MPI_Comm comm, char* name, int* len); int smpi_comm_rank(MPI_Comm comm); MPI_Comm smpi_comm_split(MPI_Comm comm, int color, int key); +MPI_Comm smpi_comm_dup(MPI_Comm comm); void smpi_comm_use(MPI_Comm comm); void smpi_comm_unuse(MPI_Comm comm); void smpi_comm_set_leaders_comm(MPI_Comm comm, MPI_Comm leaders); @@ -403,6 +409,13 @@ int smpi_coll_basic_alltoallv(void *sendbuf, int *sendcounts, void *recvbuf, int *recvcounts, int *recvdisps, MPI_Datatype recvtype, MPI_Comm comm); + +int smpi_keyval_create(MPI_Copy_function* copy_fn, MPI_Delete_function* delete_fn, int* keyval, void* extra_state); +int smpi_keyval_free(int* keyval); +int smpi_attr_delete(MPI_Comm comm, int keyval); +int smpi_attr_get(MPI_Comm comm, int keyval, void* attr_value, int* flag); +int smpi_attr_put(MPI_Comm comm, int keyval, void* attr_value); + // utilities extern double smpi_cpu_threshold; @@ -424,6 +437,10 @@ void* smpi_get_tmp_sendbuffer(int size); void* smpi_get_tmp_recvbuffer(int size); void smpi_free_tmp_buffer(void* buf); +int smpi_comm_attr_delete(MPI_Comm comm, int keyval); +int smpi_comm_attr_get(MPI_Comm comm, int keyval, void* attr_value, int* flag); +int smpi_comm_attr_put(MPI_Comm comm, int keyval, void* attr_value); + // f77 wrappers diff --git a/src/smpi/smpi_base.c b/src/smpi/smpi_base.c index d24ae3aa3f..8398a13f0d 100644 --- a/src/smpi/smpi_base.c +++ b/src/smpi/smpi_base.c @@ -75,6 +75,8 @@ double smpi_wtime_sleep = 0.0; double smpi_iprobe_sleep = 1e-4; double smpi_test_sleep = 1e-4; +xbt_dict_t smpi_keyvals = NULL; +int keyval_id=MPI_TAG_UB+1;//avoid collisions // Methods used to parse and store the values for timing injections in smpi // These are taken from surf/network.c and generalized to have more factors @@ -1587,3 +1589,62 @@ void smpi_mpi_exscan(void *sendbuf, void *recvbuf, int count, xbt_free(tmpbufs); xbt_free(requests); } + + +int smpi_keyval_create(MPI_Copy_function* copy_fn, MPI_Delete_function* delete_fn, int* keyval, void* extra_state){ + + if(!smpi_keyvals) + smpi_keyvals = xbt_dict_new(); + + smpi_key_elem value = (smpi_key_elem) xbt_new0(s_smpi_mpi_key_elem_t,1); + + value->copy_fn=copy_fn; + value->delete_fn=delete_fn; + + *keyval = keyval_id; + + xbt_dict_set(smpi_keyvals,(const char*)keyval,(void*)value, NULL); + keyval_id++; + return MPI_SUCCESS; +} + +int smpi_keyval_free(int* keyval){ + smpi_key_elem elem = xbt_dict_get_or_null(smpi_keyvals, (const char*)keyval); + if(!elem) + return MPI_ERR_ARG; + xbt_dict_remove(smpi_keyvals, (const char*)keyval); + xbt_free(elem); + return MPI_SUCCESS; +} + +int smpi_attr_delete(MPI_Comm comm, int keyval){ + smpi_key_elem elem = xbt_dict_get_or_null(smpi_keyvals, (const char*)&keyval); + if(!elem) + return MPI_ERR_ARG; + if(elem->delete_fn!=MPI_NULL_DELETE_FN){ + void * value; + int flag; + if(smpi_attr_get(comm, keyval, &value, &flag)==MPI_SUCCESS) + elem->delete_fn(comm, keyval, &value, &flag); + } + return smpi_comm_attr_delete(comm, keyval);; +} + +int smpi_attr_get(MPI_Comm comm, int keyval, void* attr_value, int* flag){ + smpi_key_elem elem = xbt_dict_get_or_null(smpi_keyvals, (const char*)&keyval); + if(!elem) + return MPI_ERR_ARG; + return smpi_comm_attr_get(comm, keyval, attr_value, flag);; +} + +int smpi_attr_put(MPI_Comm comm, int keyval, void* attr_value){ + + if(!smpi_keyvals) + smpi_keyvals = xbt_dict_new(); + + smpi_key_elem elem = xbt_dict_get_or_null(smpi_keyvals, (const char*)&keyval); + if(!elem ) + return MPI_ERR_ARG; + return smpi_comm_attr_put(comm, keyval, attr_value);; +} + diff --git a/src/smpi/smpi_comm.c b/src/smpi/smpi_comm.c index cfc23cd615..d108f6d5f9 100644 --- a/src/smpi/smpi_comm.c +++ b/src/smpi/smpi_comm.c @@ -7,12 +7,15 @@ #include #include "private.h" +#include "xbt/dict.h" #include "smpi_mpi_dt_private.h" #include "limits.h" #include "simix/smx_private.h" #include "colls/colls.h" +#include "xbt/ex.h" +extern xbt_dict_t smpi_keyvals; XBT_LOG_NEW_DEFAULT_SUBCATEGORY(smpi_comm, smpi, "Logging specific to SMPI (comm)"); @@ -34,6 +37,7 @@ typedef struct s_smpi_mpi_communicator { int is_uniform; int* non_uniform_map; //set if smp nodes have a different number of processes allocated int is_blocked;// are ranks allocated on the same smp node contiguous ? + xbt_dict_t attributes; } s_smpi_mpi_communicator_t; static int smpi_compare_rankmap(const void *a, const void *b) @@ -72,6 +76,7 @@ MPI_Comm smpi_comm_new(MPI_Group group, MPI_Topology topo) comm->non_uniform_map = NULL; comm->leaders_map = NULL; comm->is_blocked=0; + comm->attributes=NULL; return comm; } @@ -84,6 +89,32 @@ void smpi_comm_destroy(MPI_Comm comm) smpi_comm_unuse(comm); } +MPI_Comm smpi_comm_dup(MPI_Comm comm){ + if(smpi_privatize_global_variables){ //we need to switch here, as the called function may silently touch global variables + smpi_switch_data_segment(smpi_process_index()); + } + MPI_Comm newcomm = smpi_comm_new(smpi_comm_group(comm), smpi_comm_topo(comm)); + + if(comm->attributes !=NULL){ + newcomm->attributes=xbt_dict_new(); + xbt_dict_cursor_t cursor = NULL; + int *key; + int flag; + void* value_in; + void* value_out; + xbt_dict_foreach(comm->attributes, cursor, key, value_in){ + smpi_key_elem elem = xbt_dict_get_or_null(smpi_keyvals, (const char*)key); + if(elem && elem->copy_fn!=MPI_NULL_COPY_FN){ + elem->copy_fn(comm, *key, NULL, value_in, &value_out, &flag ); + if(flag) + xbt_dict_set(newcomm->attributes, (const char*)key,value_out, NULL); + } + } + } + return newcomm; +} + + MPI_Group smpi_comm_group(MPI_Comm comm) { if (comm == MPI_COMM_UNINITIALIZED) @@ -273,6 +304,17 @@ void smpi_comm_unuse(MPI_Comm comm){ xbt_free(comm->non_uniform_map); if(comm->leaders_map !=NULL) xbt_free(comm->leaders_map); + if(comm->attributes !=NULL){ + xbt_dict_cursor_t cursor = NULL; + char *key; + smpi_key_elem elem; + void * value; + int flag; + xbt_dict_foreach(comm->attributes, cursor, key, elem){ + if(smpi_attr_get(comm, (int)key, &value, &flag)==MPI_SUCCESS) + elem->delete_fn(comm, (int)key, &value, &flag); + } + } xbt_free(comm); } } @@ -468,3 +510,37 @@ void smpi_comm_init_smp(MPI_Comm comm){ smpi_process_set_replaying(1); } + +int smpi_comm_attr_delete(MPI_Comm comm, int keyval){ + if(comm->attributes==NULL) + return MPI_ERR_ARG; + + xbt_dict_remove(comm->attributes, (const char*)&keyval); + return MPI_SUCCESS; +} +int smpi_comm_attr_get(MPI_Comm comm, int keyval, void* attr_value, int* flag){ + xbt_ex_t ex; + if(comm->attributes==NULL){ + *flag=0; + return MPI_SUCCESS; + } + TRY { + *(void**)attr_value = xbt_dict_get(comm->attributes, (const char*)&keyval); + *flag=1; + } + CATCH(ex) { + *flag=0; + xbt_ex_free(ex); + } + + return MPI_SUCCESS; +} + +int smpi_comm_attr_put(MPI_Comm comm, int keyval, void* attr_value){ + if(comm->attributes==NULL) + comm->attributes=xbt_dict_new(); + + xbt_dict_set(comm->attributes, (const char*)&keyval, attr_value, NULL); + return MPI_SUCCESS; +} + diff --git a/src/smpi/smpi_pmpi.c b/src/smpi/smpi_pmpi.c index 899f7cb9af..dac9d03373 100644 --- a/src/smpi/smpi_pmpi.c +++ b/src/smpi/smpi_pmpi.c @@ -773,7 +773,7 @@ int PMPI_Comm_dup(MPI_Comm comm, MPI_Comm * newcomm) } else if (newcomm == NULL) { retval = MPI_ERR_ARG; } else { - *newcomm = smpi_comm_new(smpi_comm_group(comm), smpi_comm_topo(comm)); + *newcomm = smpi_comm_dup(comm); retval = MPI_SUCCESS; } return retval; @@ -2955,6 +2955,52 @@ MPI_Fint PMPI_Comm_c2f(MPI_Comm comm){ return smpi_comm_c2f(comm); } +int PMPI_Keyval_create(MPI_Copy_function* copy_fn, MPI_Delete_function* delete_fn, int* keyval, void* extra_state) { + return smpi_keyval_create(copy_fn, delete_fn, keyval, extra_state); +} + +int PMPI_Keyval_free(int* keyval) { + return smpi_keyval_free(keyval); +} + +int PMPI_Attr_delete(MPI_Comm comm, int keyval) { + if(keyval == MPI_TAG_UB||keyval == MPI_HOST||keyval == MPI_IO + ||keyval == MPI_WTIME_IS_GLOBAL||keyval == MPI_APPNUM + ||keyval == MPI_UNIVERSE_SIZE||keyval == MPI_LASTUSEDCODE) + return MPI_ERR_ARG; + else if (comm==MPI_COMM_NULL) + return MPI_ERR_COMM; + else + return smpi_attr_delete(comm, keyval); +} + +int PMPI_Attr_get(MPI_Comm comm, int keyval, void* attr_value, int* flag) { + if (comm==MPI_COMM_NULL){ + *flag=0; + return MPI_ERR_COMM; + } else if(keyval == MPI_TAG_UB||keyval == MPI_HOST||keyval == MPI_IO + ||keyval == MPI_WTIME_IS_GLOBAL||keyval == MPI_APPNUM + ||keyval == MPI_UNIVERSE_SIZE||keyval == MPI_LASTUSEDCODE){ + *flag=1; + //FIXME : not ideal and leaky, but should not be called too much + int* res = xbt_new(int, 1); + *res=keyval; + attr_value=(void*)res; + return MPI_SUCCESS; + } else + return smpi_attr_get(comm, keyval, attr_value, flag); +} + +int PMPI_Attr_put(MPI_Comm comm, int keyval, void* attr_value) { + if(keyval == MPI_TAG_UB||keyval == MPI_HOST||keyval == MPI_IO + ||keyval == MPI_WTIME_IS_GLOBAL||keyval == MPI_APPNUM + ||keyval == MPI_UNIVERSE_SIZE||keyval == MPI_LASTUSEDCODE) + return MPI_ERR_ARG; + else if (comm==MPI_COMM_NULL) + return MPI_ERR_COMM; + else + return smpi_attr_put(comm, keyval, attr_value); +} /* The following calls are not yet implemented and will fail at runtime. */ /* Once implemented, please move them above this notice. */ @@ -3152,18 +3198,6 @@ int PMPI_Comm_remote_size(MPI_Comm comm, int* size) { NOT_YET_IMPLEMENTED } -int PMPI_Attr_delete(MPI_Comm comm, int keyval) { - NOT_YET_IMPLEMENTED -} - -int PMPI_Attr_get(MPI_Comm comm, int keyval, void* attr_value, int* flag) { - NOT_YET_IMPLEMENTED -} - -int PMPI_Attr_put(MPI_Comm comm, int keyval, void* attr_value) { - NOT_YET_IMPLEMENTED -} - int PMPI_Rsend(void* buf, int count, MPI_Datatype datatype, int dest, int tag, MPI_Comm comm) { NOT_YET_IMPLEMENTED } @@ -3176,14 +3210,6 @@ int PMPI_Irsend(void* buf, int count, MPI_Datatype datatype, int dest, int tag, NOT_YET_IMPLEMENTED } -int PMPI_Keyval_create(MPI_Copy_function* copy_fn, MPI_Delete_function* delete_fn, int* keyval, void* extra_state) { - NOT_YET_IMPLEMENTED -} - -int PMPI_Keyval_free(int* keyval) { - NOT_YET_IMPLEMENTED -} - int PMPI_Test_cancelled(MPI_Status* status, int* flag) { NOT_YET_IMPLEMENTED } diff --git a/teshsuite/smpi/mpich3-test/attr/CMakeLists.txt b/teshsuite/smpi/mpich3-test/attr/CMakeLists.txt index 95c7d48c6b..a6bd72b7de 100644 --- a/teshsuite/smpi/mpich3-test/attr/CMakeLists.txt +++ b/teshsuite/smpi/mpich3-test/attr/CMakeLists.txt @@ -15,36 +15,36 @@ if(enable_smpi AND enable_smpi_MPICH3_testsuite) # add_executable(attr2type attr2type.c) add_executable(attrend2 attrend2.c) -# add_executable(attrend attrend.c) -# add_executable(attrerr attrerr.c) + add_executable(attrend attrend.c) + add_executable(attrerr attrerr.c) # add_executable(attrerrcomm attrerrcomm.c) # add_executable(attrerrtype attrerrtype.c) # add_executable(attric attric.c) -# add_executable(attrorder attrorder.c) + add_executable(attrorder attrorder.c) # add_executable(attrordercomm attrordercomm.c) # add_executable(attrordertype attrordertype.c) -# add_executable(attrt attrt.c) -# add_executable(baseattr2 baseattr2.c) + add_executable(attrt attrt.c) + add_executable(baseattr2 baseattr2.c) # add_executable(baseattrcomm baseattrcomm.c) -# add_executable(fkeyval fkeyval.c) + add_executable(fkeyval fkeyval.c) # add_executable(fkeyvalcomm fkeyvalcomm.c) # add_executable(fkeyvaltype fkeyvaltype.c) # add_executable(keyval_double_free keyval_double_free.c) # target_link_libraries(attr2type simgrid mtest_c) target_link_libraries(attrend2 simgrid mtest_c) -# target_link_libraries(attrend simgrid mtest_c) -# target_link_libraries(attrerr simgrid mtest_c) + target_link_libraries(attrend simgrid mtest_c) + target_link_libraries(attrerr simgrid mtest_c) # target_link_libraries(attrerrcomm simgrid mtest_c) # target_link_libraries(attrerrtype simgrid mtest_c) # target_link_libraries(attric simgrid mtest_c) -# target_link_libraries(attrorder simgrid mtest_c) + target_link_libraries(attrorder simgrid mtest_c) # target_link_libraries(attrordercomm simgrid mtest_c) # target_link_libraries(attrordertype simgrid mtest_c) -# target_link_libraries(attrt simgrid mtest_c) -# target_link_libraries(baseattr2 simgrid mtest_c) + target_link_libraries(attrt simgrid mtest_c) + target_link_libraries(baseattr2 simgrid mtest_c) # target_link_libraries(baseattrcomm simgrid mtest_c) -# target_link_libraries(fkeyval simgrid mtest_c) + target_link_libraries(fkeyval simgrid mtest_c) # target_link_libraries(fkeyvalcomm simgrid mtest_c) # target_link_libraries(fkeyvaltype simgrid mtest_c) # target_link_libraries(keyval_double_free simgrid mtest_c) diff --git a/teshsuite/smpi/mpich3-test/attr/testlist b/teshsuite/smpi/mpich3-test/attr/testlist index 368d246098..7a71bcd03a 100644 --- a/teshsuite/smpi/mpich3-test/attr/testlist +++ b/teshsuite/smpi/mpich3-test/attr/testlist @@ -1,10 +1,13 @@ -#needs MPI_Keyval_create and MPI_Attr_get -#attrt 2 +attrt 2 #needs MPI_Intercomm_create #attric 4 -#needs MPI_Errhandler_set, MPI_Keyval_create, MPI_Keyval_free, MPI_Attr_put +#TODO #attrerr 1 -#needs MPI_Keyval_create, MPI_Keyval_free, MPI_Attr_put +# The MPI-2 specification makes it clear that delect attributes are +# called on MPI_COMM_WORLD and MPI_COMM_SELF at the very beginning of +# MPI_Finalize. This is useful for tools that want to perform the MPI +# equivalent of an "at_exit" action. +# SMPI does not keep a copy of comm_self at all times for memory reasons... #attrend 1 #attrend 4 attrend2 1 @@ -15,17 +18,17 @@ attrend2 5 #attrerrtype 1 #needs MPI_Type_create_keyval, MPI_Type_dup, MPI_Type_set_attr #attr2type 1 -#needs MPI_Keyval_create, MPI_Keyval_free, MPI_Attr_put, MPI_Attr_get, MPI_Attr_delete -#attrorder 1 +attrorder 1 #needs MPI_Comm_create_keyval, MPI_Comm_free_keyval, MPI_Comm_get_attr, MPI_Comm_set_attr, MPI_Comm_delete_attr #attrordercomm 1 #needs MPI_Type_create_keyval, MPI_Type_delete_keyval, MPI_Type_set_attr, MPI_Type_delete_attr #attrordertype 1 -#needs MPI_Errhandler_set, MPI_Attr_get +#TODO #baseattr2 1 #needs MPI_Comm_get_attr #baseattrcomm 1 #MPI_Keyval_create, MPI_Keyval_free for type and comm also +#TODO #fkeyval 1 #fkeyvalcomm 1 #fkeyvaltype 1 -- 2.20.1