From 1e4199ee612c43a2d8129c87dbae8e1179b7e505 Mon Sep 17 00:00:00 2001 From: George Bosilca Date: Tue, 20 Jun 2006 14:19:44 +0000 Subject: [PATCH] Add more datatype tests. One to check all communications to self, it is used to compute the overhead of the convertor (and all convertor related operations). The second will check the position setting on the convertor. Not yet completed ... This commit was SVN r10432. --- test/datatype/Makefile.am | 10 +- test/datatype/position.c | 20 ++ test/datatype/to_self.c | 399 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 428 insertions(+), 1 deletion(-) create mode 100644 test/datatype/position.c create mode 100644 test/datatype/to_self.c diff --git a/test/datatype/Makefile.am b/test/datatype/Makefile.am index e62cb15f53..a0ec7f611b 100644 --- a/test/datatype/Makefile.am +++ b/test/datatype/Makefile.am @@ -9,7 +9,7 @@ # $HEADER$ # -check_PROGRAMS = ddt_test checksum +check_PROGRAMS = ddt_test checksum position to_self TESTS = $(check_PROGRAMS) @@ -20,3 +20,11 @@ ddt_test_LDADD = $(top_builddir)/ompi/libmpi.la checksum_SOURCES = checksum.c checksum_LDFLAGS = $(WRAPPER_EXTRA_LDFLAGS) checksum_LDADD = $(top_builddir)/ompi/libmpi.la + +position_SOURCES = position.c +position_LDFLAGS = $(WRAPPER_EXTRA_LDFLAGS) +position_LDADD = $(top_builddir)/ompi/libmpi.la + +to_self_SOURCES = to_self.c +to_self_LDFLAGS = $(WRAPPER_EXTRA_LDFLAGS) +to_self_LDADD = $(top_builddir)/ompi/libmpi.la diff --git a/test/datatype/position.c b/test/datatype/position.c new file mode 100644 index 0000000000..80dbf786b5 --- /dev/null +++ b/test/datatype/position.c @@ -0,0 +1,20 @@ +/* -*- Mode: C; c-basic-offset:4 ; -*- */ +/* + * Copyright (c) 2004-2006 The University of Tennessee and The University + * of Tennessee Research Foundation. All rights + * reserved. + * $COPYRIGHT$ + * + * Additional copyrights may follow + * + * $HEADER$ + */ + +#include "ompi_config.h" +#include "ompi/datatype/convertor.h" +#include "ompi/datatype/datatype.h" + +int main( int argc, char* argv[] ) +{ + return 0; +} diff --git a/test/datatype/to_self.c b/test/datatype/to_self.c new file mode 100644 index 0000000000..150290ba61 --- /dev/null +++ b/test/datatype/to_self.c @@ -0,0 +1,399 @@ +/* -*- Mode: C; c-basic-offset:4 ; -*- */ +/* + * Copyright (c) 2004-2006 The University of Tennessee and The University + * of Tennessee Research Foundation. All rights + * reserved. + * $COPYRIGHT$ + * + * Additional copyrights may follow + * + * $HEADER$ + */ + +#include "mpi.h" + +#include +#include +#include + +#ifdef HAVE_OPEN_MPI +#include "ompi_config.h" +#include "ompi/datatype/convertor.h" +#include "ompi/datatype/datatype.h" +#include "ompi/datatype/convertor_internal.h" +#include "ompi/datatype/datatype_internal.h" +#define MPI_DDT_DUMP(ddt) ompi_ddt_dump( (ddt) ) +#else +#define MPI_DDT_DUMP(ddt) +#endif /* OPEN_MPI */ + +/* Create a datatype similar to the one use by HPL */ +static MPI_Datatype +create_indexed_constant_gap_ddt( int number, /* number of repetitions */ + int contig_size, /* number of elements in a contiguous chunk */ + int gap_size ) /* number of elements in a gap */ +{ + MPI_Datatype dt, *types; + int i, *bLength; + MPI_Aint* displ; + + types = (MPI_Datatype*)malloc( sizeof(MPI_Datatype) * number ); + bLength = (int*)malloc( sizeof(int) * number ); + displ = (MPI_Aint*)malloc( sizeof(MPI_Aint) * number ); + + types[0] = MPI_DOUBLE; + bLength[0] = contig_size; + displ[0] = 0; + for( i = 1; i < number; i++ ) { + types[i] = MPI_DOUBLE; + bLength[i] = contig_size; + displ[i] = displ[i-1] + sizeof(double) * (contig_size + gap_size); + } + MPI_Type_struct( number, bLength, displ, types, &dt ); + MPI_DDT_DUMP( dt ); + free(types); + free(bLength); + free(displ); + MPI_Type_commit( &dt ); + return dt; +} + +static MPI_Datatype +create_optimized_indexed_constant_gap_ddt( int number, /* number of repetitions */ + int contig_size, /* number of elements in a contiguous chunk */ + int gap_size ) /* number of elements in a gap */ +{ + MPI_Datatype dt; + + MPI_Type_vector( number, contig_size, (contig_size + gap_size), MPI_DOUBLE, &dt ); + MPI_Type_commit( &dt ); + MPI_DDT_DUMP( dt ); + return dt; +} + +typedef struct { + int i[2]; + float f; +} internal_struct; +typedef struct { + int v1; + int gap1; + internal_struct is[3]; +} ddt_gap; + +static MPI_Datatype +create_indexed_gap_ddt( void ) +{ + ddt_gap dt[2]; + MPI_Datatype dt1, dt2, dt3; + int bLength[2] = { 2, 1 }; + MPI_Datatype types[2] = { MPI_INT, MPI_FLOAT }; + MPI_Aint displ[2]; + + MPI_Address( &(dt[0].is[0].i[0]), &(displ[0]) ); + MPI_Address( &(dt[0].is[0].f), &(displ[1]) ); + displ[1] -= displ[0]; + displ[0] -= displ[0]; + MPI_Type_struct( 2, bLength, displ, types, &dt1 ); + /*MPI_DDT_DUMP( dt1 );*/ + MPI_Type_contiguous( 3, dt1, &dt2 ); + /*MPI_DDT_DUMP( dt2 );*/ + bLength[0] = 1; + bLength[1] = 1; + MPI_Address( &(dt[0].v1), &(displ[0]) ); + MPI_Address( &(dt[0].is[0]), &(displ[1]) ); + displ[1] -= displ[0]; + displ[0] -= displ[0]; + types[0] = MPI_INT; + types[1] = dt2; + MPI_Type_struct( 2, bLength, displ, types, &dt3 ); + /*MPI_DDT_DUMP( dt3 );*/ + MPI_Type_free( &dt1 ); + MPI_Type_free( &dt2 ); + MPI_Type_contiguous( 10, dt3, &dt1 ); + MPI_DDT_DUMP( dt1 ); + MPI_Type_free( &dt3 ); + MPI_Type_commit( &dt1 ); + return dt1; +} + +static MPI_Datatype +create_indexed_gap_optimized_ddt( void ) +{ + MPI_Datatype dt1, dt2, dt3; + int bLength[3]; + MPI_Datatype types[3]; + MPI_Aint displ[3]; + + MPI_Type_contiguous( 40, MPI_BYTE, &dt1 ); + MPI_Type_create_resized( dt1, 0, 44, &dt2 ); + + bLength[0] = 4; + bLength[1] = 9; + bLength[2] = 36; + + types[0] = MPI_BYTE; + types[1] = dt2; + types[2] = MPI_BYTE; + + displ[0] = 0; + displ[1] = 8; + displ[2] = 44 * 9 + 8; + + MPI_Type_struct( 3, bLength, displ, types, &dt3 ); + + MPI_Type_free( &dt1 ); + MPI_Type_free( &dt2 ); + MPI_DDT_DUMP( dt3 ); + MPI_Type_commit( &dt3 ); + return dt3; +} + +static void print_result( int length, int cycles, double time ) +{ + double bandwidth, clock_prec; + + clock_prec = MPI_Wtick(); + bandwidth = (length * clock_prec * cycles) / (1024.0 * 1024.0) / (time * clock_prec); + printf( "%8d\t%.6f\t%.4f MB/s\n", length, time / cycles, bandwidth ); +} + +static int isend_recv( int cycles, + MPI_Datatype sdt, int scount, void* sbuf, + MPI_Datatype rdt, int rcount, void* rbuf ) +{ + int sres, rres, myself, tag = 0, i, slength, rlength; + MPI_Status status; + MPI_Request req; + double tstart, tend; + + MPI_Type_size( sdt, &slength ); + slength *= scount; + MPI_Type_size( rdt, &rlength ); + rlength *= rcount; + + MPI_Comm_rank( MPI_COMM_WORLD, &myself ); + + tstart = MPI_Wtime(); + for( i = 0; i < cycles; i++ ) { +#ifndef FAST + sres = MPI_Isend( sbuf, scount, sdt, myself, tag, MPI_COMM_WORLD, &req ); + rres = MPI_Recv( rbuf, rcount, rdt, myself, tag, MPI_COMM_WORLD, &status ); + MPI_Wait( &req, &status ); + /*MPI_Request_free( &req );*/ +#else + sres = ftmpi_mpi_isend( sbuf, scount, sdt, myself, tag, MPI_COMM_WORLD, &req ); + rres = ftmpi_mpi_recv( rbuf, rcount, rdt, myself, tag, MPI_COMM_WORLD, &status ); + ftmpi_request_free( &req ); +#endif + } + tend = MPI_Wtime(); + print_result( rlength, cycles, tend - tstart ); + return 0; +} + +static int irecv_send( int cycles, + MPI_Datatype sdt, int scount, void* sbuf, + MPI_Datatype rdt, int rcount, void* rbuf ) +{ + int sres, rres, myself, tag = 0, i, slength, rlength; + MPI_Request req; + MPI_Status status; + double tstart, tend; + + MPI_Type_size( sdt, &slength ); + slength *= scount; + MPI_Type_size( rdt, &rlength ); + rlength *= rcount; + + MPI_Comm_rank( MPI_COMM_WORLD, &myself ); + + tstart = MPI_Wtime(); + for( i = 0; i < cycles; i++ ) { +#ifndef FAST + rres = MPI_Irecv( rbuf, rcount, rdt, myself, tag, MPI_COMM_WORLD, &req ); + sres = MPI_Send( sbuf, scount, sdt, myself, tag, MPI_COMM_WORLD ); + MPI_Wait( &req, &status ); + /*MPI_Request_free( &req );*/ +#else + rres = ftmpi_mpi_irecv( rbuf, rcount, rdt, myself, tag, MPI_COMM_WORLD, &req ); + sres = ftmpi_mpi_send( sbuf, scount, sdt, myself, tag, MPI_COMM_WORLD ); + ftmpi_request_free( &req ); +#endif + } + tend = MPI_Wtime(); + print_result( rlength, cycles, tend - tstart ); + return 0; +} + +static int isend_irecv_wait( int cycles, + MPI_Datatype sdt, int scount, void* sbuf, + MPI_Datatype rdt, int rcount, void* rbuf ) +{ + int sres, rres, myself, tag = 0, i, slength, rlength; + MPI_Request sreq, rreq; + MPI_Status status; + double tstart, tend; + + MPI_Type_size( sdt, &slength ); + slength *= scount; + MPI_Type_size( rdt, &rlength ); + rlength *= rcount; + + MPI_Comm_rank( MPI_COMM_WORLD, &myself ); + + tstart = MPI_Wtime(); + for( i = 0; i < cycles; i++ ) { +#ifndef FAST + sres = MPI_Isend( sbuf, scount, sdt, myself, tag, MPI_COMM_WORLD, &sreq ); + rres = MPI_Irecv( rbuf, rcount, rdt, myself, tag, MPI_COMM_WORLD, &rreq ); + MPI_Wait( &sreq, &status ); + MPI_Wait( &rreq, &status ); + /*MPI_Request_free( &sreq );*/ + /*MPI_Request_free( &rreq );*/ +#else + sres = ftmpi_mpi_isend( sbuf, scount, sdt, myself, tag, MPI_COMM_WORLD, &sreq ); + rres = ftmpi_mpi_irecv( rbuf, rcount, rdt, myself, tag, MPI_COMM_WORLD, &rreq ); + ftmpi_wait( &sreq, &status ); + ftmpi_request_free( &sreq ); + ftmpi_request_free( &rreq ); +#endif + } + tend = MPI_Wtime(); + print_result( rlength, cycles, tend - tstart ); + return 0; +} + +static int irecv_isend_wait( int cycles, + MPI_Datatype sdt, int scount, void* sbuf, + MPI_Datatype rdt, int rcount, void* rbuf ) +{ + int sres, rres, myself, tag = 0, i, slength, rlength; + MPI_Request sreq, rreq; + MPI_Status status; + double tstart, tend; + + MPI_Type_size( sdt, &slength ); + slength *= scount; + MPI_Type_size( rdt, &rlength ); + rlength *= rcount; + + MPI_Comm_rank( MPI_COMM_WORLD, &myself ); + + tstart = MPI_Wtime(); + for( i = 0; i < cycles; i++ ) { +#ifndef FAST + rres = MPI_Irecv( rbuf, rcount, rdt, myself, tag, MPI_COMM_WORLD, &rreq ); + sres = MPI_Isend( sbuf, scount, sdt, myself, tag, MPI_COMM_WORLD, &sreq ); + MPI_Wait( &sreq, &status ); + MPI_Wait( &rreq, &status ); + /*MPI_Request_free( &sreq );*/ + /*MPI_Request_free( &rreq );*/ +#else + rres = ftmpi_mpi_irecv( rbuf, rcount, rdt, myself, tag, MPI_COMM_WORLD, &rreq ); + sres = ftmpi_mpi_isend( sbuf, scount, sdt, myself, tag, MPI_COMM_WORLD, &sreq ); + ftmpi_wait( &sreq, &status ); + ftmpi_request_free( &sreq ); + ftmpi_request_free( &rreq ); +#endif + } + tend = MPI_Wtime(); + print_result( rlength, cycles, tend - tstart ); + return 0; +} + +static int do_test_for_ddt( MPI_Datatype sddt, MPI_Datatype rddt, int length ) +{ + int i; + MPI_Aint extent; + char *sbuf, *rbuf; + + MPI_Type_extent( sddt, &extent ); + sbuf = (char*)malloc( length ); + rbuf = (char*)malloc( length ); + printf( "# Isend recv\n" ); + for( i = 1; i <= (length/extent); i *= 2 ) { + isend_recv( 10, sddt, i, sbuf, rddt, i, rbuf ); + } + printf( "# Irecv send\n" ); + for( i = 1; i <= (length/extent); i *= 2 ) { + irecv_send( 10, sddt, i, sbuf, rddt, i, rbuf ); + } + printf( "# Irecv Isend Wait\n" ); + for( i = 1; i <= (length/extent); i *= 2 ) { + irecv_isend_wait( 10, sddt, i, sbuf, rddt, i, rbuf ); + } + printf( "# Irecv Isend Wait\n" ); + for( i = 1; i <= (length/extent); i *= 2 ) { + isend_irecv_wait( 10, sddt, i, sbuf, rddt, i, rbuf ); + } + free( sbuf ); + free( rbuf ); + return 0; +} + +#define DO_CONTIG 0x01 +#define DO_CONSTANT_GAP 0x02 +#define DO_INDEXED_GAP 0x04 +#define DO_OPTIMIZED_INDEXED_GAP 0x08 + +int main( int argc, char* argv[] ) +{ + int rc; + int length = 1024 * 1024; + int rank, size; + MPI_Datatype ddt; + int run_tests = DO_CONTIG | DO_CONSTANT_GAP | DO_INDEXED_GAP | DO_OPTIMIZED_INDEXED_GAP; + /*int run_tests = DO_CONSTANT_GAP;*/ + + rc = MPI_Init (&argc, &argv); + + rc = MPI_Comm_rank (MPI_COMM_WORLD, &rank); + rc = MPI_Comm_size (MPI_COMM_WORLD, &size); + + if( rank != 0 ) { + MPI_Finalize(); + exit(0); + } + + if( run_tests & DO_CONTIG ) { + printf( "\ncontiguous datatype\n\n" ); + do_test_for_ddt( MPI_INT, MPI_INT, length ); + } + + if( run_tests & DO_INDEXED_GAP ) { + printf( "\nindexed gap\n\n" ); + ddt = create_indexed_gap_ddt(); + /*MPI_DDT_DUMP( ddt );*/ + do_test_for_ddt( ddt, ddt, length ); + MPI_Type_free( &ddt ); + } + + if( run_tests & DO_OPTIMIZED_INDEXED_GAP ) { + printf( "\noptimized indexed gap\n\n" ); + ddt = create_indexed_gap_optimized_ddt(); + /*MPI_DDT_DUMP( ddt );*/ + do_test_for_ddt( ddt, ddt, length ); + MPI_Type_free( &ddt ); + } + + if( run_tests & DO_CONSTANT_GAP ) { + printf( "\nconstant indexed gap\n\n" ); + ddt = create_indexed_constant_gap_ddt( 80, 100, 1 ); + /*MPI_DDT_DUMP( ddt );*/ + do_test_for_ddt( ddt, ddt, length ); + MPI_Type_free( &ddt ); + } + + if( run_tests & DO_CONSTANT_GAP ) { + printf( "\noptimized constant indexed gap\n\n" ); + ddt = create_optimized_indexed_constant_gap_ddt( 80, 100, 1 ); + /*MPI_DDT_DUMP( ddt );*/ + do_test_for_ddt( ddt, ddt, length ); + MPI_Type_free( &ddt ); + } + + MPI_Finalize (); + exit(0); +} +