X-Git-Url: http://info.iut-bm.univ-fcomte.fr/pub/gitweb/simgrid.git/blobdiff_plain/29aa074252888a50d97e3069f51ffb8e6cf99101..49fc6d8c6a29c5da6aa35c1427e93134454fafbb:/src/smpi/smpi_datatype.cpp diff --git a/src/smpi/smpi_datatype.cpp b/src/smpi/smpi_datatype.cpp index 3ff3f33bfe..2a774f30ac 100644 --- a/src/smpi/smpi_datatype.cpp +++ b/src/smpi/smpi_datatype.cpp @@ -1,5 +1,5 @@ /* smpi_datatype.cpp -- MPI primitives to handle datatypes */ -/* Copyright (c) 2009-2015. The SimGrid Team. +/* Copyright (c) 2009-2017. The SimGrid Team. * All rights reserved. */ /* This program is free software; you can redistribute it and/or modify it @@ -8,23 +8,18 @@ #include "mc/mc.h" #include "private.h" #include "simgrid/modelchecker.h" -#include "smpi_mpi_dt_private.h" -#include "xbt/replay.h" #include #include #include #include #include +#include #include -XBT_LOG_NEW_DEFAULT_SUBCATEGORY(smpi_mpi_dt, smpi, "Logging specific to SMPI (datatype)"); - -xbt_dict_t smpi_type_keyvals = nullptr; -int type_keyval_id=0;//avoid collisions - +XBT_LOG_NEW_DEFAULT_SUBCATEGORY(smpi_datatype, smpi, "Logging specific to SMPI (datatype)"); #define CREATE_MPI_DATATYPE(name, type) \ - static Datatype mpi_##name ( \ + static simgrid::smpi::Datatype mpi_##name ( \ (char*) # name, \ sizeof(type), /* size */ \ 0, /* lb */ \ @@ -34,7 +29,7 @@ int type_keyval_id=0;//avoid collisions const MPI_Datatype name = &mpi_##name; #define CREATE_MPI_DATATYPE_NULL(name) \ - static Datatype mpi_##name ( \ + static simgrid::smpi::Datatype mpi_##name ( \ (char*) # name, \ 0, /* size */ \ 0, /* lb */ \ @@ -108,103 +103,90 @@ CREATE_MPI_DATATYPE(MPI_PTR, void*); namespace simgrid{ namespace smpi{ -Datatype::Datatype(int size,int lb, int ub, int flags) : name_(nullptr), lb_(lb), ub_(ub), flags_(flags), attributes_(nullptr), in_use_(1){ +std::unordered_map Datatype::keyvals_; +int Datatype::keyval_id_=0; + +Datatype::Datatype(int size,MPI_Aint lb, MPI_Aint ub, int flags) : name_(nullptr), size_(size), lb_(lb), ub_(ub), flags_(flags), refcount_(1){ #if HAVE_MC if(MC_is_active()) - MC_ignore(&(in_use_), sizeof(in_use_)); + MC_ignore(&(refcount_), sizeof(refcount_)); #endif } //for predefined types, so in_use = 0. -Datatype::Datatype(char* name, int size,int lb, int ub, int flags) : name_(name), lb_(lb), ub_(ub), flags_(flags), attributes_(nullptr), in_use_(0){ +Datatype::Datatype(char* name, int size,MPI_Aint lb, MPI_Aint ub, int flags) : name_(name), size_(size), lb_(lb), ub_(ub), flags_(flags), refcount_(0){ #if HAVE_MC if(MC_is_active()) - MC_ignore(&(in_use_), sizeof(in_use_)); + MC_ignore(&(refcount_), sizeof(refcount_)); #endif } - -//TODO : subtypes ? -Datatype::Datatype(Datatype &datatype) : lb_(datatype.lb_), ub_(datatype.ub_), flags_(datatype.flags_), in_use_(1) +Datatype::Datatype(Datatype *datatype, int* ret) : name_(nullptr), lb_(datatype->lb_), ub_(datatype->ub_), flags_(datatype->flags_), refcount_(1) { flags_ &= ~DT_FLAG_PREDEFINED; - if(datatype.name_) - name_ = xbt_strdup(datatype.name_); - if(datatype.attributes_ !=nullptr){ - attributes_ = xbt_dict_new_homogeneous(nullptr); - xbt_dict_cursor_t cursor = nullptr; - char* key; + *ret = MPI_SUCCESS; + if(datatype->name_) + name_ = xbt_strdup(datatype->name_); + + if(!(datatype->attributes()->empty())){ int flag; - void* value_in; void* value_out; - xbt_dict_foreach (datatype.attributes_, cursor, key, value_in) { - smpi_type_key_elem elem = - static_cast(xbt_dict_get_or_null_ext(smpi_type_keyvals, key, sizeof(int))); - if (elem != nullptr && elem->copy_fn != MPI_NULL_COPY_FN) { - int ret = elem->copy_fn(&datatype, atoi(key), nullptr, value_in, &value_out, &flag); - if (ret != MPI_SUCCESS) { -// smpi_datatype_unuse(*new_t); -// *new_t = MPI_DATATYPE_NULL; - xbt_dict_cursor_free(&cursor); + for(auto it = datatype->attributes()->begin(); it != datatype->attributes()->end(); it++){ + smpi_key_elem elem = keyvals_.at((*it).first); + + if (elem != nullptr && elem->copy_fn.type_copy_fn != MPI_NULL_COPY_FN) { + *ret = elem->copy_fn.type_copy_fn(datatype, (*it).first, nullptr, (*it).second, &value_out, &flag); + if (*ret != MPI_SUCCESS) { + break; + } + if (flag){ + elem->refcount++; + attributes()->insert({(*it).first, value_out}); } - if (flag) - xbt_dict_set_ext(attributes_, key, sizeof(int), value_out, nullptr); } } } } Datatype::~Datatype(){ - xbt_assert(in_use_ >= 0); + xbt_assert(refcount_ >= 0); if(flags_ & DT_FLAG_PREDEFINED) return; //if still used, mark for deletion - if(in_use_!=0){ + if(refcount_!=0){ flags_ |=DT_FLAG_DESTROYED; return; } - if(attributes_ !=nullptr){ - xbt_dict_cursor_t cursor = nullptr; - char* key; - void * value; - int flag; - xbt_dict_foreach(attributes_, cursor, key, value){ - smpi_type_key_elem elem = - static_cast(xbt_dict_get_or_null_ext(smpi_type_keyvals, key, sizeof(int))); - if(elem!=nullptr && elem->delete_fn!=nullptr) - elem->delete_fn(this,*key, value, &flag); - } - xbt_dict_free(&attributes_); - } + cleanup_attr(); xbt_free(name_); } -void Datatype::use(){ +void Datatype::ref(){ - in_use_++; + refcount_++; #if HAVE_MC if(MC_is_active()) - MC_ignore(&(in_use_), sizeof(in_use_)); + MC_ignore(&(refcount_), sizeof(refcount_)); #endif } -void Datatype::unuse() +void Datatype::unref(MPI_Datatype datatype) { - if (in_use_ > 0) - in_use_--; + if (datatype->refcount_ > 0) + datatype->refcount_--; - if (in_use_ == 0) - this->~Datatype(); + if (datatype->refcount_ == 0 && !(datatype->flags_ & DT_FLAG_PREDEFINED)) + delete datatype; #if HAVE_MC if(MC_is_active()) - MC_ignore(&(in_use_), sizeof(in_use_)); + MC_ignore(&(datatype->refcount_), sizeof(datatype->refcount_)); #endif } @@ -226,6 +208,10 @@ int Datatype::flags(){ return flags_; } +int Datatype::refcount(){ + return refcount_; +} + void Datatype::addflag(int flag){ flags_ &= flag; } @@ -264,96 +250,6 @@ void Datatype::set_name(char* name){ name_ = xbt_strdup(name); } -int Datatype::attr_delete(int keyval){ - smpi_type_key_elem elem = - static_cast(xbt_dict_get_or_null_ext(smpi_type_keyvals, reinterpret_cast(&keyval), sizeof(int))); - if(elem==nullptr) - return MPI_ERR_ARG; - if(elem->delete_fn!=MPI_NULL_DELETE_FN){ - void * value = nullptr; - int flag; - if(smpi_type_attr_get(this, keyval, &value, &flag)==MPI_SUCCESS){ - int ret = elem->delete_fn(this, keyval, value, &flag); - if(ret!=MPI_SUCCESS) - return ret; - } - } - if(attributes_==nullptr) - return MPI_ERR_ARG; - - xbt_dict_remove_ext(attributes_, reinterpret_cast(&keyval), sizeof(int)); - return MPI_SUCCESS; -} - - -int Datatype::attr_get(int keyval, void* attr_value, int* flag){ - smpi_type_key_elem elem = - static_cast(xbt_dict_get_or_null_ext(smpi_type_keyvals, reinterpret_cast(&keyval), sizeof(int))); - if(elem==nullptr) - return MPI_ERR_ARG; - if(attributes_==nullptr){ - *flag=0; - return MPI_SUCCESS; - } - try { - *static_cast(attr_value) = xbt_dict_get_ext(attributes_, reinterpret_cast(&keyval), sizeof(int)); - *flag=1; - } - catch (xbt_ex& ex) { - *flag=0; - } - return MPI_SUCCESS; -} - -int Datatype::attr_put(int keyval, void* attr_value){ - if(smpi_type_keyvals==nullptr) - smpi_type_keyvals = xbt_dict_new_homogeneous(nullptr); - smpi_type_key_elem elem = - static_cast(xbt_dict_get_or_null_ext(smpi_type_keyvals, reinterpret_cast(&keyval), sizeof(int))); - if(elem==nullptr) - return MPI_ERR_ARG; - int flag; - void* value = nullptr; - smpi_type_attr_get(this, keyval, &value, &flag); - if(flag!=0 && elem->delete_fn!=MPI_NULL_DELETE_FN){ - int ret = elem->delete_fn(this, keyval, value, &flag); - if(ret!=MPI_SUCCESS) - return ret; - } - if(attributes_==nullptr) - attributes_ = xbt_dict_new_homogeneous(nullptr); - - xbt_dict_set_ext(attributes_, reinterpret_cast(&keyval), sizeof(int), attr_value, nullptr); - return MPI_SUCCESS; -} - -int Datatype::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==nullptr) - smpi_type_keyvals = xbt_dict_new_homogeneous(nullptr); - - 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,reinterpret_cast(keyval), sizeof(int),reinterpret_cast(value), nullptr); - type_keyval_id++; - return MPI_SUCCESS; -} - -int Datatype::keyval_free(int* keyval){ - smpi_type_key_elem elem = - static_cast(xbt_dict_get_or_null_ext(smpi_type_keyvals, reinterpret_cast(keyval), sizeof(int))); - if(elem==0){ - return MPI_ERR_ARG; - } - xbt_dict_remove_ext(smpi_type_keyvals, reinterpret_cast(keyval), sizeof(int)); - xbt_free(elem); - return MPI_SUCCESS; -} - - int Datatype::pack(void* inbuf, int incount, void* outbuf, int outcount, int* position,MPI_Comm comm){ if (outcount - *position < incount*static_cast(size_)) return MPI_ERR_BUFFER; @@ -363,7 +259,7 @@ int Datatype::pack(void* inbuf, int incount, void* outbuf, int outcount, int* po } int Datatype::unpack(void* inbuf, int insize, int* position, void* outbuf, int outcount,MPI_Comm comm){ - if (outcount*(int)size_> insize) + if (outcount*static_cast(size_)> insize) return MPI_ERR_BUFFER; Datatype::copy(static_cast(inbuf) + *position, insize, MPI_CHAR, outbuf, outcount, this); *position += outcount * size_; @@ -373,62 +269,245 @@ int Datatype::unpack(void* inbuf, int insize, int* position, void* outbuf, int o int Datatype::copy(void *sendbuf, int sendcount, MPI_Datatype sendtype, void *recvbuf, int recvcount, MPI_Datatype recvtype){ -// int count; - if(smpi_privatize_global_variables){ - smpi_switch_data_segment(smpi_process_index()); + int count; + +// FIXME Handle the case of a partial shared malloc. +#if 0 + if(smpi_is_shared(sendbuf)){ + XBT_DEBUG("Copy input buf %p is shared. Let's ignore it.", sendbuf); + }else if(smpi_is_shared(recvbuf)){ + XBT_DEBUG("Copy output buf %p is shared. Let's ignore it.", recvbuf); + } +#endif + + if(smpi_privatize_global_variables == SMPI_PRIVATIZE_MMAP){ + smpi_switch_data_segment(smpi_process()->index()); } /* First check if we really have something to do */ if (recvcount > 0 && recvbuf != sendbuf) { - /* FIXME: treat packed cases */ sendcount *= sendtype->size(); recvcount *= recvtype->size(); -// count = sendcount < recvcount ? sendcount : recvcount; - -// if(sendtype->sizeof_substruct == 0 && recvtype->sizeof_substruct == 0) { -// if(!smpi_process_get_replaying()) -// memcpy(recvbuf, sendbuf, count); -// } -// else if (sendtype->sizeof_substruct == 0) -// { -// s_smpi_subtype_t *subtype = static_cast(recvtype->substruct); -// subtype->unserialize( sendbuf, recvbuf, recvcount/smpi_datatype_size(recvtype), subtype, MPI_REPLACE); -// } -// else if (recvtype->sizeof_substruct == 0) -// { -// s_smpi_subtype_t *subtype = static_cast(sendtype->substruct); -// subtype->serialize(sendbuf, recvbuf, sendcount/smpi_datatype_size(sendtype), subtype); -// }else{ -// s_smpi_subtype_t *subtype = static_cast(sendtype->substruct); - -// void * buf_tmp = xbt_malloc(count); - -// subtype->serialize( sendbuf, buf_tmp,count/smpi_datatype_size(sendtype), subtype); -// subtype = static_cast(recvtype->substruct); -// subtype->unserialize( buf_tmp, recvbuf,count/smpi_datatype_size(recvtype), subtype, MPI_REPLACE); - -// xbt_free(buf_tmp); -// } + count = sendcount < recvcount ? sendcount : recvcount; + + if(!(sendtype->flags() & DT_FLAG_DERIVED) && !(recvtype->flags() & DT_FLAG_DERIVED)) { + if(!smpi_process()->replaying()) + memcpy(recvbuf, sendbuf, count); + } + else if (!(sendtype->flags() & DT_FLAG_DERIVED)) + { + recvtype->unserialize( sendbuf, recvbuf, recvcount/recvtype->size(), MPI_REPLACE); + } + else if (!(recvtype->flags() & DT_FLAG_DERIVED)) + { + sendtype->serialize(sendbuf, recvbuf, sendcount/sendtype->size()); + }else{ + + void * buf_tmp = xbt_malloc(count); + + sendtype->serialize( sendbuf, buf_tmp,count/sendtype->size()); + recvtype->unserialize( buf_tmp, recvbuf,count/recvtype->size(), MPI_REPLACE); + + xbt_free(buf_tmp); + } } return sendcount > recvcount ? MPI_ERR_TRUNCATE : MPI_SUCCESS; } //Default serialization method : memcpy. -void Datatype::serialize( void* noncontiguous, void *contiguous, int count, void *type){ - char* contiguous_char = static_cast(contiguous); - char* noncontiguous_char = static_cast(noncontiguous)+lb_; - memcpy(contiguous_char, noncontiguous_char, count*size_); +void Datatype::serialize( void* noncontiguous_buf, void *contiguous_buf, int count){ + char* contiguous_buf_char = static_cast(contiguous_buf); + char* noncontiguous_buf_char = static_cast(noncontiguous_buf)+lb_; + memcpy(contiguous_buf_char, noncontiguous_buf_char, count*size_); } -void Datatype::unserialize( void* contiguous, void *noncontiguous, int count, void *type, MPI_Op op){ - char* contiguous_char = static_cast(contiguous); - char* noncontiguous_char = static_cast(noncontiguous)+lb_; +void Datatype::unserialize( void* contiguous_buf, void *noncontiguous_buf, int count, MPI_Op op){ + char* contiguous_buf_char = static_cast(contiguous_buf); + char* noncontiguous_buf_char = static_cast(noncontiguous_buf)+lb_; int n=count; if(op!=MPI_OP_NULL) - op->apply( contiguous_char, noncontiguous_char, &n, this); + op->apply( contiguous_buf_char, noncontiguous_buf_char, &n, this); +} + +int Datatype::create_contiguous(int count, MPI_Datatype old_type, MPI_Aint lb, MPI_Datatype* new_type){ + if(old_type->flags_ & DT_FLAG_DERIVED){ + //handle this case as a hvector with stride equals to the extent of the datatype + return create_hvector(count, 1, old_type->get_extent(), old_type, new_type); + } + if(count>0) + *new_type = new Type_Contiguous(count * old_type->size(), lb, lb + count * old_type->size(), + DT_FLAG_DERIVED, count, old_type); + else + *new_type = new Datatype(count * old_type->size(), lb, lb + count * old_type->size(),0); + return MPI_SUCCESS; +} + +int Datatype::create_vector(int count, int block_length, int stride, MPI_Datatype old_type, MPI_Datatype* new_type) +{ + int retval; + if (block_length<0) + return MPI_ERR_ARG; + MPI_Aint lb = 0; + MPI_Aint ub = 0; + if(count>0){ + lb=old_type->lb(); + ub=((count-1)*stride+block_length-1)*old_type->get_extent()+old_type->ub(); + } + if(old_type->flags() & DT_FLAG_DERIVED || stride != block_length){ + *new_type = new Type_Vector(count * (block_length) * old_type->size(), lb, ub, + DT_FLAG_DERIVED, count, block_length, stride, old_type); + retval=MPI_SUCCESS; + }else{ + /* in this situation the data are contiguous thus it's not required to serialize and unserialize it*/ + *new_type = new Datatype(count * block_length * old_type->size(), 0, ((count -1) * stride + block_length)* + old_type->size(), DT_FLAG_CONTIGUOUS); + retval=MPI_SUCCESS; + } + return retval; +} + + +int Datatype::create_hvector(int count, int block_length, MPI_Aint stride, MPI_Datatype old_type, MPI_Datatype* new_type) +{ + int retval; + if (block_length<0) + return MPI_ERR_ARG; + MPI_Aint lb = 0; + MPI_Aint ub = 0; + if(count>0){ + lb=old_type->lb(); + ub=((count-1)*stride)+(block_length-1)*old_type->get_extent()+old_type->ub(); + } + if(old_type->flags() & DT_FLAG_DERIVED || stride != block_length*old_type->get_extent()){ + *new_type = new Type_Hvector(count * (block_length) * old_type->size(), lb, ub, + DT_FLAG_DERIVED, count, block_length, stride, old_type); + retval=MPI_SUCCESS; + }else{ + /* in this situation the data are contiguous thus it's not required to serialize and unserialize it*/ + *new_type = new Datatype(count * block_length * old_type->size(), 0, count * block_length * old_type->size(), DT_FLAG_CONTIGUOUS); + retval=MPI_SUCCESS; + } + return retval; +} + +int Datatype::create_indexed(int count, int* block_lengths, int* indices, MPI_Datatype old_type, MPI_Datatype* new_type){ + int size = 0; + bool contiguous=true; + MPI_Aint lb = 0; + MPI_Aint ub = 0; + if(count>0){ + lb=indices[0]*old_type->get_extent(); + ub=indices[0]*old_type->get_extent() + block_lengths[0]*old_type->ub(); + } + + for (int i = 0; i < count; i++) { + if (block_lengths[i] < 0) + return MPI_ERR_ARG; + size += block_lengths[i]; + + if(indices[i]*old_type->get_extent()+old_type->lb()get_extent()+old_type->lb(); + if(indices[i]*old_type->get_extent()+block_lengths[i]*old_type->ub()>ub) + ub = indices[i]*old_type->get_extent()+block_lengths[i]*old_type->ub(); + + if ( (i< count -1) && (indices[i]+block_lengths[i] != indices[i+1]) ) + contiguous=false; + } + if(old_type->flags_ & DT_FLAG_DERIVED) + contiguous=false; + + if(!contiguous){ + *new_type = new Type_Indexed(size * old_type->size(),lb,ub, + DT_FLAG_DERIVED|DT_FLAG_DATA, count, block_lengths, indices, old_type); + }else{ + Datatype::create_contiguous(size, old_type, lb, new_type); + } + return MPI_SUCCESS; +} + +int Datatype::create_hindexed(int count, int* block_lengths, MPI_Aint* indices, MPI_Datatype old_type, MPI_Datatype* new_type){ + int size = 0; + bool contiguous=true; + MPI_Aint lb = 0; + MPI_Aint ub = 0; + if(count>0){ + lb=indices[0] + old_type->lb(); + ub=indices[0] + block_lengths[0]*old_type->ub(); + } + for (int i = 0; i < count; i++) { + if (block_lengths[i] < 0) + return MPI_ERR_ARG; + size += block_lengths[i]; + + if(indices[i]+old_type->lb()lb(); + if(indices[i]+block_lengths[i]*old_type->ub()>ub) + ub = indices[i]+block_lengths[i]*old_type->ub(); + + if ( (i< count -1) && (indices[i]+block_lengths[i]*(static_cast(old_type->size())) != indices[i+1]) ) + contiguous=false; + } + if (old_type->flags_ & DT_FLAG_DERIVED || lb!=0) + contiguous=false; + + if(!contiguous){ + *new_type = new Type_Hindexed(size * old_type->size(),lb,ub, + DT_FLAG_DERIVED|DT_FLAG_DATA, count, block_lengths, indices, old_type); + }else{ + Datatype::create_contiguous(size, old_type, lb, new_type); + } + return MPI_SUCCESS; +} + +int Datatype::create_struct(int count, int* block_lengths, MPI_Aint* indices, MPI_Datatype* old_types, MPI_Datatype* new_type){ + size_t size = 0; + bool contiguous=true; + size = 0; + MPI_Aint lb = 0; + MPI_Aint ub = 0; + if(count>0){ + lb=indices[0] + old_types[0]->lb(); + ub=indices[0] + block_lengths[0]*old_types[0]->ub(); + } + bool forced_lb=false; + bool forced_ub=false; + for (int i = 0; i < count; i++) { + if (block_lengths[i]<0) + return MPI_ERR_ARG; + if (old_types[i]->flags_ & DT_FLAG_DERIVED) + contiguous=false; + + size += block_lengths[i]*old_types[i]->size(); + if (old_types[i]==MPI_LB){ + lb=indices[i]; + forced_lb=true; + } + if (old_types[i]==MPI_UB){ + ub=indices[i]; + forced_ub=true; + } + + if(!forced_lb && indices[i]+old_types[i]->lb()ub()>ub) + ub = indices[i]+block_lengths[i]*old_types[i]->ub(); + + if ( (i< count -1) && (indices[i]+block_lengths[i]*static_cast(old_types[i]->size()) != indices[i+1]) ) + contiguous=false; + } + if(!contiguous){ + *new_type = new Type_Struct(size, lb,ub, DT_FLAG_DERIVED|DT_FLAG_DATA, + count, block_lengths, indices, old_types); + }else{ + Datatype::create_contiguous(size, MPI_CHAR, lb, new_type); + } + return MPI_SUCCESS; } +Datatype* Datatype::f2c(int id){ + return static_cast(F2C::f2c(id)); +} }