From: <sv...@va...> - 2006-03-03 16:14:27
|
Author: sewardj Date: 2006-03-03 16:14:18 +0000 (Fri, 03 Mar 2006) New Revision: 5709 Log: Beginnings of proper MPI user type-walking code. Modified: trunk/auxprogs/Makefile.am trunk/auxprogs/mpiwrap.c Modified: trunk/auxprogs/Makefile.am =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- trunk/auxprogs/Makefile.am 2006-03-02 17:09:16 UTC (rev 5708) +++ trunk/auxprogs/Makefile.am 2006-03-03 16:14:18 UTC (rev 5709) @@ -45,7 +45,7 @@ # -I../include -I@MPI_PREFIX@/include #libmpiwrap_so_LDFLAGS =3D $(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 Modified: trunk/auxprogs/mpiwrap.c =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- trunk/auxprogs/mpiwrap.c 2006-03-02 17:09:16 UTC (rev 5708) +++ trunk/auxprogs/mpiwrap.c 2006-03-03 16:14:18 UTC (rev 5709) @@ -136,6 +136,12 @@ opt_strict =3D NULL !=3D strstr(options_str, "strict"); fprintf(stderr, "%s %5d: Active for pid %d\n",=20 preamble, my_pid, my_pid); + + /* Sanity check - that 'long' really is a machine word. */ + assert(sizeof(long) =3D=3D sizeof(void*)); + /* Sanity check - char is byte-sized (else address calculations + in walk_type don't work. */ + assert(sizeof(char) =3D=3D 1); if (opt_help) { fprintf(stderr, "\n"); fprintf(stderr, "Valid options for the MPIWRAP_DEBUG environmen= t" @@ -224,82 +230,186 @@ return r1 =3D=3D r2; } =20 +static long extentOfTy ( MPI_Datatype ty ) +{ + int r; + MPI_Aint n; + r =3D PMPI_Type_extent(ty, &n); + assert(r =3D=3D MPI_SUCCESS); + return (long)n; +} =20 +/* 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; + + r =3D PMPI_Type_get_envelope( *ty, &n_ints, &n_addrs, &n_dtys, &tycon= ); + assert(r =3D=3D MPI_SUCCESS); + + if (tycon !=3D MPI_COMBINER_NAMED) { + r =3D MPI_Type_free(ty); + assert(r =3D=3D MPI_SUCCESS); + } +} + + /*------------------------------------------------------------*/ -/*--- Address-range helpers ---*/ +/*--- Unpicking datatypes ---*/ /*------------------------------------------------------------*/ =20 -/* ---------------- - Do checks on memory areas defined using the MPI (buffer, count, - type) convention. - ---------------- -*/ +static=20 +void walk_type_array ( void(*f)(void*,long), char* base,=20 + MPI_Datatype ty, long count ); =20 -static inline long datasize ( MPI_Datatype datatype ) + +/* 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=20 +void walk_type ( void(*f)(void*,long), char* base, MPI_Datatype ty ) { - if (datatype =3D=3D MPI_INT) return sizeof(signed int); - if (datatype =3D=3D MPI_DOUBLE) return sizeof(double); - if (datatype =3D=3D MPI_CHAR) return sizeof(signed char); - if (datatype =3D=3D MPI_UNSIGNED) return sizeof(unsigned int); - fprintf(stderr, "%s %5d: datasize: unhandled PMPI_Datatype %d\n", - preamble, my_pid, (int)datatype); - return 0; -} + int r, n_ints, n_addrs, n_dtys, tycon; + long ex, count, i; + int* ints =3D NULL; + MPI_Aint* addrs =3D NULL; + MPI_Datatype* dtys =3D NULL; + // MPI_Datatype elemTy; =20 + if (1) {=20 + printf("walk_type %p\n", (void*)ty); + if (ty =3D=3D MPI_DATATYPE_NULL) printf("MPI_DATATYPE_NULL\n"); + else if (ty =3D=3D MPI_BYTE) printf("MPI_BYTE\n"); + else if (ty =3D=3D MPI_PACKED) printf("MPI_PACKED\n"); + else if (ty =3D=3D MPI_CHAR) printf("MPI_CHAR\n"); + else if (ty =3D=3D MPI_SHORT) printf("MPI_SHORT\n"); + else if (ty =3D=3D MPI_INT) printf("MPI_INT\n"); + else if (ty =3D=3D MPI_LONG) printf("MPI_LONG\n"); + else if (ty =3D=3D MPI_FLOAT) printf("MPI_FLOAT\n"); + else if (ty =3D=3D MPI_DOUBLE) printf("MPI_DOUBLE\n"); + else if (ty =3D=3D MPI_LONG_DOUBLE) printf("MPI_LONG_DOUBLE\n"); + else if (ty =3D=3D MPI_UNSIGNED_CHAR) printf("MPI_UNSIGNED_CHAR\n"= ); + else if (ty =3D=3D MPI_UNSIGNED_SHORT) printf("MPI_UNSIGNED_SHORT\= n"); + else if (ty =3D=3D MPI_UNSIGNED_LONG) printf("MPI_UNSIGNED_LONG\n"= ); + else if (ty =3D=3D MPI_UNSIGNED) printf("MPI_UNSIGNED\n"); + else if (ty =3D=3D MPI_FLOAT_INT) printf("MPI_FLOAT_INT\n"); + else if (ty =3D=3D MPI_DOUBLE_INT) printf("MPI_DOUBLE_INT\n"); + else if (ty =3D=3D MPI_LONG_DOUBLE_INT) printf("MPI_LONG_DOUBLE_IN= T\n"); + else if (ty =3D=3D MPI_LONG_INT) printf("MPI_LONG_INT\n"); + else if (ty =3D=3D MPI_SHORT_INT) printf("MPI_SHORT_INT\n"); + else if (ty =3D=3D MPI_2INT) printf("MPI_2INT\n"); + else if (ty =3D=3D MPI_UB) printf("MPI_UB\n"); + else if (ty =3D=3D MPI_LB) printf("MPI_LB\n"); + else if (ty =3D=3D MPI_WCHAR) printf("MPI_WCHAR\n"); + else if (ty =3D=3D MPI_LONG_LONG_INT) printf("MPI_LONG_LONG_INT\n"= ); + else if (ty =3D=3D MPI_LONG_LONG) printf("MPI_LONG_LONG\n"); + else if (ty =3D=3D MPI_UNSIGNED_LONG_LONG) printf("MPI_UNSIGNED_LO= NG_LONG\n"); + else printf("???\n"); + } + assert(ty !=3D MPI_DATATYPE_NULL); =20 -/* Check that the specified area is both addressible and contains - initialised data, and cause V to complain if not. */ + r =3D MPI_Type_get_envelope( ty, &n_ints, &n_addrs, &n_dtys, &tycon )= ; + assert(r =3D=3D MPI_SUCCESS); =20 -static -void check_readable ( void *buffer, long count, MPI_Datatype datatype ) -{ - long nbytes =3D count * datasize(datatype); - if (nbytes > 0) { - VALGRIND_CHECK_READABLE(buffer, nbytes); + /* Handle the base cases fast(er/ish). */ + if (tycon =3D=3D MPI_COMBINER_NAMED) { + if (ty =3D=3D MPI_DOUBLE) { f(base,sizeof(double)); return; } + if (ty =3D=3D MPI_INT) { f(base,sizeof(signed int)); return; = } + if (ty =3D=3D MPI_CHAR) { f(base,sizeof(signed char)); return;= } + if (ty =3D=3D MPI_UNSIGNED) { f(base,sizeof(unsigned int)); return= ; } + goto unhandled; + /*NOTREACHED*/ } -} =20 + if (1) { + ex =3D extentOfTy(ty); + printf("tycon %p %d %d %d (ext %d)\n", + (void*)tycon, n_ints, n_addrs, n_dtys, (int)ex ); + } =20 -/* 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 >=3D 0); + assert(n_addrs >=3D 0); + assert(n_dtys >=3D 0); =20 -static -void check_writable ( void *buffer, long count, MPI_Datatype datatype ) -{ - long nbytes =3D count * datasize(datatype); - if (nbytes > 0) { - VALGRIND_CHECK_WRITABLE(buffer, nbytes); + if (n_ints > 0) { + ints =3D malloc(n_ints * sizeof(int)); + assert(ints); } -} + if (n_addrs > 0) { + addrs =3D malloc(n_addrs * sizeof(MPI_Aint)); + assert(addrs); + } + if (n_dtys > 0) { + dtys =3D malloc(n_dtys * sizeof(MPI_Datatype)); + assert(dtys); + } =20 + r =3D MPI_Type_get_contents( ty, n_ints, n_addrs, n_dtys, + ints, addrs, dtys ); + assert(r =3D=3D MPI_SUCCESS); =20 -/* Set the specified area to 'addressible and defined' (safe-to-read) - state. */ + switch (tycon) { =20 -static -void make_readable ( void *buffer, int count, MPI_Datatype datatype ) -{ - long nbytes =3D count * datasize(datatype); - if (nbytes > 0) { - VALGRIND_MAKE_READABLE(buffer, nbytes); + case MPI_COMBINER_CONTIGUOUS: + assert(n_ints =3D=3D 1 && n_addrs =3D=3D 0 && n_dtys =3D=3D 1); + walk_type_array( f, base, dtys[0], ints[0] ); + maybeFreeTy( &dtys[0] ); + break; + + case MPI_COMBINER_STRUCT: + assert(n_addrs =3D=3D n_ints-1); + assert(n_dtys =3D=3D n_ints-1); + for (i =3D 0; i < ints[0]; i++) { + printf("struct (elem %d limit %d) off %d copies %d\n",=20 + (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 =3D=3D 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); } =20 -static -void=20 -make_readable_if_success ( int err, void *buffer, int count,=20 - MPI_Datatype datatype ) + +/* Same as walk_type but apply 'f' to every element in an array + of 'count' items starting at 'base'. */ +static=20 +void walk_type_array ( void(*f)(void*,long), char* base,=20 + MPI_Datatype elemTy, long count ) { - if (err =3D=3D MPI_SUCCESS) { - long nbytes =3D count * datasize(datatype); - if (nbytes > 0) { - VALGRIND_MAKE_READABLE(buffer, nbytes); - } - } + long i, ex; + ex =3D extentOfTy(elemTy); + for (i =3D 0; i < count; i++) + walk_type( f, base + i * ex, elemTy ); } =20 =20 +/*------------------------------------------------------------*/ +/*--- Address-range helpers ---*/ +/*------------------------------------------------------------*/ + /* ---------------- Do corresponding checks on memory areas defined using a=20 straightforward (start, length) description. @@ -351,6 +461,52 @@ } =20 =20 +/* ---------------- + 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=20 +make_readable_if_success ( int err, void *buffer, int count,=20 + MPI_Datatype datatype ) +{ + if (err =3D=3D MPI_SUCCESS) + make_readable(buffer, count, datatype); +} + + /*------------------------------------------------------------*/ /*--- ---*/ /*--- The wrappers proper. They are listed in the order ---*/ @@ -1236,10 +1392,10 @@ 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 @@ 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) =20 //UNIMPLEMENTED_WRAPPER(Type_struct) NO_OP_WRAPPER(Type_struct) =20 -UNIMPLEMENTED_WRAPPER(Type_ub) +NO_OP_WRAPPER(Type_ub) UNIMPLEMENTED_WRAPPER(Type_vector) UNIMPLEMENTED_WRAPPER(Unpack) =20 |