X-Git-Url: http://info.iut-bm.univ-fcomte.fr/pub/gitweb/simgrid.git/blobdiff_plain/105c1b117af96a9f150b5c06ed68209a8c66e052..7f2b5ea49487adf6b6d075435936f060617c96ad:/src/smpi/smpi_mpi_dt.c diff --git a/src/smpi/smpi_mpi_dt.c b/src/smpi/smpi_mpi_dt.c index 4cd5f6454e..bb63c6bc69 100644 --- a/src/smpi/smpi_mpi_dt.c +++ b/src/smpi/smpi_mpi_dt.c @@ -1,7 +1,7 @@ /* smpi_mpi_dt.c -- MPI primitives to handle datatypes */ /* FIXME: a very incomplete implementation */ -/* Copyright (c) 2009-2014. The SimGrid Team. +/* Copyright (c) 2009-2015. The SimGrid Team. * All rights reserved. */ /* This program is free software; you can redistribute it and/or modify it @@ -10,7 +10,7 @@ #include #include #include - +#include #include "private.h" #include "smpi_mpi_dt_private.h" #include "mc/mc.h" @@ -20,29 +20,36 @@ XBT_LOG_NEW_DEFAULT_SUBCATEGORY(smpi_mpi_dt, smpi, "Logging specific to SMPI (datatype)"); -#define CREATE_MPI_DATATYPE(name, type) \ - static s_smpi_mpi_datatype_t mpi_##name = { \ +xbt_dict_t smpi_type_keyvals = NULL; +int type_keyval_id=0;//avoid collisions + +#define CREATE_MPI_DATATYPE(name, type) \ + static s_smpi_mpi_datatype_t mpi_##name = { \ (char*) # name, \ - sizeof(type), /* size */ \ - 0, /*was 1 has_subtype*/ \ - 0, /* lb */ \ - sizeof(type), /* ub = lb + size */ \ - DT_FLAG_BASIC, /* flags */ \ - NULL /* pointer on extended struct*/ \ - }; \ -MPI_Datatype name = &mpi_##name; - -#define CREATE_MPI_DATATYPE_NULL(name) \ - static s_smpi_mpi_datatype_t mpi_##name = { \ + sizeof(type), /* size */ \ + 0, /*was 1 has_subtype*/ \ + 0, /* lb */ \ + sizeof(type), /* ub = lb + size */ \ + DT_FLAG_BASIC, /* flags */ \ + NULL, /* attributes */ \ + NULL, /* pointer on extended struct*/ \ + 0 /* in_use counter */ \ + }; \ +const MPI_Datatype name = &mpi_##name; + +#define CREATE_MPI_DATATYPE_NULL(name) \ + static s_smpi_mpi_datatype_t mpi_##name = { \ (char*) # name, \ - 0, /* size */ \ - 0, /*was 1 has_subtype*/ \ - 0, /* lb */ \ - 0, /* ub = lb + size */ \ - DT_FLAG_BASIC, /* flags */ \ - NULL /* pointer on extended struct*/ \ - }; \ -MPI_Datatype name = &mpi_##name; + 0, /* size */ \ + 0, /* was 1 has_subtype*/ \ + 0, /* lb */ \ + 0, /* ub = lb + size */ \ + DT_FLAG_BASIC, /* flags */ \ + NULL, /* attributes */ \ + NULL, /* pointer on extended struct*/ \ + 0 /* in_use counter */ \ + }; \ +const MPI_Datatype name = &mpi_##name; //The following are datatypes for the MPI functions MPI_MAXLOC and MPI_MINLOC. typedef struct { @@ -126,6 +133,7 @@ CREATE_MPI_DATATYPE(MPI_2FLOAT, float_float); CREATE_MPI_DATATYPE(MPI_2DOUBLE, double_double); CREATE_MPI_DATATYPE(MPI_2LONG, long_long); +CREATE_MPI_DATATYPE(MPI_REAL, float); CREATE_MPI_DATATYPE(MPI_REAL4, float); CREATE_MPI_DATATYPE(MPI_REAL8, float); CREATE_MPI_DATATYPE(MPI_REAL16, double); @@ -142,7 +150,7 @@ CREATE_MPI_DATATYPE(MPI_LONG_DOUBLE_INT, long_double_int); CREATE_MPI_DATATYPE_NULL(MPI_UB); CREATE_MPI_DATATYPE_NULL(MPI_LB); -CREATE_MPI_DATATYPE_NULL(MPI_PACKED); +CREATE_MPI_DATATYPE(MPI_PACKED, char); // Internal use only CREATE_MPI_DATATYPE(MPI_PTR, void*); @@ -150,8 +158,7 @@ CREATE_MPI_DATATYPE(MPI_PTR, void*); */ int is_datatype_valid(MPI_Datatype datatype) { return datatype != MPI_DATATYPE_NULL - && (datatype->flags & DT_FLAG_COMMITED) - && (smpi_datatype_size(datatype)>=0); + && (datatype->flags & DT_FLAG_COMMITED); } size_t smpi_datatype_size(MPI_Datatype datatype) @@ -169,15 +176,39 @@ MPI_Aint smpi_datatype_ub(MPI_Datatype datatype) return datatype->ub; } -MPI_Datatype smpi_datatype_dup(MPI_Datatype datatype) +int smpi_datatype_dup(MPI_Datatype datatype, MPI_Datatype* new_t) { - MPI_Datatype new_t= xbt_new(s_smpi_mpi_datatype_t,1); - memcpy(new_t, datatype, sizeof(s_smpi_mpi_datatype_t)); - if (datatype->has_subtype) - memcpy(new_t->substruct, datatype->substruct, sizeof(s_smpi_subtype_t)); + int ret=MPI_SUCCESS; + *new_t= xbt_new(s_smpi_mpi_datatype_t,1); + memcpy(*new_t, datatype, sizeof(s_smpi_mpi_datatype_t)); + if (datatype->has_subtype){ + //FIXME: may copy too much information. + (*new_t)->substruct=xbt_malloc(sizeof(s_smpi_mpi_struct_t)); + memcpy((*new_t)->substruct, datatype->substruct, sizeof(s_smpi_mpi_struct_t)); + } if(datatype->name) - new_t->name = strdup(datatype->name); - return new_t; + (*new_t)->name = xbt_strdup(datatype->name); + if(datatype->attributes !=NULL){ + (*new_t)->attributes=xbt_dict_new(); + xbt_dict_cursor_t cursor = NULL; + int *key; + int flag; + void* value_in; + void* value_out; + xbt_dict_foreach(datatype->attributes, cursor, key, value_in){ + smpi_type_key_elem elem = xbt_dict_get_or_null_ext(smpi_type_keyvals, (const char*)key, sizeof(int)); + if(elem && elem->copy_fn!=MPI_NULL_COPY_FN){ + ret = elem->copy_fn(datatype, *key, NULL, value_in, &value_out, &flag ); + if(ret!=MPI_SUCCESS){ + *new_t=MPI_DATATYPE_NULL; + return ret; + } + if(flag) + xbt_dict_set_ext((*new_t)->attributes, (const char*)key, sizeof(int),value_out, NULL); + } + } + } + return ret; } int smpi_datatype_extent(MPI_Datatype datatype, MPI_Aint * lb, @@ -206,7 +237,7 @@ void smpi_datatype_get_name(MPI_Datatype datatype, char* name, int* length){ } void smpi_datatype_set_name(MPI_Datatype datatype, char* name){ - datatype->name = strdup(name);; + datatype->name = xbt_strdup(name);; } int smpi_datatype_copy(void *sendbuf, int sendcount, MPI_Datatype sendtype, @@ -214,7 +245,7 @@ int smpi_datatype_copy(void *sendbuf, int sendcount, MPI_Datatype sendtype, { int count; if(smpi_privatize_global_variables){ - switch_data_segment(smpi_process_index()); + smpi_switch_data_segment(smpi_process_index()); } /* First check if we really have something to do */ if (recvcount > 0 && recvbuf != sendbuf) { @@ -224,17 +255,17 @@ int smpi_datatype_copy(void *sendbuf, int sendcount, MPI_Datatype sendtype, count = sendcount < recvcount ? sendcount : recvcount; if(sendtype->has_subtype == 0 && recvtype->has_subtype == 0) { - if(!_xbt_replay_is_active()) memcpy(recvbuf, sendbuf, count); + if(!smpi_process_get_replaying()) memcpy(recvbuf, sendbuf, count); } else if (sendtype->has_subtype == 0) { s_smpi_subtype_t *subtype = recvtype->substruct; - subtype->unserialize( sendbuf, recvbuf,1, subtype, MPI_REPLACE); + subtype->unserialize( sendbuf, recvbuf, recvcount/smpi_datatype_size(recvtype), subtype, MPI_REPLACE); } else if (recvtype->has_subtype == 0) { s_smpi_subtype_t *subtype = sendtype->substruct; - subtype->serialize(sendbuf, recvbuf,1, subtype); + subtype->serialize(sendbuf, recvbuf, sendcount/smpi_datatype_size(sendtype), subtype); }else{ s_smpi_subtype_t *subtype = sendtype->substruct; @@ -365,6 +396,7 @@ void smpi_datatype_create(MPI_Datatype* new_type, int size,int lb, int ub, int h new_t->flags = flags; new_t->substruct = struct_type; new_t->in_use=0; + new_t->attributes=NULL; *new_type = new_t; #ifdef HAVE_MC @@ -374,6 +406,18 @@ void smpi_datatype_create(MPI_Datatype* new_type, int size,int lb, int ub, int h } void smpi_datatype_free(MPI_Datatype* type){ + xbt_assert((*type)->in_use >= 0); + if((*type)->attributes !=NULL){ + xbt_dict_cursor_t cursor = NULL; + int* key; + void * value; + int flag; + xbt_dict_foreach((*type)->attributes, cursor, key, value){ + smpi_type_key_elem elem = xbt_dict_get_or_null_ext(smpi_type_keyvals, (const char*)key, sizeof(int)); + if(elem && elem->delete_fn) + elem->delete_fn(*type,*key, value, &flag); + } + } if((*type)->flags & DT_FLAG_PREDEFINED)return; @@ -405,7 +449,10 @@ void smpi_datatype_use(MPI_Datatype type){ void smpi_datatype_unuse(MPI_Datatype type){ - if(type && type->in_use-- == 0 && (type->flags & DT_FLAG_DESTROYED)) + if (type->in_use > 0) + type->in_use--; + + if(type && type->in_use == 0 && (type->flags & DT_FLAG_DESTROYED)) smpi_datatype_free(&type); #ifdef HAVE_MC @@ -1616,11 +1663,119 @@ void smpi_op_destroy(MPI_Op op) void smpi_op_apply(MPI_Op op, void *invec, void *inoutvec, int *len, MPI_Datatype * datatype) { + if(op==MPI_OP_NULL) + return; + if(smpi_privatize_global_variables){ //we need to switch here, as the called function may silently touch global variables - XBT_VERB("Applying operation, switch to the right data frame "); - switch_data_segment(smpi_process_index()); + XBT_DEBUG("Applying operation, switch to the right data frame "); + smpi_switch_data_segment(smpi_process_index()); } - if(!_xbt_replay_is_active()) + if(!smpi_process_get_replaying()) op->func(invec, inoutvec, len, datatype); } + +int smpi_type_attr_delete(MPI_Datatype type, int keyval){ + smpi_type_key_elem elem = xbt_dict_get_or_null_ext(smpi_type_keyvals, (const char*)&keyval, sizeof(int)); + if(!elem) + return MPI_ERR_ARG; + if(elem->delete_fn!=MPI_NULL_DELETE_FN){ + void * value; + int flag; + if(smpi_type_attr_get(type, keyval, &value, &flag)==MPI_SUCCESS){ + int ret = elem->delete_fn(type, keyval, value, &flag); + if(ret!=MPI_SUCCESS) return ret; + } + } + if(type->attributes==NULL) + return MPI_ERR_ARG; + + xbt_dict_remove_ext(type->attributes, (const char*)&keyval, sizeof(int)); + return MPI_SUCCESS; +} + +int smpi_type_attr_get(MPI_Datatype type, int keyval, void* attr_value, int* flag){ + smpi_type_key_elem elem = xbt_dict_get_or_null_ext(smpi_type_keyvals, (const char*)&keyval, sizeof(int)); + if(!elem) + return MPI_ERR_ARG; + xbt_ex_t ex; + if(type->attributes==NULL){ + *flag=0; + return MPI_SUCCESS; + } + TRY { + *(void**)attr_value = xbt_dict_get_ext(type->attributes, (const char*)&keyval, sizeof(int)); + *flag=1; + } + CATCH(ex) { + *flag=0; + xbt_ex_free(ex); + } + return MPI_SUCCESS; +} + +int smpi_type_attr_put(MPI_Datatype type, int keyval, void* attr_value){ + if(!smpi_type_keyvals) + smpi_type_keyvals = xbt_dict_new(); + smpi_type_key_elem elem = xbt_dict_get_or_null_ext(smpi_type_keyvals, (const char*)&keyval, sizeof(int)); + if(!elem ) + return MPI_ERR_ARG; + int flag; + void* value; + smpi_type_attr_get(type, keyval, &value, &flag); + if(flag && elem->delete_fn!=MPI_NULL_DELETE_FN){ + int ret = elem->delete_fn(type, keyval, value, &flag); + if(ret!=MPI_SUCCESS) return ret; + } + if(type->attributes==NULL) + type->attributes=xbt_dict_new(); + + xbt_dict_set_ext(type->attributes, (const char*)&keyval, sizeof(int), attr_value, NULL); + return MPI_SUCCESS; +} + +int smpi_type_keyval_create(MPI_Type_copy_attr_function* copy_fn, MPI_Type_delete_attr_function* delete_fn, int* keyval, void* extra_state){ + + if(!smpi_type_keyvals) + smpi_type_keyvals = xbt_dict_new(); + + smpi_type_key_elem value = (smpi_type_key_elem) xbt_new0(s_smpi_mpi_type_key_elem_t,1); + + value->copy_fn=copy_fn; + value->delete_fn=delete_fn; + + *keyval = type_keyval_id; + xbt_dict_set_ext(smpi_type_keyvals,(const char*)keyval, sizeof(int),(void*)value, NULL); + type_keyval_id++; + return MPI_SUCCESS; +} + +int smpi_type_keyval_free(int* keyval){ + smpi_type_key_elem elem = xbt_dict_get_or_null_ext(smpi_type_keyvals, (const char*)keyval, sizeof(int)); + if(!elem){ + return MPI_ERR_ARG; + } + xbt_dict_remove_ext(smpi_type_keyvals, (const char*)keyval, sizeof(int)); + xbt_free(elem); + return MPI_SUCCESS; +} + +int smpi_mpi_pack(void* inbuf, int incount, MPI_Datatype type, void* outbuf, int outcount, int* position, MPI_Comm comm){ + size_t size = smpi_datatype_size(type); + if (outcount - *position < incount*size) + return MPI_ERR_BUFFER; + smpi_datatype_copy(inbuf, incount, type, + (char*)outbuf + *position, outcount, MPI_CHAR); + *position += incount * size; + return MPI_SUCCESS; +} + +int smpi_mpi_unpack(void* inbuf, int insize, int* position, void* outbuf, int outcount, MPI_Datatype type, MPI_Comm comm){ + size_t size = smpi_datatype_size(type); + if (outcount*size> insize) + return MPI_ERR_BUFFER; + smpi_datatype_copy((char*)inbuf + *position, insize, MPI_CHAR, + outbuf, outcount, type); + *position += outcount * size; + return MPI_SUCCESS; +}