From: Julian Seward Date: Fri, 3 Mar 2006 16:14:18 +0000 (+0000) Subject: Beginnings of proper MPI user type-walking code. X-Git-Tag: svn/VALGRIND_3_2_0~238 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=fa1c58807636713d6512193efd24017a1475fc94;p=thirdparty%2Fvalgrind.git Beginnings of proper MPI user type-walking code. git-svn-id: svn://svn.valgrind.org/valgrind/trunk@5709 --- diff --git a/auxprogs/Makefile.am b/auxprogs/Makefile.am index 085daea471..39ba4a0332 100644 --- a/auxprogs/Makefile.am +++ b/auxprogs/Makefile.am @@ -45,7 +45,7 @@ noinst_PROGRAMS = libmpiwrap.so # -I../include -I@MPI_PREFIX@/include #libmpiwrap_so_LDFLAGS = $(AM_FLAG_M3264_PRI) -g -shared libmpiwrap.so: mpiwrap.c - $(MPI_CC) -g -O -fno-omit-frame-pointer -fpic -shared \ + $(MPI_CC) -g -O -fno-omit-frame-pointer -Wall -fpic -shared \ -I../include -I@MPI_PREFIX@/include \ $(AM_FLAG_M3264_PRI) \ -o libmpiwrap.so mpiwrap.c diff --git a/auxprogs/mpiwrap.c b/auxprogs/mpiwrap.c index 0d1d0f2143..c629ba5b5b 100644 --- a/auxprogs/mpiwrap.c +++ b/auxprogs/mpiwrap.c @@ -136,6 +136,12 @@ static inline void before ( char* fnname ) opt_strict = NULL != strstr(options_str, "strict"); fprintf(stderr, "%s %5d: Active for pid %d\n", preamble, my_pid, my_pid); + + /* Sanity check - that 'long' really is a machine word. */ + assert(sizeof(long) == sizeof(void*)); + /* Sanity check - char is byte-sized (else address calculations + in walk_type don't work. */ + assert(sizeof(char) == 1); if (opt_help) { fprintf(stderr, "\n"); fprintf(stderr, "Valid options for the MPIWRAP_DEBUG environment" @@ -224,82 +230,186 @@ Bool eq_MPI_Request ( MPI_Request r1, MPI_Request r2 ) return r1 == r2; } +static long extentOfTy ( MPI_Datatype ty ) +{ + int r; + MPI_Aint n; + r = PMPI_Type_extent(ty, &n); + assert(r == MPI_SUCCESS); + return (long)n; +} -/*------------------------------------------------------------*/ -/*--- Address-range helpers ---*/ -/*------------------------------------------------------------*/ +/* Free up *ty, if it is not a named type */ +static void maybeFreeTy ( MPI_Datatype* ty ) +{ + int r, n_ints, n_addrs, n_dtys, tycon; -/* ---------------- - Do checks on memory areas defined using the MPI (buffer, count, - type) convention. - ---------------- -*/ + r = PMPI_Type_get_envelope( *ty, &n_ints, &n_addrs, &n_dtys, &tycon ); + assert(r == MPI_SUCCESS); -static inline long datasize ( MPI_Datatype datatype ) -{ - if (datatype == MPI_INT) return sizeof(signed int); - if (datatype == MPI_DOUBLE) return sizeof(double); - if (datatype == MPI_CHAR) return sizeof(signed char); - if (datatype == MPI_UNSIGNED) return sizeof(unsigned int); - fprintf(stderr, "%s %5d: datasize: unhandled PMPI_Datatype %d\n", - preamble, my_pid, (int)datatype); - return 0; + if (tycon != MPI_COMBINER_NAMED) { + r = MPI_Type_free(ty); + assert(r == MPI_SUCCESS); + } } -/* Check that the specified area is both addressible and contains - initialised data, and cause V to complain if not. */ +/*------------------------------------------------------------*/ +/*--- Unpicking datatypes ---*/ +/*------------------------------------------------------------*/ -static -void check_readable ( void *buffer, long count, MPI_Datatype datatype ) +static +void walk_type_array ( void(*f)(void*,long), char* base, + MPI_Datatype ty, long count ); + + +/* Walk over all fragments of the object of type 'ty' with base + address 'base', and apply 'f' to the start/length of each + contiguous fragment. */ +static +void walk_type ( void(*f)(void*,long), char* base, MPI_Datatype ty ) { - long nbytes = count * datasize(datatype); - if (nbytes > 0) { - VALGRIND_CHECK_READABLE(buffer, nbytes); + int r, n_ints, n_addrs, n_dtys, tycon; + long ex, count, i; + int* ints = NULL; + MPI_Aint* addrs = NULL; + MPI_Datatype* dtys = NULL; + // MPI_Datatype elemTy; + + if (1) { + printf("walk_type %p\n", (void*)ty); + if (ty == MPI_DATATYPE_NULL) printf("MPI_DATATYPE_NULL\n"); + else if (ty == MPI_BYTE) printf("MPI_BYTE\n"); + else if (ty == MPI_PACKED) printf("MPI_PACKED\n"); + else if (ty == MPI_CHAR) printf("MPI_CHAR\n"); + else if (ty == MPI_SHORT) printf("MPI_SHORT\n"); + else if (ty == MPI_INT) printf("MPI_INT\n"); + else if (ty == MPI_LONG) printf("MPI_LONG\n"); + else if (ty == MPI_FLOAT) printf("MPI_FLOAT\n"); + else if (ty == MPI_DOUBLE) printf("MPI_DOUBLE\n"); + else if (ty == MPI_LONG_DOUBLE) printf("MPI_LONG_DOUBLE\n"); + else if (ty == MPI_UNSIGNED_CHAR) printf("MPI_UNSIGNED_CHAR\n"); + else if (ty == MPI_UNSIGNED_SHORT) printf("MPI_UNSIGNED_SHORT\n"); + else if (ty == MPI_UNSIGNED_LONG) printf("MPI_UNSIGNED_LONG\n"); + else if (ty == MPI_UNSIGNED) printf("MPI_UNSIGNED\n"); + else if (ty == MPI_FLOAT_INT) printf("MPI_FLOAT_INT\n"); + else if (ty == MPI_DOUBLE_INT) printf("MPI_DOUBLE_INT\n"); + else if (ty == MPI_LONG_DOUBLE_INT) printf("MPI_LONG_DOUBLE_INT\n"); + else if (ty == MPI_LONG_INT) printf("MPI_LONG_INT\n"); + else if (ty == MPI_SHORT_INT) printf("MPI_SHORT_INT\n"); + else if (ty == MPI_2INT) printf("MPI_2INT\n"); + else if (ty == MPI_UB) printf("MPI_UB\n"); + else if (ty == MPI_LB) printf("MPI_LB\n"); + else if (ty == MPI_WCHAR) printf("MPI_WCHAR\n"); + else if (ty == MPI_LONG_LONG_INT) printf("MPI_LONG_LONG_INT\n"); + else if (ty == MPI_LONG_LONG) printf("MPI_LONG_LONG\n"); + else if (ty == MPI_UNSIGNED_LONG_LONG) printf("MPI_UNSIGNED_LONG_LONG\n"); + else printf("???\n"); + } + assert(ty != MPI_DATATYPE_NULL); + + r = MPI_Type_get_envelope( ty, &n_ints, &n_addrs, &n_dtys, &tycon ); + assert(r == MPI_SUCCESS); + + /* Handle the base cases fast(er/ish). */ + if (tycon == MPI_COMBINER_NAMED) { + if (ty == MPI_DOUBLE) { f(base,sizeof(double)); return; } + if (ty == MPI_INT) { f(base,sizeof(signed int)); return; } + if (ty == MPI_CHAR) { f(base,sizeof(signed char)); return; } + if (ty == MPI_UNSIGNED) { f(base,sizeof(unsigned int)); return; } + goto unhandled; + /*NOTREACHED*/ } -} + if (1) { + ex = extentOfTy(ty); + printf("tycon %p %d %d %d (ext %d)\n", + (void*)tycon, n_ints, n_addrs, n_dtys, (int)ex ); + } -/* Check that the specified area is addressible, and cause V to - complain if not. Doesn't matter whether the data there is - initialised or not. */ + /* Now safe to do MPI_Type_get_contents */ + assert(n_ints >= 0); + assert(n_addrs >= 0); + assert(n_dtys >= 0); -static -void check_writable ( void *buffer, long count, MPI_Datatype datatype ) -{ - long nbytes = count * datasize(datatype); - if (nbytes > 0) { - VALGRIND_CHECK_WRITABLE(buffer, nbytes); + if (n_ints > 0) { + ints = malloc(n_ints * sizeof(int)); + assert(ints); + } + if (n_addrs > 0) { + addrs = malloc(n_addrs * sizeof(MPI_Aint)); + assert(addrs); + } + if (n_dtys > 0) { + dtys = malloc(n_dtys * sizeof(MPI_Datatype)); + assert(dtys); } -} + r = MPI_Type_get_contents( ty, n_ints, n_addrs, n_dtys, + ints, addrs, dtys ); + assert(r == MPI_SUCCESS); -/* Set the specified area to 'addressible and defined' (safe-to-read) - state. */ + switch (tycon) { -static -void make_readable ( void *buffer, int count, MPI_Datatype datatype ) -{ - long nbytes = count * datasize(datatype); - if (nbytes > 0) { - VALGRIND_MAKE_READABLE(buffer, nbytes); + case MPI_COMBINER_CONTIGUOUS: + assert(n_ints == 1 && n_addrs == 0 && n_dtys == 1); + walk_type_array( f, base, dtys[0], ints[0] ); + maybeFreeTy( &dtys[0] ); + break; + + case MPI_COMBINER_STRUCT: + assert(n_addrs == n_ints-1); + assert(n_dtys == n_ints-1); + for (i = 0; i < ints[0]; i++) { + printf("struct (elem %d limit %d) off %d copies %d\n", + (int)i, (int)ints[0], (int)addrs[i], (int)ints[i+1]); + walk_type_array( f, base + addrs[i], dtys[i], (long)ints[i+1] ); + maybeFreeTy( &dtys[i] ); + } + break; + + default: + goto unhandled; + + } + + /* normal exit */ + if (ints) free(ints); + if (addrs) free(addrs); + if (dtys) free(dtys); + return; + + unhandled: + if (tycon == MPI_COMBINER_NAMED) { + fprintf(stderr, "%s %5d: walk_type: unhandled base type 0x%lx\n", + preamble, my_pid, (long)ty); + } else { + fprintf(stderr, "%s %5d: walk_type: unhandled combiner 0x%lx\n", + preamble, my_pid, (long)tycon); } + if (ints) free(ints); + if (addrs) free(addrs); + if (dtys) free(dtys); } -static -void -make_readable_if_success ( int err, void *buffer, int count, - MPI_Datatype datatype ) + +/* Same as walk_type but apply 'f' to every element in an array + of 'count' items starting at 'base'. */ +static +void walk_type_array ( void(*f)(void*,long), char* base, + MPI_Datatype elemTy, long count ) { - if (err == MPI_SUCCESS) { - long nbytes = count * datasize(datatype); - if (nbytes > 0) { - VALGRIND_MAKE_READABLE(buffer, nbytes); - } - } + long i, ex; + ex = extentOfTy(elemTy); + for (i = 0; i < count; i++) + walk_type( f, base + i * ex, elemTy ); } +/*------------------------------------------------------------*/ +/*--- Address-range helpers ---*/ +/*------------------------------------------------------------*/ + /* ---------------- Do corresponding checks on memory areas defined using a straightforward (start, length) description. @@ -351,6 +461,52 @@ void make_writable_untyped ( void* buffer, long nbytes ) } +/* ---------------- + Do checks on memory areas defined using the MPI (buffer, count, + type) convention. + ---------------- +*/ + +/* Check that the specified area is both addressible and contains + initialised data, and cause V to complain if not. */ + +static +void check_readable ( char* buffer, long count, MPI_Datatype datatype ) +{ + walk_type_array( check_readable_untyped, buffer, datatype, count ); +} + + +/* Check that the specified area is addressible, and cause V to + complain if not. Doesn't matter whether the data there is + initialised or not. */ + +static +void check_writable ( void *buffer, long count, MPI_Datatype datatype ) +{ + walk_type_array( check_writable_untyped, buffer, datatype, count ); +} + + +/* Set the specified area to 'addressible and defined' (safe-to-read) + state. */ + +static +void make_readable ( void *buffer, int count, MPI_Datatype datatype ) +{ + walk_type_array( make_readable_untyped, buffer, datatype, count ); +} + +static +void +make_readable_if_success ( int err, void *buffer, int count, + MPI_Datatype datatype ) +{ + if (err == MPI_SUCCESS) + make_readable(buffer, count, datatype); +} + + /*------------------------------------------------------------*/ /*--- ---*/ /*--- The wrappers proper. They are listed in the order ---*/ @@ -1236,10 +1392,10 @@ NO_OP_WRAPPER(Type_contiguous) UNIMPLEMENTED_WRAPPER(Type_count) UNIMPLEMENTED_WRAPPER(Type_create_darray) UNIMPLEMENTED_WRAPPER(Type_create_subarray) -UNIMPLEMENTED_WRAPPER(Type_extent) +NO_OP_WRAPPER(Type_extent) UNIMPLEMENTED_WRAPPER(Type_free) -UNIMPLEMENTED_WRAPPER(Type_get_contents) -UNIMPLEMENTED_WRAPPER(Type_get_envelope) +NO_OP_WRAPPER(Type_get_contents) +NO_OP_WRAPPER(Type_get_envelope) UNIMPLEMENTED_WRAPPER(Type_get_name) UNIMPLEMENTED_WRAPPER(Type_create_hindexed) UNIMPLEMENTED_WRAPPER(Type_create_hvector) @@ -1250,14 +1406,14 @@ NO_OP_WRAPPER(Type_create_struct) UNIMPLEMENTED_WRAPPER(Type_hindexed) UNIMPLEMENTED_WRAPPER(Type_hvector) UNIMPLEMENTED_WRAPPER(Type_indexed) -UNIMPLEMENTED_WRAPPER(Type_lb) +NO_OP_WRAPPER(Type_lb) UNIMPLEMENTED_WRAPPER(Type_set_name) UNIMPLEMENTED_WRAPPER(Type_size) //UNIMPLEMENTED_WRAPPER(Type_struct) NO_OP_WRAPPER(Type_struct) -UNIMPLEMENTED_WRAPPER(Type_ub) +NO_OP_WRAPPER(Type_ub) UNIMPLEMENTED_WRAPPER(Type_vector) UNIMPLEMENTED_WRAPPER(Unpack)