diff --git a/ompi/datatype/Makefile.am b/ompi/datatype/Makefile.am index b14c05a5a7..643e8147fd 100644 --- a/ompi/datatype/Makefile.am +++ b/ompi/datatype/Makefile.am @@ -13,6 +13,8 @@ # Copyright (c) 2007-2013 Los Alamos National Security, LLC. All rights # reserved. # Copyright (c) 2010 Cisco Systems, Inc. All rights reserved. +# Copyright (c) 2016 Research Organization for Information Science +# and Technology (RIST). All rights reserved. # $COPYRIGHT$ # # Additional copyrights may follow @@ -37,6 +39,7 @@ libdatatype_la_SOURCES = \ ompi_datatype_create_vector.c \ ompi_datatype_create_darray.c \ ompi_datatype_create_subarray.c \ + ompi_datatype_external.c \ ompi_datatype_external32.c \ ompi_datatype_match_size.c \ ompi_datatype_module.c \ diff --git a/ompi/datatype/ompi_datatype.h b/ompi/datatype/ompi_datatype.h index 17e1632e07..ff6a1b0b2f 100644 --- a/ompi/datatype/ompi_datatype.h +++ b/ompi/datatype/ompi_datatype.h @@ -7,7 +7,7 @@ * Copyright (c) 2010 Cisco Systems, Inc. All rights reserved. * Copyright (c) 2013 Los Alamos National Security, LLC. All rights * reserved. - * Copyright (c) 2015 Research Organization for Information Science + * Copyright (c) 2015-2016 Research Organization for Information Science * and Technology (RIST). All rights reserved. * $COPYRIGHT$ * @@ -363,5 +363,16 @@ OMPI_DECLSPEC int ompi_datatype_safeguard_pointer_debug_breakpoint( const void* int count ); #endif /* OPAL_ENABLE_DEBUG */ +OMPI_DECLSPEC int ompi_datatype_pack_external( const char datarep[], const void *inbuf, int incount, + ompi_datatype_t *datatype, void *outbuf, + MPI_Aint outsize, MPI_Aint *position); + +OMPI_DECLSPEC int ompi_datatype_unpack_external( const char datarep[], const void *inbuf, MPI_Aint insize, + MPI_Aint *position, void *outbuf, int outcount, + ompi_datatype_t *datatype); + +OMPI_DECLSPEC int ompi_datatype_pack_external_size( const char datarep[], int incount, + ompi_datatype_t *datatype, MPI_Aint *size); + END_C_DECLS #endif /* OMPI_DATATYPE_H_HAS_BEEN_INCLUDED */ diff --git a/ompi/datatype/ompi_datatype_external.c b/ompi/datatype/ompi_datatype_external.c new file mode 100644 index 0000000000..d47531ef29 --- /dev/null +++ b/ompi/datatype/ompi_datatype_external.c @@ -0,0 +1,135 @@ +/* -*- Mode: C; c-basic-offset:4 ; -*- */ +/* + * Copyright (c) 2004-2007 The Trustees of Indiana University and Indiana + * University Research and Technology + * Corporation. All rights reserved. + * Copyright (c) 2004-2016 The University of Tennessee and The University + * of Tennessee Research Foundation. All rights + * reserved. + * Copyright (c) 2004-2008 High Performance Computing Center Stuttgart, + * University of Stuttgart. All rights reserved. + * Copyright (c) 2004-2005 The Regents of the University of California. + * All rights reserved. + * Copyright (c) 2006 Cisco Systems, Inc. All rights reserved. + * Copyright (c) 2013 Los Alamos National Security, LLC. All rights + * reserved. + * Copyright (c) 2015-2016 Research Organization for Information Science + * and Technology (RIST). All rights reserved. + * $COPYRIGHT$ + * + * Additional copyrights may follow + * + * $HEADER$ + */ + +#include "ompi_config.h" +#include + +#include "ompi/runtime/params.h" +#include "ompi/communicator/communicator.h" +#include "ompi/datatype/ompi_datatype.h" +#include "opal/datatype/opal_convertor.h" + +int ompi_datatype_pack_external(const char datarep[], const void *inbuf, int incount, + ompi_datatype_t *datatype, void *outbuf, + MPI_Aint outsize, MPI_Aint *position) +{ + int rc = MPI_SUCCESS; + opal_convertor_t local_convertor; + struct iovec invec; + unsigned int iov_count; + size_t size; + + OBJ_CONSTRUCT(&local_convertor, opal_convertor_t); + + /* The resulting convertor will be set to the position zero. We have to use + * CONVERTOR_SEND_CONVERSION in order to force the convertor to do anything + * more than just packing the data. + */ + opal_convertor_copy_and_prepare_for_send( ompi_mpi_external32_convertor, + &(datatype->super), incount, (void *) inbuf, + CONVERTOR_SEND_CONVERSION, + &local_convertor ); + + /* Check for truncation */ + opal_convertor_get_packed_size( &local_convertor, &size ); + if( (*position + size) > (size_t)outsize ) { /* we can cast as we already checked for < 0 */ + OBJ_DESTRUCT( &local_convertor ); + return MPI_ERR_TRUNCATE; + } + + /* Prepare the iovec with all informations */ + invec.iov_base = (char*) outbuf + (*position); + invec.iov_len = size; + + /* Do the actual packing */ + iov_count = 1; + rc = opal_convertor_pack( &local_convertor, &invec, &iov_count, &size ); + *position += size; + OBJ_DESTRUCT( &local_convertor ); + + /* All done. Note that the convertor returns 1 upon success, not + OMPI_SUCCESS. */ + return (rc == 1) ? OMPI_SUCCESS : MPI_ERR_UNKNOWN; +} + +int ompi_datatype_unpack_external (const char datarep[], const void *inbuf, MPI_Aint insize, + MPI_Aint *position, void *outbuf, int outcount, + ompi_datatype_t *datatype) +{ + int rc = MPI_SUCCESS; + opal_convertor_t local_convertor; + struct iovec outvec; + unsigned int iov_count; + size_t size; + + OBJ_CONSTRUCT(&local_convertor, opal_convertor_t); + + /* the resulting convertor will be set to the position ZERO */ + opal_convertor_copy_and_prepare_for_recv( ompi_mpi_external32_convertor, + &(datatype->super), outcount, outbuf, + 0, + &local_convertor ); + + /* Check for truncation */ + opal_convertor_get_packed_size( &local_convertor, &size ); + if( (*position + size) > (unsigned int)insize ) { + OBJ_DESTRUCT( &local_convertor ); + return MPI_ERR_TRUNCATE; + } + + /* Prepare the iovec with all informations */ + outvec.iov_base = (char*) inbuf + (*position); + outvec.iov_len = size; + + /* Do the actual unpacking */ + iov_count = 1; + rc = opal_convertor_unpack( &local_convertor, &outvec, &iov_count, &size ); + *position += size; + OBJ_DESTRUCT( &local_convertor ); + + /* All done. Note that the convertor returns 1 upon success, not + OMPI_SUCCESS. */ + return (rc == 1) ? OMPI_SUCCESS : MPI_ERR_UNKNOWN; +} + +int ompi_datatype_pack_external_size(const char datarep[], int incount, + ompi_datatype_t *datatype, MPI_Aint *size) +{ + opal_convertor_t local_convertor; + size_t length; + + OBJ_CONSTRUCT(&local_convertor, opal_convertor_t); + + /* the resulting convertor will be set to the position ZERO */ + opal_convertor_copy_and_prepare_for_recv( ompi_mpi_external32_convertor, + &(datatype->super), incount, NULL, + CONVERTOR_SEND_CONVERSION, + &local_convertor ); + + opal_convertor_get_unpacked_size( &local_convertor, &length ); + *size = (MPI_Aint)length; + OBJ_DESTRUCT( &local_convertor ); + + return OMPI_SUCCESS; +} diff --git a/ompi/mpi/c/pack.c b/ompi/mpi/c/pack.c index 91c5cf0014..555f5212f0 100644 --- a/ompi/mpi/c/pack.c +++ b/ompi/mpi/c/pack.c @@ -3,7 +3,7 @@ * Copyright (c) 2004-2007 The Trustees of Indiana University and Indiana * University Research and Technology * Corporation. All rights reserved. - * Copyright (c) 2004-2005 The University of Tennessee and The University + * Copyright (c) 2004-2016 The University of Tennessee and The University * of Tennessee Research Foundation. All rights * reserved. * Copyright (c) 2004-2008 High Performance Computing Center Stuttgart, @@ -45,7 +45,7 @@ static const char FUNC_NAME[] = "MPI_Pack"; int MPI_Pack(const void *inbuf, int incount, MPI_Datatype datatype, void *outbuf, int outsize, int *position, MPI_Comm comm) { - int rc; + int rc = MPI_SUCCESS; opal_convertor_t local_convertor; struct iovec invec; unsigned int iov_count; @@ -67,9 +67,11 @@ int MPI_Pack(const void *inbuf, int incount, MPI_Datatype datatype, return OMPI_ERRHANDLER_INVOKE(comm, MPI_ERR_COUNT, FUNC_NAME); } else if (outsize < 0) { return OMPI_ERRHANDLER_INVOKE(comm, MPI_ERR_ARG, FUNC_NAME); - } else if (MPI_DATATYPE_NULL == datatype || NULL == datatype) { - return OMPI_ERRHANDLER_INVOKE(comm, MPI_ERR_TYPE, FUNC_NAME); } + OMPI_CHECK_DATATYPE_FOR_SEND(rc, datatype, incount); + OMPI_ERRHANDLER_CHECK(rc, comm, rc, FUNC_NAME); + OMPI_CHECK_USER_BUFFER(rc, inbuf, datatype, incount); + OMPI_ERRHANDLER_CHECK(rc, comm, rc, FUNC_NAME); } OPAL_CR_ENTER_LIBRARY(); diff --git a/ompi/mpi/c/pack_external.c b/ompi/mpi/c/pack_external.c index fea4bd3155..4ccffbc2b9 100644 --- a/ompi/mpi/c/pack_external.c +++ b/ompi/mpi/c/pack_external.c @@ -3,7 +3,7 @@ * Copyright (c) 2004-2007 The Trustees of Indiana University and Indiana * University Research and Technology * Corporation. All rights reserved. - * Copyright (c) 2004-2005 The University of Tennessee and The University + * Copyright (c) 2004-2016 The University of Tennessee and The University * of Tennessee Research Foundation. All rights * reserved. * Copyright (c) 2004-2008 High Performance Computing Center Stuttgart, @@ -46,11 +46,7 @@ int MPI_Pack_external(const char datarep[], const void *inbuf, int incount, MPI_Datatype datatype, void *outbuf, MPI_Aint outsize, MPI_Aint *position) { - int rc; - opal_convertor_t local_convertor; - struct iovec invec; - unsigned int iov_count; - size_t size; + int rc = MPI_SUCCESS; MEMCHECKER( memchecker_datatype(datatype); @@ -65,46 +61,21 @@ int MPI_Pack_external(const char datarep[], const void *inbuf, int incount, return OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD, MPI_ERR_COUNT, FUNC_NAME); } else if (outsize < 0) { return OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD, MPI_ERR_ARG, FUNC_NAME); - } else if (MPI_DATATYPE_NULL == datatype || NULL == datatype) { - return OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD, MPI_ERR_TYPE, FUNC_NAME); } + OMPI_CHECK_DATATYPE_FOR_SEND(rc, datatype, incount); + OMPI_ERRHANDLER_CHECK(rc, MPI_COMM_WORLD, rc, FUNC_NAME); + OMPI_CHECK_USER_BUFFER(rc, inbuf, datatype, incount); + OMPI_ERRHANDLER_CHECK(rc, MPI_COMM_WORLD, rc, FUNC_NAME); } OPAL_CR_ENTER_LIBRARY(); - OBJ_CONSTRUCT(&local_convertor, opal_convertor_t); - - /* The resulting convertor will be set to the position zero. We have to use - * CONVERTOR_SEND_CONVERSION in order to force the convertor to do anything - * more than just packing the data. - */ - opal_convertor_copy_and_prepare_for_send( ompi_mpi_external32_convertor, - &(datatype->super), incount, (void *) inbuf, - CONVERTOR_SEND_CONVERSION, - &local_convertor ); - - /* Check for truncation */ - opal_convertor_get_packed_size( &local_convertor, &size ); - if( (*position + size) > (size_t)outsize ) { /* we can cast as we already checked for < 0 */ - OBJ_DESTRUCT( &local_convertor ); - OPAL_CR_EXIT_LIBRARY(); - return OMPI_ERRHANDLER_INVOKE( MPI_COMM_WORLD, MPI_ERR_TRUNCATE, FUNC_NAME ); - } - - /* Prepare the iovec with all informations */ - invec.iov_base = (char*) outbuf + (*position); - invec.iov_len = size; - - /* Do the actual packing */ - iov_count = 1; - rc = opal_convertor_pack( &local_convertor, &invec, &iov_count, &size ); - *position += size; - OBJ_DESTRUCT( &local_convertor ); + rc = ompi_datatype_pack_external(datarep, inbuf, incount, + datatype, outbuf, + outsize, position); OPAL_CR_EXIT_LIBRARY(); - /* All done. Note that the convertor returns 1 upon success, not - OMPI_SUCCESS. */ - OMPI_ERRHANDLER_RETURN((rc == 1) ? OMPI_SUCCESS : OMPI_ERROR, - MPI_COMM_WORLD, MPI_ERR_UNKNOWN, FUNC_NAME); + OMPI_ERRHANDLER_RETURN((OMPI_SUCCESS == rc) ? OMPI_SUCCESS : OMPI_ERROR, + MPI_COMM_WORLD, rc, FUNC_NAME); } diff --git a/ompi/mpi/c/pack_external_size.c b/ompi/mpi/c/pack_external_size.c index 113ebef294..45044d00e5 100644 --- a/ompi/mpi/c/pack_external_size.c +++ b/ompi/mpi/c/pack_external_size.c @@ -13,7 +13,7 @@ * Copyright (c) 2006 Cisco Systems, Inc. All rights reserved. * Copyright (c) 2013 Los Alamos National Security, LLC. All rights * reserved. - * Copyright (c) 2015 Research Organization for Information Science + * Copyright (c) 2015-2016 Research Organization for Information Science * and Technology (RIST). All rights reserved. * $COPYRIGHT$ * @@ -45,8 +45,7 @@ static const char FUNC_NAME[] = "MPI_Pack_external_size"; int MPI_Pack_external_size(const char datarep[], int incount, MPI_Datatype datatype, MPI_Aint *size) { - opal_convertor_t local_convertor; - size_t length; + int rc = MPI_SUCCESS; MEMCHECKER( memchecker_datatype(datatype); @@ -63,18 +62,10 @@ int MPI_Pack_external_size(const char datarep[], int incount, OPAL_CR_ENTER_LIBRARY(); - OBJ_CONSTRUCT(&local_convertor, opal_convertor_t); - - /* the resulting convertor will be set to the position ZERO */ - opal_convertor_copy_and_prepare_for_recv( ompi_mpi_external32_convertor, - &(datatype->super), incount, NULL, - CONVERTOR_SEND_CONVERSION, - &local_convertor ); - - opal_convertor_get_unpacked_size( &local_convertor, &length ); - *size = (MPI_Aint)length; - OBJ_DESTRUCT( &local_convertor ); - + rc = ompi_datatype_pack_external_size(datarep, incount, + datatype, size); OPAL_CR_EXIT_LIBRARY(); - return OMPI_SUCCESS; + + OMPI_ERRHANDLER_RETURN((OMPI_SUCCESS == rc) ? OMPI_SUCCESS : OMPI_ERROR, + MPI_COMM_WORLD, rc, FUNC_NAME); } diff --git a/ompi/mpi/c/unpack.c b/ompi/mpi/c/unpack.c index 6e345167a8..253bec8db9 100644 --- a/ompi/mpi/c/unpack.c +++ b/ompi/mpi/c/unpack.c @@ -2,7 +2,7 @@ * Copyright (c) 2004-2007 The Trustees of Indiana University and Indiana * University Research and Technology * Corporation. All rights reserved. - * Copyright (c) 2004-2005 The University of Tennessee and The University + * Copyright (c) 2004-2016 The University of Tennessee and The University * of Tennessee Research Foundation. All rights * reserved. * Copyright (c) 2004-2008 High Performance Computing Center Stuttgart, @@ -43,7 +43,7 @@ int MPI_Unpack(const void *inbuf, int insize, int *position, void *outbuf, int outcount, MPI_Datatype datatype, MPI_Comm comm) { - int rc = 1; + int rc = MPI_SUCCESS; opal_convertor_t local_convertor; struct iovec outvec; unsigned int iov_count; @@ -70,9 +70,10 @@ int MPI_Unpack(const void *inbuf, int insize, int *position, return OMPI_ERRHANDLER_INVOKE(comm, MPI_ERR_COUNT, FUNC_NAME); } - if (MPI_DATATYPE_NULL == datatype || NULL == datatype) { - return OMPI_ERRHANDLER_INVOKE(comm, MPI_ERR_TYPE, FUNC_NAME); - } + OMPI_CHECK_DATATYPE_FOR_RECV(rc, datatype, outcount); + OMPI_ERRHANDLER_CHECK(rc, comm, rc, FUNC_NAME); + OMPI_CHECK_USER_BUFFER(rc, outbuf, datatype, outcount); + OMPI_ERRHANDLER_CHECK(rc, comm, rc, FUNC_NAME); } OPAL_CR_ENTER_LIBRARY(); @@ -103,12 +104,11 @@ int MPI_Unpack(const void *inbuf, int insize, int *position, /* All done. Note that the convertor returns 1 upon success, not OMPI_SUCCESS. */ - + rc = (1 == rc) ? OMPI_SUCCESS : OMPI_ERROR; } OPAL_CR_EXIT_LIBRARY(); OMPI_ERRHANDLER_RETURN((rc == 1) ? OMPI_SUCCESS : OMPI_ERROR, comm, MPI_ERR_UNKNOWN, FUNC_NAME); - } diff --git a/ompi/mpi/c/unpack_external.c b/ompi/mpi/c/unpack_external.c index df3879d4e2..2d3372b517 100644 --- a/ompi/mpi/c/unpack_external.c +++ b/ompi/mpi/c/unpack_external.c @@ -3,7 +3,7 @@ * Copyright (c) 2004-2007 The Trustees of Indiana University and Indiana * University Research and Technology * Corporation. All rights reserved. - * Copyright (c) 2004-2005 The University of Tennessee and The University + * Copyright (c) 2004-2016 The University of Tennessee and The University * of Tennessee Research Foundation. All rights * reserved. * Copyright (c) 2004-2008 High Performance Computing Center Stuttgart, @@ -45,11 +45,7 @@ int MPI_Unpack_external (const char datarep[], const void *inbuf, MPI_Aint insiz MPI_Aint *position, void *outbuf, int outcount, MPI_Datatype datatype) { - int rc; - opal_convertor_t local_convertor; - struct iovec outvec; - unsigned int iov_count; - size_t size; + int rc = MPI_SUCCESS; MEMCHECKER( memchecker_datatype(datatype); @@ -62,41 +58,21 @@ int MPI_Unpack_external (const char datarep[], const void *inbuf, MPI_Aint insiz return OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD, MPI_ERR_ARG, FUNC_NAME); } else if (outcount < 0) { return OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD, MPI_ERR_COUNT, FUNC_NAME); - } else if (MPI_DATATYPE_NULL == datatype || NULL == datatype) { - return OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD, MPI_ERR_TYPE, FUNC_NAME); } + OMPI_CHECK_DATATYPE_FOR_RECV(rc, datatype, outcount); + OMPI_ERRHANDLER_CHECK(rc, MPI_COMM_WORLD, rc, FUNC_NAME); + OMPI_CHECK_USER_BUFFER(rc, outbuf, datatype, outcount); + OMPI_ERRHANDLER_CHECK(rc, MPI_COMM_WORLD, rc, FUNC_NAME); } OPAL_CR_ENTER_LIBRARY(); - OBJ_CONSTRUCT(&local_convertor, opal_convertor_t); - - /* the resulting convertor will be set to the position ZERO */ - opal_convertor_copy_and_prepare_for_recv( ompi_mpi_external32_convertor, - &(datatype->super), outcount, outbuf, 0, &local_convertor ); - - /* Check for truncation */ - opal_convertor_get_packed_size( &local_convertor, &size ); - if( (*position + size) > (unsigned int)insize ) { - OBJ_DESTRUCT( &local_convertor ); - OPAL_CR_EXIT_LIBRARY(); - return OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD, MPI_ERR_TRUNCATE, FUNC_NAME); - } - - /* Prepare the iovec with all informations */ - outvec.iov_base = (char*) inbuf + (*position); - outvec.iov_len = size; - - /* Do the actual unpacking */ - iov_count = 1; - rc = opal_convertor_unpack( &local_convertor, &outvec, &iov_count, &size ); - *position += size; - OBJ_DESTRUCT( &local_convertor ); + rc = ompi_datatype_unpack_external(datarep, inbuf, insize, + position, outbuf, outcount, + datatype); OPAL_CR_EXIT_LIBRARY(); - /* All done. Note that the convertor returns 1 upon success, not - OMPI_SUCCESS. */ - OMPI_ERRHANDLER_RETURN((rc == 1) ? OMPI_SUCCESS : OMPI_ERROR, - MPI_COMM_WORLD, MPI_ERR_UNKNOWN, FUNC_NAME); + OMPI_ERRHANDLER_RETURN((OMPI_SUCCESS == rc) ? OMPI_SUCCESS : OMPI_ERROR, + MPI_COMM_WORLD, rc, FUNC_NAME); } diff --git a/opal/datatype/opal_convertor.c b/opal/datatype/opal_convertor.c index d548128318..46aff82972 100644 --- a/opal/datatype/opal_convertor.c +++ b/opal/datatype/opal_convertor.c @@ -3,7 +3,7 @@ * Copyright (c) 2004-2006 The Trustees of Indiana University and Indiana * University Research and Technology * Corporation. All rights reserved. - * Copyright (c) 2004-2014 The University of Tennessee and The University + * Copyright (c) 2004-2016 The University of Tennessee and The University * of Tennessee Research Foundation. All rights * reserved. * Copyright (c) 2004-2006 High Performance Computing Center Stuttgart, @@ -12,7 +12,7 @@ * All rights reserved. * Copyright (c) 2009 Oak Ridge National Labs. All rights reserved. * Copyright (c) 2011 NVIDIA Corporation. All rights reserved. - * Copyright (c) 2013 Research Organization for Information Science + * Copyright (c) 2013-2016 Research Organization for Information Science * and Technology (RIST). All rights reserved. * $COPYRIGHT$ * @@ -449,16 +449,17 @@ int32_t opal_convertor_set_position_nocheck( opal_convertor_t* convertor, /** - * Compute the remote size. + * Compute the remote size. If necessary remove the homogeneous flag + * and redirect the convertor description toward the non-optimized + * datatype representation. */ -#if OPAL_ENABLE_HETEROGENEOUS_SUPPORT #define OPAL_CONVERTOR_COMPUTE_REMOTE_SIZE(convertor, datatype, bdt_mask) \ { \ if( OPAL_UNLIKELY(0 != (bdt_mask)) ) { \ opal_convertor_master_t* master; \ int i; \ uint32_t mask = datatype->bdt_used; \ - convertor->flags ^= CONVERTOR_HOMOGENEOUS; \ + convertor->flags &= (~CONVERTOR_HOMOGENEOUS); \ master = convertor->master; \ convertor->remote_size = 0; \ for( i = OPAL_DATATYPE_FIRST_TYPE; mask && (i < OPAL_DATATYPE_MAX_PREDEFINED); i++ ) { \ @@ -472,13 +473,6 @@ int32_t opal_convertor_set_position_nocheck( opal_convertor_t* convertor, convertor->use_desc = &(datatype->desc); \ } \ } -#else -#define OPAL_CONVERTOR_COMPUTE_REMOTE_SIZE(convertor, datatype, bdt_mask) \ -{ \ - assert(0 == (bdt_mask)); \ - (void)bdt_mask; /* silence compiler warning */ \ -} -#endif /* OPAL_ENABLE_HETEROGENEOUS_SUPPORT */ /** * This macro will initialize a convertor based on a previously created @@ -511,16 +505,13 @@ int32_t opal_convertor_set_position_nocheck( opal_convertor_t* convertor, convertor->flags |= (CONVERTOR_NO_OP | CONVERTOR_HOMOGENEOUS); \ convertor->pDesc = (opal_datatype_t*)datatype; \ convertor->bConverted = 0; \ - /* By default consider the optimized description */ \ convertor->use_desc = &(datatype->opt_desc); \ \ convertor->remote_size = convertor->local_size; \ if( OPAL_LIKELY(convertor->remoteArch == opal_local_arch) ) { \ - if( (convertor->flags & (CONVERTOR_WITH_CHECKSUM | OPAL_DATATYPE_FLAG_NO_GAPS)) == OPAL_DATATYPE_FLAG_NO_GAPS ) { \ - return OPAL_SUCCESS; \ - } \ - if( ((convertor->flags & (CONVERTOR_WITH_CHECKSUM | OPAL_DATATYPE_FLAG_CONTIGUOUS)) \ - == OPAL_DATATYPE_FLAG_CONTIGUOUS) && (1 == count) ) { \ + if( !(convertor->flags & CONVERTOR_WITH_CHECKSUM) && \ + ((convertor->flags & OPAL_DATATYPE_FLAG_NO_GAPS) || \ + ((convertor->flags & OPAL_DATATYPE_FLAG_CONTIGUOUS) && (1 == count))) ) { \ return OPAL_SUCCESS; \ } \ } \ @@ -532,8 +523,9 @@ int32_t opal_convertor_set_position_nocheck( opal_convertor_t* convertor, /* For predefined datatypes (contiguous) do nothing more */ \ /* if checksum is enabled then always continue */ \ if( ((convertor->flags & (CONVERTOR_WITH_CHECKSUM | OPAL_DATATYPE_FLAG_NO_GAPS)) \ - == OPAL_DATATYPE_FLAG_NO_GAPS) && \ - (convertor->flags & (CONVERTOR_SEND | CONVERTOR_HOMOGENEOUS)) ) { \ + == OPAL_DATATYPE_FLAG_NO_GAPS) && \ + ((convertor->flags & (CONVERTOR_SEND | CONVERTOR_HOMOGENEOUS)) == \ + (CONVERTOR_SEND | CONVERTOR_HOMOGENEOUS)) ) { \ return OPAL_SUCCESS; \ } \ convertor->flags &= ~CONVERTOR_NO_OP; \ @@ -566,26 +558,24 @@ int32_t opal_convertor_prepare_for_recv( opal_convertor_t* convertor, OPAL_CONVERTOR_PREPARE( convertor, datatype, count, pUserBuf ); if( convertor->flags & CONVERTOR_WITH_CHECKSUM ) { -#if OPAL_ENABLE_HETEROGENEOUS_SUPPORT if( !(convertor->flags & CONVERTOR_HOMOGENEOUS) ) { convertor->fAdvance = opal_unpack_general_checksum; - } else -#endif - if( convertor->pDesc->flags & OPAL_DATATYPE_FLAG_CONTIGUOUS ) { - convertor->fAdvance = opal_unpack_homogeneous_contig_checksum; } else { - convertor->fAdvance = opal_generic_simple_unpack_checksum; + if( convertor->pDesc->flags & OPAL_DATATYPE_FLAG_CONTIGUOUS ) { + convertor->fAdvance = opal_unpack_homogeneous_contig_checksum; + } else { + convertor->fAdvance = opal_generic_simple_unpack_checksum; + } } } else { -#if OPAL_ENABLE_HETEROGENEOUS_SUPPORT if( !(convertor->flags & CONVERTOR_HOMOGENEOUS) ) { convertor->fAdvance = opal_unpack_general; - } else -#endif - if( convertor->pDesc->flags & OPAL_DATATYPE_FLAG_CONTIGUOUS ) { - convertor->fAdvance = opal_unpack_homogeneous_contig; } else { - convertor->fAdvance = opal_generic_simple_unpack; + if( convertor->pDesc->flags & OPAL_DATATYPE_FLAG_CONTIGUOUS ) { + convertor->fAdvance = opal_unpack_homogeneous_contig; + } else { + convertor->fAdvance = opal_generic_simple_unpack; + } } } return OPAL_SUCCESS; @@ -605,24 +595,32 @@ int32_t opal_convertor_prepare_for_send( opal_convertor_t* convertor, OPAL_CONVERTOR_PREPARE( convertor, datatype, count, pUserBuf ); if( convertor->flags & CONVERTOR_WITH_CHECKSUM ) { - if( datatype->flags & OPAL_DATATYPE_FLAG_CONTIGUOUS ) { - if( ((datatype->ub - datatype->lb) == (OPAL_PTRDIFF_TYPE)datatype->size) - || (1 >= convertor->count) ) - convertor->fAdvance = opal_pack_homogeneous_contig_checksum; - else - convertor->fAdvance = opal_pack_homogeneous_contig_with_gaps_checksum; + if( CONVERTOR_SEND_CONVERSION == (convertor->flags & (CONVERTOR_SEND_CONVERSION|CONVERTOR_HOMOGENEOUS)) ) { + convertor->fAdvance = opal_pack_general_checksum; } else { - convertor->fAdvance = opal_generic_simple_pack_checksum; + if( datatype->flags & OPAL_DATATYPE_FLAG_CONTIGUOUS ) { + if( ((datatype->ub - datatype->lb) == (OPAL_PTRDIFF_TYPE)datatype->size) + || (1 >= convertor->count) ) + convertor->fAdvance = opal_pack_homogeneous_contig_checksum; + else + convertor->fAdvance = opal_pack_homogeneous_contig_with_gaps_checksum; + } else { + convertor->fAdvance = opal_generic_simple_pack_checksum; + } } } else { - if( datatype->flags & OPAL_DATATYPE_FLAG_CONTIGUOUS ) { - if( ((datatype->ub - datatype->lb) == (OPAL_PTRDIFF_TYPE)datatype->size) - || (1 >= convertor->count) ) - convertor->fAdvance = opal_pack_homogeneous_contig; - else - convertor->fAdvance = opal_pack_homogeneous_contig_with_gaps; + if( CONVERTOR_SEND_CONVERSION == (convertor->flags & (CONVERTOR_SEND_CONVERSION|CONVERTOR_HOMOGENEOUS)) ) { + convertor->fAdvance = opal_pack_general; } else { - convertor->fAdvance = opal_generic_simple_pack; + if( datatype->flags & OPAL_DATATYPE_FLAG_CONTIGUOUS ) { + if( ((datatype->ub - datatype->lb) == (OPAL_PTRDIFF_TYPE)datatype->size) + || (1 >= convertor->count) ) + convertor->fAdvance = opal_pack_homogeneous_contig; + else + convertor->fAdvance = opal_pack_homogeneous_contig_with_gaps; + } else { + convertor->fAdvance = opal_generic_simple_pack; + } } } return OPAL_SUCCESS; @@ -678,15 +676,33 @@ int opal_convertor_clone( const opal_convertor_t* source, void opal_convertor_dump( opal_convertor_t* convertor ) { - printf( "Convertor %p count %d stack position %d bConverted %ld\n", (void*)convertor, - convertor->count, convertor->stack_pos, (unsigned long)convertor->bConverted ); - printf( "\tlocal_size %ld remote_size %ld flags %X stack_size %d pending_length %d\n", - (unsigned long)convertor->local_size, (unsigned long)convertor->remote_size, - convertor->flags, convertor->stack_size, convertor->partial_length ); + opal_output( 0, "Convertor %p count %d stack position %d bConverted %ld\n" + "\tlocal_size %ld remote_size %ld flags %X stack_size %d pending_length %d\n" + "\tremote_arch %u local_arch %u\n", + (void*)convertor, + convertor->count, convertor->stack_pos, (unsigned long)convertor->bConverted, + (unsigned long)convertor->local_size, (unsigned long)convertor->remote_size, + convertor->flags, convertor->stack_size, convertor->partial_length, + convertor->remoteArch, opal_local_arch ); + if( convertor->flags & CONVERTOR_RECV ) opal_output( 0, "unpack "); + if( convertor->flags & CONVERTOR_SEND ) opal_output( 0, "pack "); + if( convertor->flags & CONVERTOR_SEND_CONVERSION ) opal_output( 0, "conversion "); + if( convertor->flags & CONVERTOR_HOMOGENEOUS ) opal_output( 0, "homogeneous " ); + else opal_output( 0, "heterogeneous "); + if( convertor->flags & CONVERTOR_NO_OP ) opal_output( 0, "no_op "); + if( convertor->flags & CONVERTOR_WITH_CHECKSUM ) opal_output( 0, "checksum "); + if( convertor->flags & CONVERTOR_CUDA ) opal_output( 0, "CUDA "); + if( convertor->flags & CONVERTOR_CUDA_ASYNC ) opal_output( 0, "CUDA Async "); + if( convertor->flags & CONVERTOR_COMPLETED ) opal_output( 0, "COMPLETED "); + opal_datatype_dump( convertor->pDesc ); - printf( "Actual stack representation\n" ); - opal_datatype_dump_stack( convertor->pStack, convertor->stack_pos, - convertor->pDesc->desc.desc, convertor->pDesc->name ); + if( !((0 == convertor->stack_pos) && + ((size_t)convertor->pStack[convertor->stack_pos].index > convertor->pDesc->desc.length)) ) { + /* only if the convertor is completely initialized */ + opal_output( 0, "Actual stack representation\n" ); + opal_datatype_dump_stack( convertor->pStack, convertor->stack_pos, + convertor->pDesc->desc.desc, convertor->pDesc->name ); + } } diff --git a/opal/datatype/opal_convertor.h b/opal/datatype/opal_convertor.h index 5b26b7e7d6..7c5de1af39 100644 --- a/opal/datatype/opal_convertor.h +++ b/opal/datatype/opal_convertor.h @@ -175,9 +175,7 @@ static inline int opal_convertor_cleanup( opal_convertor_t* convertor ) */ static inline int32_t opal_convertor_need_buffers( const opal_convertor_t* pConvertor ) { -#if OPAL_ENABLE_HETEROGENEOUS_SUPPORT if (OPAL_UNLIKELY(0 == (pConvertor->flags & CONVERTOR_HOMOGENEOUS))) return 1; -#endif #if OPAL_CUDA_SUPPORT if( pConvertor->flags & (CONVERTOR_CUDA | CONVERTOR_CUDA_UNIFIED)) return 1; #endif diff --git a/opal/datatype/opal_datatype_add.c b/opal/datatype/opal_datatype_add.c index d6a1458b65..890f5503bb 100644 --- a/opal/datatype/opal_datatype_add.c +++ b/opal/datatype/opal_datatype_add.c @@ -3,7 +3,7 @@ * Copyright (c) 2004-2006 The Trustees of Indiana University and Indiana * University Research and Technology * Corporation. All rights reserved. - * Copyright (c) 2004-2009 The University of Tennessee and The University + * Copyright (c) 2004-2016 The University of Tennessee and The University * of Tennessee Research Foundation. All rights * reserved. * Copyright (c) 2004-2006 High Performance Computing Center Stuttgart, @@ -278,27 +278,14 @@ int32_t opal_datatype_add( opal_datatype_t* pdtBase, const opal_datatype_t* pdtA */ if( (pdtAdd->flags & (OPAL_DATATYPE_FLAG_PREDEFINED | OPAL_DATATYPE_FLAG_DATA)) == (OPAL_DATATYPE_FLAG_PREDEFINED | OPAL_DATATYPE_FLAG_DATA) ) { pdtBase->btypes[pdtAdd->id] += count; + pLast->elem.common.type = pdtAdd->id; + pLast->elem.count = count; + pLast->elem.disp = disp; + pLast->elem.extent = extent; + pdtBase->desc.used++; + pLast->elem.common.flags = pdtAdd->flags & ~(OPAL_DATATYPE_FLAG_COMMITTED); if( (extent != (OPAL_PTRDIFF_TYPE)pdtAdd->size) && (count > 1) ) { /* gaps around the datatype */ - localFlags = pdtAdd->flags & ~(OPAL_DATATYPE_FLAG_COMMITTED | OPAL_DATATYPE_FLAG_CONTIGUOUS | OPAL_DATATYPE_FLAG_NO_GAPS); - CREATE_LOOP_START( pLast, count, 2, extent, localFlags ); - pLast++; - pLast->elem.common.type = pdtAdd->id; - pLast->elem.count = 1; - pLast->elem.disp = disp; - pLast->elem.extent = pdtAdd->size; - pLast->elem.common.flags = localFlags | OPAL_DATATYPE_FLAG_CONTIGUOUS; - pLast++; - CREATE_LOOP_END( pLast, 2, disp, pdtAdd->size, localFlags ); - pdtBase->desc.used += 3; - pdtBase->btypes[OPAL_DATATYPE_LOOP] = 1; - pdtBase->btypes[OPAL_DATATYPE_END_LOOP] = 1; - } else { - pLast->elem.common.type = pdtAdd->id; - pLast->elem.count = count; - pLast->elem.disp = disp; - pLast->elem.extent = extent; - pdtBase->desc.used++; - pLast->elem.common.flags = pdtAdd->flags & ~(OPAL_DATATYPE_FLAG_COMMITTED); + pLast->elem.common.flags &= ~(OPAL_DATATYPE_FLAG_CONTIGUOUS | OPAL_DATATYPE_FLAG_NO_GAPS); } } else { /* keep trace of the total number of basic datatypes in the datatype definition */ diff --git a/opal/datatype/opal_datatype_dump.c b/opal/datatype/opal_datatype_dump.c index c1b86cb439..3057567419 100644 --- a/opal/datatype/opal_datatype_dump.c +++ b/opal/datatype/opal_datatype_dump.c @@ -89,8 +89,8 @@ int opal_datatype_dump_data_desc( dt_elem_desc_t* pDesc, int nbElems, char* ptr, (int)pDesc->end_loop.items, (long)pDesc->end_loop.first_elem_disp, (int)pDesc->end_loop.size ); else - index += snprintf( ptr + index, length - index, "count %d disp 0x%lx (%ld) extent %d (size %ld)\n", - (int)pDesc->elem.count, (long)pDesc->elem.disp, (long)pDesc->elem.disp, + index += snprintf( ptr + index, length - index, "count %d disp 0x%lx (%ld) blen %d extent %d (size %ld)\n", + (int)pDesc->elem.count, (long)pDesc->elem.disp, (long)pDesc->elem.disp, (int)pDesc->elem.blocklen, (int)pDesc->elem.extent, (long)(pDesc->elem.count * opal_datatype_basicDatatypes[pDesc->elem.common.type]->size) ); pDesc++; diff --git a/opal/datatype/opal_datatype_pack.c b/opal/datatype/opal_datatype_pack.c index 45f1213b81..7c8fb58e69 100644 --- a/opal/datatype/opal_datatype_pack.c +++ b/opal/datatype/opal_datatype_pack.c @@ -3,7 +3,7 @@ * Copyright (c) 2004-2006 The Trustees of Indiana University and Indiana * University Research and Technology * Corporation. All rights reserved. - * Copyright (c) 2004-2014 The University of Tennessee and The University + * Copyright (c) 2004-2016 The University of Tennessee and The University * of Tennessee Research Foundation. All rights * reserved. * Copyright (c) 2004-2006 High Performance Computing Center Stuttgart, @@ -42,10 +42,12 @@ #define opal_pack_homogeneous_contig_function opal_pack_homogeneous_contig_checksum #define opal_pack_homogeneous_contig_with_gaps_function opal_pack_homogeneous_contig_with_gaps_checksum #define opal_generic_simple_pack_function opal_generic_simple_pack_checksum +#define opal_pack_general_function opal_pack_general_checksum #else #define opal_pack_homogeneous_contig_function opal_pack_homogeneous_contig #define opal_pack_homogeneous_contig_with_gaps_function opal_pack_homogeneous_contig_with_gaps #define opal_generic_simple_pack_function opal_generic_simple_pack +#define opal_pack_general_function opal_pack_general #endif /* defined(CHECKSUM) */ @@ -393,3 +395,199 @@ opal_generic_simple_pack_function( opal_convertor_t* pConvertor, pConvertor->stack_pos, pStack->index, (int)pStack->count, (long)pStack->disp ); ); return 0; } + +/* + * Remember that the first item in the stack (ie. position 0) is the number + * of times the datatype is involved in the operation (ie. the count argument + * in the MPI_ call). + */ +/* Convert data from multiple input buffers (as received from the network layer) + * to a contiguous output buffer with a predefined size. + * return OPAL_SUCCESS if everything went OK and if there is still room before the complete + * conversion of the data (need additional call with others input buffers ) + * 1 if everything went fine and the data was completly converted + * -1 something wrong occurs. + */ + +static inline void +pack_predefined_heterogeneous( opal_convertor_t* CONVERTOR, + const dt_elem_desc_t* ELEM, + uint32_t* COUNT, + unsigned char** SOURCE, + unsigned char** DESTINATION, + size_t* SPACE ) +{ + uint32_t _count = *(COUNT); + size_t _r_blength, _l_blength; + const ddt_elem_desc_t* _elem = &((ELEM)->elem); + unsigned char* _source = (*SOURCE) + _elem->disp; + const opal_convertor_master_t* master = (CONVERTOR)->master; + OPAL_PTRDIFF_TYPE advance; + + _r_blength = master->remote_sizes[_elem->common.type]; + _l_blength = opal_datatype_basicDatatypes[_elem->common.type]->size; + if( (_count * _r_blength) > *(SPACE) ) { + _count = (uint32_t)(*(SPACE) / _r_blength); + if( 0 == _count ) return; /* nothing to do */ + } + + OPAL_DATATYPE_SAFEGUARD_POINTER( _source, (_count * _elem->extent), (CONVERTOR)->pBaseBuf, + (CONVERTOR)->pDesc, (CONVERTOR)->count ); + DO_DEBUG( opal_output( 0, "pack [l %s r %s] memcpy( %p, %p, %lu ) => space %lu\n", + ((OPAL_PTRDIFF_TYPE)_l_blength == _elem->extent) ? "cont" : "----", + ((OPAL_PTRDIFF_TYPE)_r_blength == _elem->extent) ? "cont" : "----", + *(DESTINATION), _source, (unsigned long)_r_blength, + (unsigned long)(*(SPACE)) ); ); + master->pFunctions[_elem->common.type]( CONVERTOR, _count, + _source, *SPACE, _elem->extent, + *DESTINATION, *SPACE, _r_blength, + &advance ); + _r_blength *= _count; /* update the remote length to encompass all the elements */ + *(SOURCE) += _count * _elem->extent; + *(DESTINATION) += _r_blength; + *(SPACE) -= _r_blength; + *(COUNT) -= _count; +} + +int32_t +opal_pack_general_function( opal_convertor_t* pConvertor, + struct iovec* iov, uint32_t* out_size, + size_t* max_data ) +{ + dt_stack_t* pStack; /* pointer to the position on the stack */ + uint32_t pos_desc; /* actual position in the description of the derived datatype */ + uint32_t count_desc; /* the number of items already done in the actual pos_desc */ + size_t total_packed = 0; /* total amount packed this time */ + dt_elem_desc_t* description; + dt_elem_desc_t* pElem; + const opal_datatype_t *pData = pConvertor->pDesc; + unsigned char *conv_ptr, *iov_ptr; + size_t iov_len_local; + uint32_t iov_count; + int type, rc; + const opal_convertor_master_t* master = pConvertor->master; + ptrdiff_t advance; + + DO_DEBUG( opal_output( 0, "opal_convertor_general_pack( %p:%p, {%p, %lu}, %d )\n", + (void*)pConvertor, (void*)pConvertor->pBaseBuf, + iov[0].iov_base, (unsigned long)iov[0].iov_len, *out_size ); ); + + description = pConvertor->use_desc->desc; + + /* For the first step we have to add both displacement to the source. After in the + * main while loop we will set back the conv_ptr to the correct value. This is + * due to the fact that the convertor can stop in the middle of a data with a count + */ + pStack = pConvertor->pStack + pConvertor->stack_pos; + pos_desc = pStack->index; + conv_ptr = pConvertor->pBaseBuf + pStack->disp; + count_desc = (uint32_t)pStack->count; + pStack--; + pConvertor->stack_pos--; + pElem = &(description[pos_desc]); + + DO_DEBUG( opal_output( 0, "pack start pos_desc %d count_desc %d disp %ld\n" + "stack_pos %d pos_desc %d count_desc %d disp %ld\n", + pos_desc, count_desc, (long)(conv_ptr - pConvertor->pBaseBuf), + pConvertor->stack_pos, pStack->index, (int)pStack->count, (long)pStack->disp ); ); + + for( iov_count = 0; iov_count < (*out_size); iov_count++ ) { + iov_ptr = (unsigned char *) iov[iov_count].iov_base; + iov_len_local = iov[iov_count].iov_len; + while( 1 ) { + while( pElem->elem.common.flags & OPAL_DATATYPE_FLAG_DATA ) { + type = description[pos_desc].elem.common.type; + /* now here we have a basic datatype */ + DO_DEBUG( opal_output( 0, "pack (%p:%ld, %d, %ld) -> (%p, %ld) type %s\n", + pConvertor->pBaseBuf, conv_ptr + pElem->elem.disp - pConvertor->pBaseBuf, + count_desc, description[pos_desc].elem.extent, + iov_ptr, iov_len_local, + opal_datatype_basicDatatypes[type]->name ); ); + + pack_predefined_heterogeneous( pConvertor, pElem, &count_desc, + &conv_ptr, &iov_ptr, &iov_len_local); +#if 0 + PACK_PREDEFINED_DATATYPE( pConvertor, pElem, count_desc, + conv_ptr, iov_ptr, iov_len_local ); +#endif + if( 0 == count_desc ) { /* completed */ + conv_ptr = pConvertor->pBaseBuf + pStack->disp; + pos_desc++; /* advance to the next data */ + UPDATE_INTERNAL_COUNTERS( description, pos_desc, pElem, count_desc ); + continue; + } + goto complete_loop; + } + if( OPAL_DATATYPE_END_LOOP == pElem->elem.common.type ) { /* end of the current loop */ + DO_DEBUG( opal_output( 0, "pack end_loop count %d stack_pos %d" + " pos_desc %d disp %ld space %lu\n", + (int)pStack->count, pConvertor->stack_pos, + pos_desc, (long)pStack->disp, (unsigned long)iov_len_local ); ); + if( --(pStack->count) == 0 ) { /* end of loop */ + if( 0 == pConvertor->stack_pos ) { + /* we lie about the size of the next element in order to + * make sure we exit the main loop. + */ + *out_size = iov_count; + goto complete_loop; /* completed */ + } + pConvertor->stack_pos--; + pStack--; + pos_desc++; + } else { + pos_desc = pStack->index + 1; + if( pStack->index == -1 ) { + pStack->disp += (pData->ub - pData->lb); + } else { + assert( OPAL_DATATYPE_LOOP == description[pStack->index].loop.common.type ); + pStack->disp += description[pStack->index].loop.extent; + } + } + conv_ptr = pConvertor->pBaseBuf + pStack->disp; + UPDATE_INTERNAL_COUNTERS( description, pos_desc, pElem, count_desc ); + DO_DEBUG( opal_output( 0, "pack new_loop count %d stack_pos %d pos_desc %d count_desc %d disp %ld space %lu\n", + (int)pStack->count, pConvertor->stack_pos, pos_desc, + count_desc, (long)pStack->disp, (unsigned long)iov_len_local ); ); + } + if( OPAL_DATATYPE_LOOP == pElem->elem.common.type ) { + OPAL_PTRDIFF_TYPE local_disp = (OPAL_PTRDIFF_TYPE)conv_ptr; +#if 0 + if( pElem->loop.common.flags & OPAL_DATATYPE_FLAG_CONTIGUOUS ) { + PACK_CONTIGUOUS_LOOP( pConvertor, pElem, count_desc, + conv_ptr, iov_ptr, iov_len_local ); + if( 0 == count_desc ) { /* completed */ + pos_desc += pElem->loop.items + 1; + goto update_loop_description; + } + /* Save the stack with the correct last_count value. */ + } +#endif /* in a heterogeneous environment we can't handle the contiguous loops */ + local_disp = (OPAL_PTRDIFF_TYPE)conv_ptr - local_disp; + PUSH_STACK( pStack, pConvertor->stack_pos, pos_desc, OPAL_DATATYPE_LOOP, count_desc, + pStack->disp + local_disp); + pos_desc++; + update_loop_description: /* update the current state */ + conv_ptr = pConvertor->pBaseBuf + pStack->disp; + UPDATE_INTERNAL_COUNTERS( description, pos_desc, pElem, count_desc ); + DDT_DUMP_STACK( pConvertor->pStack, pConvertor->stack_pos, pElem, "advance loop" ); + continue; + } + } + complete_loop: + iov[iov_count].iov_len -= iov_len_local; /* update the amount of valid data */ + total_packed += iov[iov_count].iov_len; + } + *max_data = total_packed; + pConvertor->bConverted += total_packed; /* update the already converted bytes */ + *out_size = iov_count; + if( pConvertor->bConverted == pConvertor->local_size ) { + pConvertor->flags |= CONVERTOR_COMPLETED; + return 1; + } + /* Save the global position for the next round */ + PUSH_STACK( pStack, pConvertor->stack_pos, pos_desc, pElem->elem.common.type, count_desc, + conv_ptr - pConvertor->pBaseBuf ); + DO_DEBUG( opal_output( 0, "pack save stack stack_pos %d pos_desc %d count_desc %d disp %ld\n", + pConvertor->stack_pos, pStack->index, (int)pStack->count, (long)pStack->disp ); ); + return 0; +} diff --git a/opal/datatype/opal_datatype_prototypes.h b/opal/datatype/opal_datatype_prototypes.h index bcfb59b9b3..668397112b 100644 --- a/opal/datatype/opal_datatype_prototypes.h +++ b/opal/datatype/opal_datatype_prototypes.h @@ -1,6 +1,6 @@ /* -*- Mode: C; c-basic-offset:4 ; -*- */ /* - * Copyright (c) 2004-2009 The University of Tennessee and The University + * Copyright (c) 2004-2016 The University of Tennessee and The University * of Tennessee Research Foundation. All rights * reserved. * Copyright (c) 2009 Oak Ridge National Labs. All rights reserved. @@ -24,6 +24,14 @@ BEGIN_C_DECLS */ OPAL_DECLSPEC int32_t +opal_pack_general( opal_convertor_t* pConvertor, + struct iovec* iov, uint32_t* out_size, + size_t* max_data ); +OPAL_DECLSPEC int32_t +opal_pack_general_checksum( opal_convertor_t* pConvertor, + struct iovec* iov, uint32_t* out_size, + size_t* max_data ); +OPAL_DECLSPEC int32_t opal_unpack_general( opal_convertor_t* pConvertor, struct iovec* iov, uint32_t* out_size, size_t* max_data ); diff --git a/test/datatype/Makefile.am b/test/datatype/Makefile.am index d870e6902e..39c2b8c1cd 100644 --- a/test/datatype/Makefile.am +++ b/test/datatype/Makefile.am @@ -14,7 +14,7 @@ # if PROJECT_OMPI - MPI_TESTS = checksum position position_noncontig ddt_test ddt_raw unpack_ooo ddt_pack + MPI_TESTS = checksum position position_noncontig ddt_test ddt_raw unpack_ooo ddt_pack external32 MPI_CHECKS = to_self endif TESTS = opal_datatype_test $(MPI_TESTS) @@ -72,5 +72,11 @@ opal_datatype_test_LDFLAGS = $(OMPI_PKG_CONFIG_LDFLAGS) opal_datatype_test_LDADD = \ $(top_builddir)/opal/lib@OPAL_LIB_PREFIX@open-pal.la +external32_SOURCES = external32.c +external32_LDFLAGS = $(OMPI_PKG_CONFIG_LDFLAGS) +external32_LDADD = \ + $(top_builddir)/ompi/libmpi.la \ + $(top_builddir)/opal/lib@OPAL_LIB_PREFIX@open-pal.la + distclean: rm -rf *.dSYM .deps .libs *.log *.o *.trs $(check_PROGRAMS) Makefile diff --git a/test/datatype/external32.c b/test/datatype/external32.c new file mode 100644 index 0000000000..d09938510b --- /dev/null +++ b/test/datatype/external32.c @@ -0,0 +1,228 @@ +/* -*- Mode: C; c-basic-offset:4 ; -*- */ +/* + * Copyright (c) 2016 The University of Tennessee and The University + * of Tennessee Research Foundation. All rights + * reserved. + * $COPYRIGHT$ + * + * Additional copyrights may follow + * + * $HEADER$ + */ + +#include +#include + +#include "ompi_config.h" +#include "ompi/datatype/ompi_datatype.h" +#include "opal/runtime/opal.h" +#include "opal/datatype/opal_convertor.h" +#include "opal/datatype/opal_datatype_internal.h" +#include + +static int verbose = 0; + +typedef int (*checker_t)(void*, void*, ompi_datatype_t *, int, void*); + +int check_contiguous( void* send_buffer, void* packed, + ompi_datatype_t * datatype, int count, void* arg ); + +int check_vector( void* send_buffer, void* packed, + ompi_datatype_t * datatype, int count, void* arg ); + +static int pack_unpack_datatype( void* send_data, ompi_datatype_t *datatype, int count, + void* recv_data, checker_t validator, void *validator_arg ); + +static void dump_hex(void* what, size_t length); + +static void dump_hex(void* what, size_t length) +{ + size_t i; + for( i = 0; i < length; i++ ) { + printf("%02x", (unsigned int)(((unsigned char*)what)[i])); + } +} + +int check_contiguous( void* send_buffer, void* packed, + ompi_datatype_t* datatype, int count, void* arg ) +{ + int i; + + if( (datatype == &ompi_mpi_int.dt) || (datatype == &ompi_mpi_int32_t.dt) ) { + uint32_t val; + for( i = 0 ; i < count; i++ ) { + val = htonl(((uint32_t*)send_buffer)[i]); + if( val != ((uint32_t*)packed)[i] ) { + printf("Error at position %d expected %x found %x (type %s)\n", + i, ((uint32_t*)packed)[i], ((uint32_t*)send_buffer)[i], datatype->name); + return -1; + } + } + } else if( (datatype == &ompi_mpi_short.dt) || (datatype == &ompi_mpi_int16_t.dt) ) { + uint16_t val; + for( i = 0 ; i < count; i++ ) { + val = htons(((uint16_t*)send_buffer)[i]); + if( val != ((uint16_t*)packed)[i] ) { + printf("Error at position %d expected %x found %x (type %s)\n", + i, ((uint16_t*)packed)[i], ((uint16_t*)send_buffer)[i], datatype->name); + return -1; + } + } + } else { + printf("Unknown type\n"); + return -1; + } + return 0; +} + +int check_vector( void* send_buffer, void* packed, + ompi_datatype_t* datatype, int count, void* arg ) +{ + int i; + ompi_datatype_t *origtype = (ompi_datatype_t *)arg; + + if( (origtype == &ompi_mpi_int.dt) || (origtype == &ompi_mpi_int32_t.dt) ) { + uint32_t val; + for( i = 0 ; i < count; i++ ) { + val = htonl(((uint32_t*)send_buffer)[2*i]); + if( val != ((uint32_t*)packed)[i] ) { + printf("Error at position %d expected %x found %x (type %s)\n", + i, ((uint32_t*)packed)[i], ((uint32_t*)send_buffer)[2*i], datatype->name); + return -1; + } + } + } else if( (origtype == &ompi_mpi_short.dt) || (origtype == &ompi_mpi_int16_t.dt) ) { + uint16_t val; + for( i = 0 ; i < count; i++ ) { + val = htons(((uint16_t*)send_buffer)[2*i]); + if( val != ((uint16_t*)packed)[i] ) { + printf("Error at position %d expected %x found %x (type %s)\n", + i, ((uint16_t*)packed)[i], ((uint16_t*)send_buffer)[2*i], datatype->name); + return -1; + } + } + } else { + printf("Unknown %s type\n", datatype->name); + return -1; + } + return 0; +} + +static int pack_unpack_datatype( void* send_data, ompi_datatype_t *datatype, int count, + void* recv_data, + checker_t validator, void* validator_arg) +{ + MPI_Aint position = 0, buffer_size; + void* buffer; + int error; + + error = ompi_datatype_pack_external_size("external32", + count, datatype, &buffer_size); + if( MPI_SUCCESS != error ) goto return_error_code; + + buffer = (void*)malloc(buffer_size); + if( NULL == buffer ) { error = MPI_ERR_UNKNOWN; goto return_error_code; } + + error = ompi_datatype_pack_external("external32", (void*)send_data, count, datatype, + buffer, buffer_size, &position); + if( MPI_SUCCESS != error ) goto return_error_code; + if( 0 != validator(send_data, buffer, datatype, count, validator_arg) ) { + printf("Error during pack external. Bailing out\n"); + return -1; + } + + printf("packed %ld bytes into a %ld bytes buffer ", position, buffer_size); dump_hex(buffer, position); printf("\n"); + + position = 0; + error = ompi_datatype_unpack_external("external32", buffer, buffer_size, &position, + recv_data, count, datatype); + if( MPI_SUCCESS != error ) goto return_error_code; + free(buffer); + + return_error_code: + return (error == MPI_SUCCESS ? 0 : -1); +} + +int main(int argc, char *argv[]) +{ + opal_init_util(&argc, &argv); + ompi_datatype_init(); + + /* Simple contiguous data: MPI_INT32_T */ + { + int32_t send_data[2] = {1234, 5678}; + int32_t recv_data[2] = {-1, -1}; + + if( verbose ) { + printf("send data %08x %08x \n", send_data[0], send_data[1]); + printf("data "); dump_hex(&send_data, sizeof(int32_t) * 2); printf("\n"); + } + (void)pack_unpack_datatype( send_data, &ompi_mpi_int32_t.dt, 2, + recv_data, check_contiguous, (void*)&ompi_mpi_int32_t.dt ); + if( verbose ) { + printf("recv "); dump_hex(&recv_data, sizeof(int32_t) * 2); printf("\n"); + printf("recv data %08x %08x \n", recv_data[0], recv_data[1]); + } + if( (send_data[0] != recv_data[0]) || (send_data[1] != recv_data[1]) ) { + printf("Error during external32 pack/unack for contiguous types (MPI_INT32_T)\n"); + exit(-1); + } + } + /* Simple contiguous data: MPI_INT16_T */ + { + int16_t send_data[2] = {1234, 5678}; + int16_t recv_data[2] = {-1, -1}; + + if( verbose ) { + printf("send data %08x %08x \n", send_data[0], send_data[1]); + printf("data "); dump_hex(&send_data, sizeof(int16_t) * 2); printf("\n"); + } + (void)pack_unpack_datatype( send_data, &ompi_mpi_int16_t.dt, 2, + recv_data, check_contiguous, (void*)&ompi_mpi_int16_t.dt ); + if( verbose ) { + printf("recv "); dump_hex(&recv_data, sizeof(int16_t) * 2); printf("\n"); + printf("recv data %08x %08x \n", recv_data[0], recv_data[1]); + } + if( (send_data[0] != recv_data[0]) || (send_data[1] != recv_data[1]) ) { + printf("Error during external32 pack/unack for contiguous types\n"); + exit(-1); + } + } + + /* Vector datatype */ + printf("\n\nVector datatype\n\n"); + { + int count=2, blocklength=1, stride=2; + int send_data[3] = {1234, 0, 5678}; + int recv_data[3] = {-1, -1, -1}; + ompi_datatype_t *ddt; + + ompi_datatype_create_vector ( count, blocklength, stride, &ompi_mpi_int.dt, &ddt ); + { + const int* a_i[3] = {&count, &blocklength, &stride}; + ompi_datatype_t *type = &ompi_mpi_int.dt; + + ompi_datatype_set_args( ddt, 3, a_i, 0, NULL, 1, &type, MPI_COMBINER_VECTOR ); + } + ompi_datatype_commit(&ddt); + + if( verbose ) { + printf("send data %08x %x08x %08x \n", send_data[0], send_data[1], send_data[2]); + printf("data "); dump_hex(&send_data, sizeof(int32_t) * 3); printf("\n"); + } + (void)pack_unpack_datatype( send_data, ddt, 1, recv_data, check_vector, (void*)&ompi_mpi_int32_t.dt ); + if( verbose ) { + printf("recv "); dump_hex(&recv_data, sizeof(int32_t) * 3); printf("\n"); + printf("recv data %08x %08x %08x \n", recv_data[0], recv_data[1], recv_data[2]); + } + ompi_datatype_destroy(&ddt); + if( (send_data[0] != recv_data[0]) || (send_data[2] != recv_data[2]) ) { + printf("Error during external32 pack/unack for vector types (MPI_INT32_T)\n"); + exit(-1); + } + } + + ompi_datatype_finalize(); + + return 0; +}