From: Augustin Degomme Date: Wed, 12 Mar 2014 09:35:58 +0000 (+0100) Subject: add mpich3 topo tests X-Git-Tag: v3_11~105^2~6 X-Git-Url: http://info.iut-bm.univ-fcomte.fr/pub/gitweb/simgrid.git/commitdiff_plain/3b578f744282579b374a1461561b41f2d8b2684b?ds=sidebyside add mpich3 topo tests They are not built or run for now, because features are not yet implemented --- diff --git a/buildtools/Cmake/DefinePackages.cmake b/buildtools/Cmake/DefinePackages.cmake index b2d079e437..3cda3678e7 100644 --- a/buildtools/Cmake/DefinePackages.cmake +++ b/buildtools/Cmake/DefinePackages.cmake @@ -956,6 +956,7 @@ set(TESHSUITE_CMAKEFILES_TXT teshsuite/smpi/mpich3-test/coll/CMakeLists.txt teshsuite/smpi/mpich3-test/datatype/CMakeLists.txt teshsuite/smpi/mpich3-test/group/CMakeLists.txt + teshsuite/smpi/mpich3-test/topo/CMakeLists.txt teshsuite/smpi/mpich3-test/init/CMakeLists.txt teshsuite/smpi/mpich3-test/pt2pt/CMakeLists.txt teshsuite/smpi/mpich3-test/f77/util/CMakeLists.txt diff --git a/buildtools/Cmake/MakeExe.cmake b/buildtools/Cmake/MakeExe.cmake index c854fb5580..72ec2fc407 100644 --- a/buildtools/Cmake/MakeExe.cmake +++ b/buildtools/Cmake/MakeExe.cmake @@ -97,6 +97,7 @@ add_subdirectory(${CMAKE_HOME_DIRECTORY}/teshsuite/smpi/mpich3-test/coll) add_subdirectory(${CMAKE_HOME_DIRECTORY}/teshsuite/smpi/mpich3-test/comm) add_subdirectory(${CMAKE_HOME_DIRECTORY}/teshsuite/smpi/mpich3-test/datatype) add_subdirectory(${CMAKE_HOME_DIRECTORY}/teshsuite/smpi/mpich3-test/group) +add_subdirectory(${CMAKE_HOME_DIRECTORY}/teshsuite/smpi/mpich3-test/topo) add_subdirectory(${CMAKE_HOME_DIRECTORY}/teshsuite/smpi/mpich3-test/init) add_subdirectory(${CMAKE_HOME_DIRECTORY}/teshsuite/smpi/mpich3-test/pt2pt) diff --git a/teshsuite/smpi/mpich3-test/topo/CMakeLists.txt b/teshsuite/smpi/mpich3-test/topo/CMakeLists.txt new file mode 100644 index 0000000000..6bc6b43270 --- /dev/null +++ b/teshsuite/smpi/mpich3-test/topo/CMakeLists.txt @@ -0,0 +1,87 @@ +cmake_minimum_required(VERSION 2.6) + +if(enable_smpi AND enable_smpi_MPICH3_testsuite) + if(WIN32) + set(CMAKE_C_FLAGS "-include ${CMAKE_HOME_DIRECTORY}/include/smpi/smpi_main.h") + else() + set(CMAKE_C_COMPILER "${CMAKE_BINARY_DIR}/smpi_script/bin/smpicc") + set(CMAKE_Fortran_COMPILER "${CMAKE_BINARY_DIR}/smpi_script/bin/smpiff") + endif() + + set(EXECUTABLE_OUTPUT_PATH "${CMAKE_CURRENT_BINARY_DIR}") + include_directories("${CMAKE_HOME_DIRECTORY}/include/smpi") + include_directories("${CMAKE_CURRENT_SOURCE_DIR}/../include/") + + +# add_executable(cartcreates cartcreates.c) +# add_executable(cartmap1 cartmap1.c) +# add_executable(cartshift1 cartshift1.c) +# add_executable(cartsuball cartsuball.c) +# add_executable(cartzero cartzero.c) +# add_executable(dgraph_unwgt dgraph_unwgt.c) +# add_executable(dims1 dims1.c) +# add_executable(dims2 dims2.c) +# add_executable(distgraph1 distgraph1.c) +# add_executable(graphcr2 graphcr2.c) +# add_executable(graphcr graphcr.c) +# add_executable(graphmap1 graphmap1.c) +# add_executable(neighb_coll neighb_coll.c) +# add_executable(topodup topodup.c) +# add_executable(topotest topotest.c) + + +# target_link_libraries(cartcreates simgrid mtest_c) +# target_link_libraries(cartmap1 simgrid mtest_c) +# target_link_libraries(cartshift1 simgrid mtest_c) +# target_link_libraries(cartsuball simgrid mtest_c) +# target_link_libraries(cartzero simgrid mtest_c) +# target_link_libraries(dgraph_unwgt simgrid mtest_c) +# target_link_libraries(dims1 simgrid mtest_c) +# target_link_libraries(dims2 simgrid mtest_c) +# target_link_libraries(distgraph1 simgrid mtest_c) +# target_link_libraries(graphcr2 simgrid mtest_c) +# target_link_libraries(graphcr simgrid mtest_c) +# target_link_libraries(graphmap1 simgrid mtest_c) +# target_link_libraries(neighb_coll simgrid mtest_c) +# target_link_libraries(topodup simgrid mtest_c) +# target_link_libraries(topotest simgrid mtest_c) + +endif() + +set(tesh_files + ${tesh_files} + PARENT_SCOPE + ) +set(xml_files + ${xml_files} + PARENT_SCOPE + ) +set(examples_src + ${examples_src} + ${CMAKE_CURRENT_SOURCE_DIR}/cartcreates.c + ${CMAKE_CURRENT_SOURCE_DIR}/cartmap1.c + ${CMAKE_CURRENT_SOURCE_DIR}/cartshift1.c + ${CMAKE_CURRENT_SOURCE_DIR}/cartsuball.c + ${CMAKE_CURRENT_SOURCE_DIR}/cartzero.c + ${CMAKE_CURRENT_SOURCE_DIR}/dgraph_unwgt.c + ${CMAKE_CURRENT_SOURCE_DIR}/dims1.c + ${CMAKE_CURRENT_SOURCE_DIR}/dims2.c + ${CMAKE_CURRENT_SOURCE_DIR}/distgraph1.c + ${CMAKE_CURRENT_SOURCE_DIR}/graphcr2.c + ${CMAKE_CURRENT_SOURCE_DIR}/graphcr.c + ${CMAKE_CURRENT_SOURCE_DIR}/graphmap1.c + ${CMAKE_CURRENT_SOURCE_DIR}/neighb_coll.c + ${CMAKE_CURRENT_SOURCE_DIR}/testlist + ${CMAKE_CURRENT_SOURCE_DIR}/topodup.c + ${CMAKE_CURRENT_SOURCE_DIR}/topotest.c + PARENT_SCOPE + ) +set(bin_files + ${bin_files} + PARENT_SCOPE + ) +set(txt_files + ${txt_files} + ${CMAKE_CURRENT_SOURCE_DIR}/testlist + PARENT_SCOPE + ) diff --git a/teshsuite/smpi/mpich3-test/topo/cartcreates.c b/teshsuite/smpi/mpich3-test/topo/cartcreates.c new file mode 100644 index 0000000000..92365d7f01 --- /dev/null +++ b/teshsuite/smpi/mpich3-test/topo/cartcreates.c @@ -0,0 +1,54 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * (C) 2003 by Argonne National Laboratory. + * See COPYRIGHT in top-level directory. + */ +#include "mpi.h" +#include +#include "mpitest.h" + +int main( int argc, char *argv[] ) +{ + int errs = 0; + int size, rank; + int dims[2], periods[2]; + MPI_Comm comm; + + MTest_Init( &argc, &argv ); + + /* Create a new cartesian communicator in a subset of the processes */ + MPI_Comm_size( MPI_COMM_WORLD, &size ); + MPI_Comm_rank( MPI_COMM_WORLD, &rank ); + if (size < 2) { + fprintf( stderr, "This test needs at least 2 processes\n" ); + MPI_Abort( MPI_COMM_WORLD, 1 ); + } + dims[0] = size-1; + periods[0] = 1; + MPI_Cart_create( MPI_COMM_WORLD, 1, dims, periods, 0, &comm ); + + if (comm != MPI_COMM_NULL) { + int csize; + MPI_Comm_size( comm, &csize ); + if (csize != dims[0]) { + errs++; + fprintf( stderr, + "Sizes is wrong in cart communicator. Is %d, should be %d\n", + csize, dims[0] ); + } + MPI_Barrier( comm ); + + MPI_Comm_free( &comm ); + } + else if (rank < dims[0]) { + errs++; + fprintf( stderr, "Communicator returned is null!" ); + } + + MTest_Finalize( errs ); + + MPI_Finalize(); + + return 0; +} diff --git a/teshsuite/smpi/mpich3-test/topo/cartmap1.c b/teshsuite/smpi/mpich3-test/topo/cartmap1.c new file mode 100644 index 0000000000..1ce5ad8d89 --- /dev/null +++ b/teshsuite/smpi/mpich3-test/topo/cartmap1.c @@ -0,0 +1,64 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * (C) 2003 by Argonne National Laboratory. + * See COPYRIGHT in top-level directory. + */ +#include "mpi.h" +#include +#include "mpitest.h" + +int main( int argc, char *argv[] ) +{ + int errs = 0; + int dims[2]; + int periods[2]; + int size, rank, newrank; + + MTest_Init( &argc, &argv ); + + MPI_Comm_size( MPI_COMM_WORLD, &size ); + MPI_Comm_rank( MPI_COMM_WORLD, &rank ); + + /* This defines a one dimensional cartision grid with a single point */ + periods[0] = 1; + dims[0] = 1; + + MPI_Cart_map( MPI_COMM_WORLD, 1, dims, periods, &newrank ); + if (rank > 0) { + if (newrank != MPI_UNDEFINED) { + errs++; + printf( "rank outside of input communicator not UNDEFINED\n" ); + } + } + else { + if (rank != newrank) { + errs++; + printf( "Newrank not defined and should be 0\n" ); + } + } + + + /* As of MPI 2.1, a 0-dimensional topology is valid (its also a + point) */ + MPI_Cart_map( MPI_COMM_WORLD, 0, dims, periods, &newrank ); + if (rank > 0) { + if (newrank != MPI_UNDEFINED) { + errs++; + printf( "rank outside of input communicator not UNDEFINED\n" ); + } + } + else { + /* rank == 0 */ + if (rank != newrank) { + errs++; + printf( "Newrank not defined and should be 0\n" ); + } + } + + + MTest_Finalize( errs ); + MPI_Finalize(); + return 0; + +} diff --git a/teshsuite/smpi/mpich3-test/topo/cartshift1.c b/teshsuite/smpi/mpich3-test/topo/cartshift1.c new file mode 100644 index 0000000000..679f12c18c --- /dev/null +++ b/teshsuite/smpi/mpich3-test/topo/cartshift1.c @@ -0,0 +1,96 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * (C) 2003 by Argonne National Laboratory. + * See COPYRIGHT in top-level directory. + */ +#include "mpi.h" +#include +#include "mpitest.h" + +int main( int argc, char *argv[] ) +{ + int errs = 0; + int size, rank; + int source, dest; + int dims[2], periods[2]; + MPI_Comm comm; + + MTest_Init( &argc, &argv ); + + MPI_Comm_size( MPI_COMM_WORLD, &size ); + MPI_Comm_rank( MPI_COMM_WORLD, &rank ); + dims[0] = size; + periods[0] = 1; + MPI_Cart_create( MPI_COMM_WORLD, 1, dims, periods, 0, &comm ); + MPI_Cart_shift( comm, 0, 1, &source, &dest ); + if (source != ((rank - 1 + size) % size)) { + errs++; + printf( "source for shift 1 is %d\n", source ); + } + if (dest != ((rank + 1) % size)) { + errs++; + printf( "dest for shift 1 is %d\n", dest ); + } + MPI_Cart_shift( comm, 0, 0, &source, &dest ); + if (source != rank) { + errs++; + printf( "Source for shift 0 is %d\n", source ); + } + if (dest != rank) { + errs++; + printf( "Dest for shift 0 is %d\n", dest ); + } + MPI_Cart_shift( comm, 0, -1, &source, &dest ); + if (source != ((rank + 1) % size)) { + errs++; + printf( "source for shift -1 is %d\n", source ); + } + if (dest != ((rank - 1 + size) % size)) { + errs++; + printf( "dest for shift -1 is %d\n", dest ); + } + + /* Now, with non-periodic */ + MPI_Comm_free( &comm ); + periods[0] = 0; + MPI_Cart_create( MPI_COMM_WORLD, 1, dims, periods, 0, &comm ); + MPI_Cart_shift( comm, 0, 1, &source, &dest ); + if ((rank > 0 && source != (rank - 1)) || + (rank == 0 && source != MPI_PROC_NULL)) { + errs++; + printf( "source for non-periodic shift 1 is %d\n", source ); + } + if ((rank < size-1 && dest != rank + 1) || + ((rank == size-1) && dest != MPI_PROC_NULL)) { + errs++; + printf( "dest for non-periodic shift 1 is %d\n", dest ); + } + MPI_Cart_shift( comm, 0, 0, &source, &dest ); + if (source != rank) { + errs++; + printf( "Source for non-periodic shift 0 is %d\n", source ); + } + if (dest != rank) { + errs++; + printf( "Dest for non-periodic shift 0 is %d\n", dest ); + } + MPI_Cart_shift( comm, 0, -1, &source, &dest ); + if ((rank < size - 1 && source != rank + 1) || + (rank == size - 1 && source != MPI_PROC_NULL)) { + + errs++; + printf( "source for non-periodic shift -1 is %d\n", source ); + } + if ((rank > 0 && dest != rank - 1) || + (rank == 0 && dest != MPI_PROC_NULL)) { + errs++; + printf( "dest for non-periodic shift -1 is %d\n", dest ); + } + MPI_Comm_free( &comm ); + + MTest_Finalize( errs ); + MPI_Finalize(); + return 0; + +} diff --git a/teshsuite/smpi/mpich3-test/topo/cartsuball.c b/teshsuite/smpi/mpich3-test/topo/cartsuball.c new file mode 100644 index 0000000000..890db5a633 --- /dev/null +++ b/teshsuite/smpi/mpich3-test/topo/cartsuball.c @@ -0,0 +1,54 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * (C) 2003 by Argonne National Laboratory. + * See COPYRIGHT in top-level directory. + */ +#include "mpi.h" +#include +#include "mpitest.h" + +int main( int argc, char *argv[] ) +{ + int errs = 0; + int size, dims[2], periods[2], remain[2]; + int result, rank; + MPI_Comm comm, newcomm; + + MTest_Init( &argc, &argv ); + + /* First, create a 1-dim cartesian communicator */ + periods[0] = 0; + MPI_Comm_size( MPI_COMM_WORLD, &size ); + dims[0] = size; + MPI_Cart_create( MPI_COMM_WORLD, 1, dims, periods, 0, &comm ); + + /* Now, extract a communicator with no dimensions */ + remain[0] = 0; + MPI_Cart_sub( comm, remain, &newcomm ); + + MPI_Comm_rank(comm, &rank); + + if (rank == 0) { + /* This should be congruent to MPI_COMM_SELF */ + MPI_Comm_compare( MPI_COMM_SELF, newcomm, &result ); + if (result != MPI_CONGRUENT) { + errs++; + printf( "cart sub to size 0 did not give self\n" ); + } + MPI_Comm_free( &newcomm ); + } + else if (newcomm != MPI_COMM_NULL) { + errs++; + printf( "cart sub to size 0 did not give null\n" ); + } + + /* Free the new communicator so that storage leak tests will + be happy */ + MPI_Comm_free( &comm ); + + MTest_Finalize( errs ); + MPI_Finalize(); + return 0; + +} diff --git a/teshsuite/smpi/mpich3-test/topo/cartzero.c b/teshsuite/smpi/mpich3-test/topo/cartzero.c new file mode 100644 index 0000000000..c8e601ee3e --- /dev/null +++ b/teshsuite/smpi/mpich3-test/topo/cartzero.c @@ -0,0 +1,92 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * (C) 2008 by Argonne National Laboratory. + * See COPYRIGHT in top-level directory. + */ +#include "mpi.h" +#include +#include "mpitest.h" + +/* + Check that the MPI implementation properly handles zero-dimensional + Cartesian communicators - the original standard implies that these + should be consistent with higher dimensional topologies and thus + these should work with any MPI implementation. MPI 2.1 made this + requirement explicit. +*/ +int main( int argc, char *argv[] ) +{ + int errs = 0; + int size, rank, ndims; + MPI_Comm comm, newcomm; + + MTest_Init( &argc, &argv ); + + /* Create a new cartesian communicator in a subset of the processes */ + MPI_Comm_size( MPI_COMM_WORLD, &size ); + MPI_Comm_rank( MPI_COMM_WORLD, &rank ); + if (size < 2) { + fprintf( stderr, "This test needs at least 2 processes\n" ); + MPI_Abort( MPI_COMM_WORLD, 1 ); + } + + MPI_Cart_create( MPI_COMM_WORLD, 0, NULL, NULL, 0, &comm ); + + if (comm != MPI_COMM_NULL) { + int csize; + MPI_Comm_size( comm, &csize ); + if (csize != 1) { + errs++; + fprintf( stderr, + "Sizes is wrong in cart communicator. Is %d, should be 1\n", + csize ); + } + + /* This function is not meaningful, but should not fail */ + MPI_Dims_create(1, 0, NULL); + + ndims = -1; + MPI_Cartdim_get(comm, &ndims); + if (ndims != 0) { + errs++; + fprintf(stderr, "MPI_Cartdim_get: ndims is %d, should be 0\n", ndims); + } + + /* this function should not fail */ + MPI_Cart_get(comm, 0, NULL, NULL, NULL); + + MPI_Cart_rank(comm, NULL, &rank); + if (rank != 0) { + errs++; + fprintf(stderr, "MPI_Cart_rank: rank is %d, should be 0\n", rank); + } + + /* this function should not fail */ + MPI_Cart_coords(comm, 0, 0, NULL); + + MPI_Cart_sub(comm, NULL, &newcomm); + ndims = -1; + MPI_Cartdim_get(newcomm, &ndims); + if (ndims != 0) { + errs++; + fprintf(stderr, + "MPI_Cart_sub did not return zero-dimensional communicator\n"); + } + + MPI_Barrier( comm ); + + MPI_Comm_free( &comm ); + MPI_Comm_free( &newcomm ); + } + else if (rank == 0) { + errs++; + fprintf( stderr, "Communicator returned is null!" ); + } + + MTest_Finalize( errs ); + + MPI_Finalize(); + + return 0; +} diff --git a/teshsuite/smpi/mpich3-test/topo/dgraph_unwgt.c b/teshsuite/smpi/mpich3-test/topo/dgraph_unwgt.c new file mode 100644 index 0000000000..e29b3a4275 --- /dev/null +++ b/teshsuite/smpi/mpich3-test/topo/dgraph_unwgt.c @@ -0,0 +1,171 @@ +#include +#include +#include +#include "mpi.h" +#include "mpitest.h" + +#define RING_NUM_NEIGHBORS 2 + +static int validate_dgraph(MPI_Comm dgraph_comm) +{ + int comm_topo; + int src_sz, dest_sz; + int wgt_flag, ierr; + int srcs[RING_NUM_NEIGHBORS], dests[RING_NUM_NEIGHBORS]; + int *src_wgts, *dest_wgts; + + int world_rank, world_size; + int idx, nbr_sep; + + comm_topo = MPI_UNDEFINED; + MPI_Topo_test(dgraph_comm, &comm_topo); + switch (comm_topo) { + case MPI_DIST_GRAPH : + break; + default: + fprintf(stderr, "dgraph_comm is NOT of type MPI_DIST_GRAPH\n"); + return 0; + } + + ierr = MPI_Dist_graph_neighbors_count(dgraph_comm, + &src_sz, &dest_sz, &wgt_flag); + if (ierr != MPI_SUCCESS) { + fprintf(stderr, "MPI_Dist_graph_neighbors_count() fails!\n"); + return 0; + } +/* + else + fprintf(stderr, "MPI_Dist_graph_neighbors_count() succeeds!\n"); +*/ + + if (wgt_flag) { + fprintf(stderr, "dgraph_comm is NOT created with MPI_UNWEIGHTED\n"); + return 0; + } +/* + else + fprintf(stderr, "dgraph_comm is created with MPI_UNWEIGHTED\n"); +*/ + if (src_sz != RING_NUM_NEIGHBORS || dest_sz != RING_NUM_NEIGHBORS) { + fprintf(stderr, "source or destination edge array is not of size %d.\n", + RING_NUM_NEIGHBORS); + fprintf(stderr, "src_sz = %d, dest_sz = %d\n", src_sz, dest_sz); + return 0; + } + + /* + src_wgts and dest_wgts could be anything, e.g. NULL, since + MPI_Dist_graph_neighbors_count() returns MPI_UNWEIGHTED. + Since this program has a Fortran77 version, and standard Fortran77 + has no pointer and NULL, so use MPI_UNWEIGHTED for the weighted arrays. + */ + src_wgts = MPI_UNWEIGHTED; + dest_wgts = MPI_UNWEIGHTED; + ierr = MPI_Dist_graph_neighbors(dgraph_comm, + src_sz, srcs, src_wgts, + dest_sz, dests, dest_wgts); + if (ierr != MPI_SUCCESS) { + fprintf(stderr, "MPI_Dist_graph_neighbors() fails!\n"); + return 0; + } +/* + else + fprintf(stderr, "MPI_Dist_graph_neighbors() succeeds!\n"); +*/ + + /* + Check if the neighbors returned from MPI are really + the nearest neighbors within a ring. + */ + MPI_Comm_size(MPI_COMM_WORLD, &world_size); + MPI_Comm_rank(MPI_COMM_WORLD, &world_rank); + + for (idx=0; idx < src_sz; idx++) { + nbr_sep = abs(srcs[idx] - world_rank); + if ( nbr_sep != 1 && nbr_sep != (world_size-1) ) { + fprintf(stderr, "srcs[%d]=%d is NOT a neighbor of my rank %d.\n", + idx, srcs[idx], world_rank); + return 0; + } + } + for (idx=0; idx < dest_sz; idx++) { + nbr_sep = abs(dests[idx] - world_rank); + if ( nbr_sep != 1 && nbr_sep != (world_size-1) ) { + fprintf(stderr, "dests[%d]=%d is NOT a neighbor of my rank %d.\n", + idx, dests[idx], world_rank); + return 0; + } + } + + /* + fprintf(stderr, "dgraph_comm is of type MPI_DIST_GRAPH " + "of a bidirectional ring.\n"); + */ + return 1; +} + +/* + Specify a distributed graph of a bidirectional ring of the MPI_COMM_WORLD, + i.e. everyone only talks to left and right neighbors. +*/ +int main(int argc, char *argv[]) +{ + MPI_Comm dgraph_comm; + int world_size, world_rank, ierr; + int errs = 0; + + int src_sz, dest_sz; + int degs[1]; + int srcs[RING_NUM_NEIGHBORS], dests[RING_NUM_NEIGHBORS]; + + MTest_Init(&argc, &argv); + MPI_Comm_size(MPI_COMM_WORLD, &world_size); + MPI_Comm_rank(MPI_COMM_WORLD, &world_rank); + + degs[0] = 2; + srcs[0] = world_rank; + dests[0] = world_rank-1 < 0 ? world_size-1 : world_rank-1 ; + dests[1] = world_rank+1 >= world_size ? 0 : world_rank+1 ; + ierr = MPI_Dist_graph_create(MPI_COMM_WORLD, 1, srcs, degs, dests, + MPI_UNWEIGHTED, MPI_INFO_NULL, 1, + &dgraph_comm); + if ( ierr != MPI_SUCCESS ) { + fprintf(stderr, "MPI_Dist_graph_create() fails!\n"); + MPI_Abort(MPI_COMM_WORLD, 1); + return 1; + } + if (!validate_dgraph(dgraph_comm)) { + fprintf(stderr, "MPI_Dist_graph_create() does NOT create " + "a bidirectional ring graph!\n"); + MPI_Abort(MPI_COMM_WORLD, 1); + return 1; + } + MPI_Comm_free(&dgraph_comm); + + src_sz = 2; + srcs[0] = world_rank-1 < 0 ? world_size-1 : world_rank-1 ; + srcs[1] = world_rank+1 >= world_size ? 0 : world_rank+1 ; + dest_sz = 2; + dests[0] = world_rank-1 < 0 ? world_size-1 : world_rank-1 ; + dests[1] = world_rank+1 >= world_size ? 0 : world_rank+1 ; + ierr = MPI_Dist_graph_create_adjacent(MPI_COMM_WORLD, + src_sz, srcs, MPI_UNWEIGHTED, + dest_sz, dests, MPI_UNWEIGHTED, + MPI_INFO_NULL, 1, &dgraph_comm); + if ( ierr != MPI_SUCCESS ) { + fprintf(stderr, "MPI_Dist_graph_create_adjacent() fails!\n"); + MPI_Abort(MPI_COMM_WORLD, 1); + return 1; + } + if (!validate_dgraph(dgraph_comm)) { + fprintf(stderr, "MPI_Dist_graph_create_adjacent() does NOT create " + "a bidirectional ring graph!\n"); + MPI_Abort(MPI_COMM_WORLD, 1); + return 1; + } + MPI_Comm_free(&dgraph_comm); + + MTest_Finalize(errs); + MPI_Finalize(); + return 0; +} diff --git a/teshsuite/smpi/mpich3-test/topo/dims1.c b/teshsuite/smpi/mpich3-test/topo/dims1.c new file mode 100644 index 0000000000..b429776470 --- /dev/null +++ b/teshsuite/smpi/mpich3-test/topo/dims1.c @@ -0,0 +1,144 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * (C) 2003 by Argonne National Laboratory. + * See COPYRIGHT in top-level directory. + */ +#include "mpi.h" +#include +#include "mpitest.h" + +int prodof( int ndims, const int dims[] ); +int increasing( int ndims, const int dims[] ); + +int prodof( int ndims, const int dims[] ) +{ + int i, prod=1; + for (i=0; i dims[i-1]) { + printf ("%d = dims[%d] > dims[%d] = %d\n", dims[i], i, + i-1, dims[i-1] ); + err = 1; + } + } + return err; +} +int main( int argc, char *argv[] ) +{ + int errs = 0; + int dims[4], nnodes, ndims; + + MTest_Init( &argc, &argv ); + + /* Test multiple dims create values. For each, make sure that the + product of dims is the number of input nodes */ + nnodes = 2*3*5*7*11; + ndims = 2; + dims[0] = dims[1] = 0; + MPI_Dims_create( nnodes, ndims, dims ); + if (prodof(ndims,dims) != nnodes) { + errs++; + printf( "dims create returned the wrong decomposition for %d in %d dims\n", + nnodes, ndims ); + } + if (increasing( ndims, dims )) { + errs++; + printf( "dims create returned a decomposition with increasing dimensions (see MPI-1 standard section 6.5)\n" ); + printf( "dims create returned the wrong decomposition for %d in %d dims\n", + nnodes, ndims ); + } + + /* Test multiple dims create values. For each, make sure that the + product of dims is the number of input nodes */ + nnodes = 2*7; + ndims = 2; + dims[0] = dims[1] = 0; + MPI_Dims_create( nnodes, ndims, dims ); + if (prodof(ndims,dims) != nnodes) { + errs++; + printf( "dims create returned the wrong decomposition for %d in %d dims\n", + nnodes, ndims ); + } + if (increasing( ndims, dims )) { + errs++; + printf( "dims create returned a decomposition with increasing dimensions (see MPI-1 standard section 6.5)\n" ); + printf( "dims create returned the wrong decomposition for %d in %d dims\n", + nnodes, ndims ); + } + + nnodes = 2*2*3*3*5*7*11; + ndims = 2; + dims[0] = dims[1] = 0; + MPI_Dims_create( nnodes, ndims, dims ); + if (prodof(ndims,dims) != nnodes) { + errs++; + printf( "dims create returned the wrong decomposition for %d in %d dims\n", + nnodes, ndims ); + } + if (increasing( ndims, dims )) { + errs++; + printf( "dims create returned a decomposition with increasing dimensions (see MPI-1 standard section 6.5)\n" ); + printf( "dims create returned the wrong decomposition for %d in %d dims\n", + nnodes, ndims ); + } + + nnodes = 11; + ndims = 2; + dims[0] = dims[1] = 0; + MPI_Dims_create( nnodes, ndims, dims ); + if (prodof(ndims,dims) != nnodes) { + errs++; + printf( "dims create returned the wrong decomposition for %d in %d dims\n", + nnodes, ndims ); + } + if (increasing( ndims, dims )) { + errs++; + printf( "dims create returned a decomposition with increasing dimensions (see MPI-1 standard section 6.5)\n" ); + printf( "dims create returned the wrong decomposition for %d in %d dims\n", + nnodes, ndims ); + } + + nnodes = 5*7*11; + ndims = 4; + dims[0] = dims[1] = dims[2] = dims[3] = 0; + MPI_Dims_create( nnodes, ndims, dims ); + if (prodof(ndims,dims) != nnodes) { + errs++; + printf( "dims create returned the wrong decomposition for %d in %d dims\n", + nnodes, ndims ); + } + if (increasing( ndims, dims )) { + errs++; + printf( "dims create returned a decomposition with increasing dimensions (see MPI-1 standard section 6.5)\n" ); + printf( "dims create returned the wrong decomposition for %d in %d dims\n", + nnodes, ndims ); + } + + nnodes = 64; + ndims = 4; + dims[0] = dims[1] = dims[2] = dims[3] = 0; + MPI_Dims_create( nnodes, ndims, dims ); + if (prodof(ndims,dims) != nnodes) { + errs++; + printf( "dims create returned the wrong decomposition for %d in %d dims\n", + nnodes, ndims ); + } + if (increasing( ndims, dims )) { + errs++; + printf( "dims create returned a decomposition with increasing dimensions (see MPI-1 standard section 6.5)\n" ); + printf( "dims create returned the wrong decomposition for %d in %d dims\n", + nnodes, ndims ); + } + + MTest_Finalize( errs ); + MPI_Finalize(); + return 0; + +} diff --git a/teshsuite/smpi/mpich3-test/topo/dims2.c b/teshsuite/smpi/mpich3-test/topo/dims2.c new file mode 100644 index 0000000000..aa453eb89a --- /dev/null +++ b/teshsuite/smpi/mpich3-test/topo/dims2.c @@ -0,0 +1,93 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * (C) 2003 by Argonne National Laboratory. + * See COPYRIGHT in top-level directory. + */ +#include "mpi.h" +#include +#include "mpitest.h" + +int prodof( int, const int[] ); +/* + * Test edge cases of Dims_create + */ +int prodof( int ndims, const int dims[] ) +{ + int i, prod=1; + for (i=0; i +#include +#include +#include +#include "mpitest.h" + +#define NUM_GRAPHS 10 +#define MAX_WEIGHT 100 + +/* convenience globals */ +int size, rank; + +/* We need MPI 2.2 to be able to compile the following routines. */ +#if MTEST_HAVE_MIN_MPI_VERSION(2,2) + +/* Maybe use a bit vector instead? */ +int **layout; + +#define MAX_LAYOUT_NAME_LEN 256 +char graph_layout_name[MAX_LAYOUT_NAME_LEN] = {'\0'}; + +static void create_graph_layout(int graph_num) +{ + int i, j; + + if (rank == 0) { + switch (graph_num) { + case 0: + strncpy(graph_layout_name, "deterministic complete graph", MAX_LAYOUT_NAME_LEN); + for (i = 0; i < size; i++) + for (j = 0; j < size; j++) + layout[i][j] = (i + 2) * (j + 1); + break; + case 1: + strncpy(graph_layout_name, "every other edge deleted", MAX_LAYOUT_NAME_LEN); + for (i = 0; i < size; i++) + for (j = 0; j < size; j++) + layout[i][j] = (j % 2 ? (i + 2) * (j + 1) : 0); + break; + case 2: + strncpy(graph_layout_name, "only self-edges", MAX_LAYOUT_NAME_LEN); + for (i = 0; i < size; i++) { + for (j = 0; j < size; j++) { + if (i == rank && j == rank) + layout[i][j] = 10 * (i + 1); + else + layout[i][j] = 0; + } + } + break; + case 3: + strncpy(graph_layout_name, "no edges", MAX_LAYOUT_NAME_LEN); + for (i = 0; i < size; i++) + for (j = 0; j < size; j++) + layout[i][j] = 0; + break; + default: + strncpy(graph_layout_name, "a random incomplete graph", MAX_LAYOUT_NAME_LEN); + srand(graph_num); + + /* Create a connectivity graph; layout[i,j]==w represents an outward + * connectivity from i to j with weight w, w==0 is no edge. */ + for (i = 0; i < size; i++) { + for (j = 0; j < size; j++) { + /* disable about a third of the edges */ + if (((rand() * 1.0) / RAND_MAX) < 0.33) + layout[i][j] = 0; + else + layout[i][j] = rand() % MAX_WEIGHT; + } + } + break; + } + } + + /* because of the randomization we must determine the graph on rank 0 and + * send the layout to all other processes */ + MPI_Bcast(graph_layout_name, MAX_LAYOUT_NAME_LEN, MPI_CHAR, 0, MPI_COMM_WORLD); + for (i = 0; i < size; ++i) { + MPI_Bcast(layout[i], size, MPI_INT, 0, MPI_COMM_WORLD); + } +} + +static int verify_comm(MPI_Comm comm) +{ + int local_errs = 0; + int i, j; + int indegree, outdegree, weighted; + int *sources, *sweights, *destinations, *dweights; + int use_dup; + int topo_type = MPI_UNDEFINED; + MPI_Comm dupcomm = MPI_COMM_NULL; + + sources = (int *) malloc(size * sizeof(int)); + sweights = (int *) malloc(size * sizeof(int)); + destinations = (int *) malloc(size * sizeof(int)); + dweights = (int *) malloc(size * sizeof(int)); + + for (use_dup = 0; use_dup <= 1; ++use_dup) { + if (!use_dup) { + MPI_Dist_graph_neighbors_count(comm, &indegree, &outdegree, &weighted); + } + else { + MPI_Comm_dup(comm, &dupcomm); + comm = dupcomm; /* caller retains original comm value */ + } + + MPI_Topo_test(comm, &topo_type); + if (topo_type != MPI_DIST_GRAPH) { + fprintf(stderr, "topo_type != MPI_DIST_GRAPH\n"); + ++local_errs; + } + + j = 0; + for (i = 0; i < size; i++) + if (layout[i][rank]) + j++; + if (j != indegree) { + fprintf(stderr, "indegree does not match, expected=%d got=%d, layout='%s'\n", indegree, j, graph_layout_name); + ++local_errs; + } + + j = 0; + for (i = 0; i < size; i++) + if (layout[rank][i]) + j++; + if (j != outdegree) { + fprintf(stderr, "outdegree does not match, expected=%d got=%d, layout='%s'\n", outdegree, j, graph_layout_name); + ++local_errs; + } + + if ((indegree || outdegree) && (weighted == 0)) { + fprintf(stderr, "MPI_Dist_graph_neighbors_count thinks the graph is not weighted\n"); + ++local_errs; + } + + + MPI_Dist_graph_neighbors(comm, indegree, sources, sweights, outdegree, destinations, dweights); + + /* For each incoming and outgoing edge in the matrix, search if + * the query function listed it in the sources. */ + for (i = 0; i < size; i++) { + if (layout[i][rank]) { + for (j = 0; j < indegree; j++) { + assert(sources[j] >= 0); + assert(sources[j] < size); + if (sources[j] == i) + break; + } + if (j == indegree) { + fprintf(stderr, "no edge from %d to %d specified\n", i, rank); + ++local_errs; + } + else { + if (sweights[j] != layout[i][rank]) { + fprintf(stderr, "incorrect weight for edge (%d,%d): %d instead of %d\n", + i, rank, sweights[j], layout[i][rank]); + ++local_errs; + } + } + } + if (layout[rank][i]) { + for (j = 0; j < outdegree; j++) { + assert(destinations[j] >= 0); + assert(destinations[j] < size); + if (destinations[j] == i) + break; + } + if (j == outdegree) { + fprintf(stderr, "no edge from %d to %d specified\n", rank, i); + ++local_errs; + } + else { + if (dweights[j] != layout[rank][i]) { + fprintf(stderr, "incorrect weight for edge (%d,%d): %d instead of %d\n", + rank, i, dweights[j], layout[rank][i]); + ++local_errs; + } + } + } + } + + /* For each incoming and outgoing edge in the sources, we should + * have an entry in the matrix */ + for (i = 0; i < indegree; i++) { + if (layout[sources[i]][rank] != sweights[i]) { + fprintf(stderr, "edge (%d,%d) has a weight %d instead of %d\n", i, rank, + sweights[i], layout[sources[i]][rank]); + ++local_errs; + } + } + for (i = 0; i < outdegree; i++) { + if (layout[rank][destinations[i]] != dweights[i]) { + fprintf(stderr, "edge (%d,%d) has a weight %d instead of %d\n", rank, i, + dweights[i], layout[rank][destinations[i]]); + ++local_errs; + } + } + + } + + if (dupcomm != MPI_COMM_NULL) + MPI_Comm_free(&dupcomm); + + return local_errs; +} + +#endif /* At least MPI 2.2 */ + +int main(int argc, char *argv[]) +{ + int errs = 0; + int i, j, k, p; + int indegree, outdegree, reorder; + int check_indegree, check_outdegree, check_weighted; + int *sources, *sweights, *destinations, *dweights, *degrees; + MPI_Comm comm; + + MTest_Init(&argc, &argv); + + MPI_Comm_size(MPI_COMM_WORLD, &size); + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + +#if MTEST_HAVE_MIN_MPI_VERSION(2,2) + layout = (int **) malloc(size * sizeof(int *)); + assert(layout); + for (i = 0; i < size; i++) { + layout[i] = (int *) malloc(size * sizeof(int)); + assert(layout[i]); + } + /* alloc size*size ints to handle the all-on-one-process case */ + sources = (int *) malloc(size * size * sizeof(int)); + sweights = (int *) malloc(size * size * sizeof(int)); + destinations = (int *) malloc(size * size * sizeof(int)); + dweights = (int *) malloc(size * size * sizeof(int)); + degrees = (int *) malloc(size * size * sizeof(int)); + + for (i = 0; i < NUM_GRAPHS; i++) { + create_graph_layout(i); + if (rank == 0) { + MTestPrintfMsg( 1, "using graph layout '%s'\n", graph_layout_name ); + } + + /* MPI_Dist_graph_create_adjacent */ + if (rank == 0) { + MTestPrintfMsg( 1, "testing MPI_Dist_graph_create_adjacent\n" ); + } + indegree = 0; + k = 0; + for (j = 0; j < size; j++) { + if (layout[j][rank]) { + indegree++; + sources[k] = j; + sweights[k++] = layout[j][rank]; + } + } + + outdegree = 0; + k = 0; + for (j = 0; j < size; j++) { + if (layout[rank][j]) { + outdegree++; + destinations[k] = j; + dweights[k++] = layout[rank][j]; + } + } + + for (reorder = 0; reorder <= 1; reorder++) { + MPI_Dist_graph_create_adjacent(MPI_COMM_WORLD, indegree, sources, sweights, + outdegree, destinations, dweights, MPI_INFO_NULL, + reorder, &comm); + MPI_Barrier(comm); + errs += verify_comm(comm); + MPI_Comm_free(&comm); + } + + /* a weak check that passing MPI_UNWEIGHTED doesn't cause + * create_adjacent to explode */ + MPI_Dist_graph_create_adjacent(MPI_COMM_WORLD, indegree, sources, MPI_UNWEIGHTED, + outdegree, destinations, MPI_UNWEIGHTED, MPI_INFO_NULL, + reorder, &comm); + MPI_Barrier(comm); + /* intentionally no verify here, weights won't match */ + MPI_Comm_free(&comm); + + + /* MPI_Dist_graph_create() where each process specifies its + * outgoing edges */ + if (rank == 0) { + MTestPrintfMsg( 1, + "testing MPI_Dist_graph_create w/ outgoing only\n" ); + } + sources[0] = rank; + k = 0; + for (j = 0; j < size; j++) { + if (layout[rank][j]) { + destinations[k] = j; + dweights[k++] = layout[rank][j]; + } + } + degrees[0] = k; + for (reorder = 0; reorder <= 1; reorder++) { + MPI_Dist_graph_create(MPI_COMM_WORLD, 1, sources, degrees, destinations, dweights, + MPI_INFO_NULL, reorder, &comm); + MPI_Barrier(comm); + errs += verify_comm(comm); + MPI_Comm_free(&comm); + } + + + /* MPI_Dist_graph_create() where each process specifies its + * incoming edges */ + if (rank == 0) { + MTestPrintfMsg( 1, + "testing MPI_Dist_graph_create w/ incoming only\n" ); + } + k = 0; + for (j = 0; j < size; j++) { + if (layout[j][rank]) { + sources[k] = j; + sweights[k] = layout[j][rank]; + degrees[k] = 1; + destinations[k++] = rank; + } + } + for (reorder = 0; reorder <= 1; reorder++) { + MPI_Dist_graph_create(MPI_COMM_WORLD, k, sources, degrees, destinations, sweights, + MPI_INFO_NULL, reorder, &comm); + MPI_Barrier(comm); + errs += verify_comm(comm); + MPI_Comm_free(&comm); + } + + + /* MPI_Dist_graph_create() where rank 0 specifies the entire + * graph */ + if (rank == 0) { + MTestPrintfMsg( 1, + "testing MPI_Dist_graph_create w/ rank 0 specifies only\n" ); + } + p = 0; + for (j = 0; j < size; j++) { + for (k = 0; k < size; k++) { + if (layout[j][k]) { + sources[p] = j; + sweights[p] = layout[j][k]; + degrees[p] = 1; + destinations[p++] = k; + } + } + } + for (reorder = 0; reorder <= 1; reorder++) { + MPI_Dist_graph_create(MPI_COMM_WORLD, (rank == 0) ? p : 0, sources, degrees, + destinations, sweights, MPI_INFO_NULL, reorder, &comm); + MPI_Barrier(comm); + errs += verify_comm(comm); + MPI_Comm_free(&comm); + } + + /* MPI_Dist_graph_create() where rank 0 specifies the entire + * graph and all other ranks pass NULL. Can catch implementation + * problems when MPI_UNWEIGHTED==NULL. */ + if (rank == 0) { + MTestPrintfMsg( 1, + "testing MPI_Dist_graph_create w/ rank 0 specifies only -- NULLs\n"); + } + p = 0; + for (j = 0; j < size; j++) { + for (k = 0; k < size; k++) { + if (layout[j][k]) { + sources[p] = j; + sweights[p] = layout[j][k]; + degrees[p] = 1; + destinations[p++] = k; + } + } + } + for (reorder = 0; reorder <= 1; reorder++) { + if (rank == 0) { + MPI_Dist_graph_create(MPI_COMM_WORLD, p, sources, degrees, + destinations, sweights, MPI_INFO_NULL, reorder, &comm); + } + else { + MPI_Dist_graph_create(MPI_COMM_WORLD, 0, NULL, NULL, + NULL, NULL, MPI_INFO_NULL, reorder, &comm); + } + MPI_Barrier(comm); + errs += verify_comm(comm); + MPI_Comm_free(&comm); + } + + } + + /* now tests that don't depend on the layout[][] array */ + + /* The MPI-2.2 standard recommends implementations set + * MPI_UNWEIGHTED==NULL, but this leads to an ambiguity. The draft + * MPI-3.0 standard specifically recommends _not_ setting it equal + * to NULL. */ + if (MPI_UNWEIGHTED == NULL) { + fprintf(stderr, "MPI_UNWEIGHTED should not be NULL\n"); + ++errs; + } + + /* MPI_Dist_graph_create() with no graph */ + if (rank == 0) { + MTestPrintfMsg( 1, "testing MPI_Dist_graph_create w/ no graph\n" ); + } + for (reorder = 0; reorder <= 1; reorder++) { + MPI_Dist_graph_create(MPI_COMM_WORLD, 0, sources, degrees, + destinations, sweights, MPI_INFO_NULL, reorder, &comm); + MPI_Dist_graph_neighbors_count(comm, &check_indegree, &check_outdegree, &check_weighted); + if (!check_weighted) { + fprintf(stderr, "expected weighted == TRUE for the \"no graph\" case\n"); + ++errs; + } + MPI_Comm_free(&comm); + } + + /* MPI_Dist_graph_create() with no graph -- passing MPI_WEIGHTS_EMPTY + instead */ + /* NOTE that MPI_WEIGHTS_EMPTY was added in MPI-3 and does not + appear before then. This part of the test thus requires a check + on the MPI major version */ +#if MPI_VERSION >= 3 + if (rank == 0) { + MTestPrintfMsg( 1, "testing MPI_Dist_graph_create w/ no graph\n" ); + } + for (reorder = 0; reorder <= 1; reorder++) { + MPI_Dist_graph_create(MPI_COMM_WORLD, 0, sources, degrees, + destinations, MPI_WEIGHTS_EMPTY, MPI_INFO_NULL, reorder, &comm); + MPI_Dist_graph_neighbors_count(comm, &check_indegree, &check_outdegree, &check_weighted); + if (!check_weighted) { + fprintf(stderr, "expected weighted == TRUE for the \"no graph -- MPI_WEIGHTS_EMPTY\" case\n"); + ++errs; + } + MPI_Comm_free(&comm); + } +#endif + + /* MPI_Dist_graph_create() with no graph -- passing NULLs instead */ + if (rank == 0) { + MTestPrintfMsg( 1, + "testing MPI_Dist_graph_create w/ no graph -- NULLs\n" ); + } + for (reorder = 0; reorder <= 1; reorder++) { + MPI_Dist_graph_create(MPI_COMM_WORLD, 0, NULL, NULL, + NULL, NULL, MPI_INFO_NULL, reorder, &comm); + MPI_Dist_graph_neighbors_count(comm, &check_indegree, &check_outdegree, &check_weighted); + /* ambiguous if they are equal, only check when they are distinct values. */ + if (MPI_UNWEIGHTED != NULL) { + if (!check_weighted) { + fprintf(stderr, "expected weighted == TRUE for the \"no graph -- NULLs\" case\n"); + ++errs; + } + } + MPI_Comm_free(&comm); + } + + /* MPI_Dist_graph_create() with no graph -- passing NULLs+MPI_UNWEIGHTED instead */ + if (rank == 0) { + MTestPrintfMsg( 1, + "testing MPI_Dist_graph_create w/ no graph -- NULLs+MPI_UNWEIGHTED\n" ); + } + for (reorder = 0; reorder <= 1; reorder++) { + MPI_Dist_graph_create(MPI_COMM_WORLD, 0, NULL, NULL, + NULL, MPI_UNWEIGHTED, MPI_INFO_NULL, reorder, &comm); + MPI_Dist_graph_neighbors_count(comm, &check_indegree, &check_outdegree, &check_weighted); + /* ambiguous if they are equal, only check when they are distinct values. */ + if (MPI_UNWEIGHTED != NULL) { + if (check_weighted) { + fprintf(stderr, "expected weighted == FALSE for the \"no graph -- NULLs+MPI_UNWEIGHTED\" case\n"); + ++errs; + } + } + MPI_Comm_free(&comm); + } + + /* MPI_Dist_graph_create_adjacent() with no graph */ + if (rank == 0) { + MTestPrintfMsg( 1, + "testing MPI_Dist_graph_create_adjacent w/ no graph\n" ); + } + for (reorder = 0; reorder <= 1; reorder++) { + MPI_Dist_graph_create_adjacent(MPI_COMM_WORLD, 0, sources, sweights, + 0, destinations, dweights, MPI_INFO_NULL, reorder, &comm); + MPI_Dist_graph_neighbors_count(comm, &check_indegree, &check_outdegree, &check_weighted); + if (!check_weighted) { + fprintf(stderr, "expected weighted == TRUE for the \"no graph\" case\n"); + ++errs; + } + MPI_Comm_free(&comm); + } + + /* MPI_Dist_graph_create_adjacent() with no graph -- passing MPI_WEIGHTS_EMPTY instead */ + /* NOTE that MPI_WEIGHTS_EMPTY was added in MPI-3 and does not + appear before then. This part of the test thus requires a check + on the MPI major version */ +#if MPI_VERSION >= 3 + if (rank == 0) { + MTestPrintfMsg( 1, + "testing MPI_Dist_graph_create_adjacent w/ no graph -- MPI_WEIGHTS_EMPTY\n" ); + } + for (reorder = 0; reorder <= 1; reorder++) { + MPI_Dist_graph_create_adjacent(MPI_COMM_WORLD, 0, sources, MPI_WEIGHTS_EMPTY, + 0, destinations, MPI_WEIGHTS_EMPTY, MPI_INFO_NULL, reorder, &comm); + MPI_Dist_graph_neighbors_count(comm, &check_indegree, &check_outdegree, &check_weighted); + if (!check_weighted) { + fprintf(stderr, "expected weighted == TRUE for the \"no graph -- MPI_WEIGHTS_EMPTY\" case\n"); + ++errs; + } + MPI_Comm_free(&comm); + } +#endif + + /* MPI_Dist_graph_create_adjacent() with no graph -- passing NULLs instead */ + if (rank == 0) { + MTestPrintfMsg( 1, + "testing MPI_Dist_graph_create_adjacent w/ no graph -- NULLs\n" ); + } + for (reorder = 0; reorder <= 1; reorder++) { + MPI_Dist_graph_create_adjacent(MPI_COMM_WORLD, 0, NULL, NULL, + 0, NULL, NULL, MPI_INFO_NULL, reorder, &comm); + MPI_Dist_graph_neighbors_count(comm, &check_indegree, &check_outdegree, &check_weighted); + /* ambiguous if they are equal, only check when they are distinct values. */ + if (MPI_UNWEIGHTED != NULL) { + if (!check_weighted) { + fprintf(stderr, "expected weighted == TRUE for the \"no graph -- NULLs\" case\n"); + ++errs; + } + } + MPI_Comm_free(&comm); + } + + /* MPI_Dist_graph_create_adjacent() with no graph -- passing NULLs+MPI_UNWEIGHTED instead */ + if (rank == 0) { + MTestPrintfMsg( 1, +"testing MPI_Dist_graph_create_adjacent w/ no graph -- NULLs+MPI_UNWEIGHTED\n"); + } + for (reorder = 0; reorder <= 1; reorder++) { + MPI_Dist_graph_create_adjacent(MPI_COMM_WORLD, 0, NULL, MPI_UNWEIGHTED, + 0, NULL, MPI_UNWEIGHTED, MPI_INFO_NULL, reorder, &comm); + MPI_Dist_graph_neighbors_count(comm, &check_indegree, &check_outdegree, &check_weighted); + /* ambiguous if they are equal, only check when they are distinct values. */ + if (MPI_UNWEIGHTED != NULL) { + if (check_weighted) { + fprintf(stderr, "expected weighted == FALSE for the \"no graph -- NULLs+MPI_UNWEIGHTED\" case\n"); + ++errs; + } + } + MPI_Comm_free(&comm); + } + + + for (i = 0; i < size; i++) + free(layout[i]); + free(layout); +#endif + + MTest_Finalize(errs); + MPI_Finalize(); + + return 0; +} diff --git a/teshsuite/smpi/mpich3-test/topo/graphcr.c b/teshsuite/smpi/mpich3-test/topo/graphcr.c new file mode 100644 index 0000000000..2bfac484ab --- /dev/null +++ b/teshsuite/smpi/mpich3-test/topo/graphcr.c @@ -0,0 +1,34 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * (C) 2003 by Argonne National Laboratory. + * See COPYRIGHT in top-level directory. + */ +#include "mpi.h" +#include +#include "mpitest.h" + +/* +static char MTEST_Descrip[] = "Create a communicator with a graph that contains no processes"; +*/ + +int main( int argc, char *argv[] ) +{ + int errs = 0; + int *index = 0, *edges = 0; + MPI_Comm comm; + + MTest_Init( &argc, &argv ); + + /* MPI 2.1, page 246, lines 29-30 make it clear that this is a valid + (not erroneous) call that must return MPI_COMM_NULL */ + MPI_Graph_create( MPI_COMM_WORLD, 0, index, edges, 0, &comm ); + if (comm != MPI_COMM_NULL) { + errs++; + fprintf( stderr, "Expected MPI_COMM_NULL from empty graph create\n" ); + } + + MTest_Finalize( errs ); + MPI_Finalize(); + return 0; +} diff --git a/teshsuite/smpi/mpich3-test/topo/graphcr2.c b/teshsuite/smpi/mpich3-test/topo/graphcr2.c new file mode 100644 index 0000000000..6d5fd2ae30 --- /dev/null +++ b/teshsuite/smpi/mpich3-test/topo/graphcr2.c @@ -0,0 +1,70 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * (C) 2003 by Argonne National Laboratory. + * See COPYRIGHT in top-level directory. + */ +#include "mpi.h" +#include +#include +#include "mpitest.h" + +/* +static char MTEST_Descrip[] = "Create a communicator with a graph that contains null edges and one that contains duplicate edges"; +*/ + +int main( int argc, char *argv[] ) +{ + int errs = 0; + int *index = 0, *edges = 0; + int rank, size, i, j, crank, csize; + MPI_Comm comm; + + MTest_Init( &argc, &argv ); + + MPI_Comm_size( MPI_COMM_WORLD, &size ); + MPI_Comm_rank( MPI_COMM_WORLD, &rank ); + + index = (int *)malloc( size*sizeof(int) ); + edges = (int *)malloc( size*sizeof(int) ); + for (i=0; i +#include "mpitest.h" + +int main( int argc, char *argv[] ) +{ + int errs = 0; + int newrank, merr, rank; + int index[2], edges[2]; + + MTest_Init( &argc, &argv ); + + MPI_Comm_rank( MPI_COMM_WORLD, &rank ); + /* Graph map where there are no nodes for this process */ + MPI_Comm_set_errhandler( MPI_COMM_WORLD, MPI_ERRORS_RETURN ); + /* Here is a singleton graph, containing only the root process */ + index[0] = 0; + edges[0] = 0; + merr = MPI_Graph_map( MPI_COMM_WORLD, 1, index, edges, &newrank ); + if (merr) { + errs++; + printf( "Graph map returned an error\n" ); + MTestPrintError( merr ); + } + if (rank != 0 && newrank != MPI_UNDEFINED) { + errs++; + printf( "Graph map with no local nodes did not return MPI_UNDEFINED\n" ); + } + + MTest_Finalize( errs ); + MPI_Finalize(); + return 0; + +} diff --git a/teshsuite/smpi/mpich3-test/topo/neighb_coll.c b/teshsuite/smpi/mpich3-test/topo/neighb_coll.c new file mode 100644 index 0000000000..0c4a7fd882 --- /dev/null +++ b/teshsuite/smpi/mpich3-test/topo/neighb_coll.c @@ -0,0 +1,179 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * (C) 2012 by Argonne National Laboratory. + * See COPYRIGHT in top-level directory. + */ +#include +#include +#include + +#include +#include "mpitest.h" + +#if !defined(USE_STRICT_MPI) && defined(MPICH) +#define TEST_NEIGHB_COLL 1 +#endif + +/* assert-like macro that bumps the err count and emits a message */ +#define check(x_) \ + do { \ + if (!(x_)) { \ + ++errs; \ + if (errs < 10) { \ + fprintf(stderr, "check failed: (%s), line %d\n", #x_, __LINE__); \ + } \ + } \ + } while (0) + +int main(int argc, char *argv[]) +{ + int errs = 0; + int wrank, wsize; + int periods[1] = { 0 }; + MPI_Comm cart, dgraph, graph; + + MPI_Init(&argc, &argv); + MPI_Comm_rank(MPI_COMM_WORLD, &wrank); + MPI_Comm_size(MPI_COMM_WORLD, &wsize); + +#if defined(TEST_NEIGHB_COLL) + /* a basic test for the 10 (5 patterns x {blocking,nonblocking}) MPI-3 + * neighborhood collective routines */ + + /* (wrap)--> 0 <--> 1 <--> ... <--> p-1 <--(wrap) */ + MPI_Cart_create(MPI_COMM_WORLD, 1, &wsize, periods, /*reorder=*/0, &cart); + + /* allgather */ + { + int sendbuf[1] = { wrank }; + int recvbuf[2] = { 0xdeadbeef, 0xdeadbeef }; + + /* should see one send to each neighbor (rank-1 and rank+1) and one receive + * each from same */ + MPI_Neighbor_allgather(sendbuf, 1, MPI_INT, recvbuf, 1, MPI_INT, cart); + + if (wrank == 0) + check(recvbuf[0] == 0xdeadbeef); + else + check(recvbuf[0] == wrank - 1); + + if (wrank == wsize - 1) + check(recvbuf[1] == 0xdeadbeef); + else + check(recvbuf[1] == wrank + 1); + } + + /* allgatherv */ + { + int sendbuf[1] = { wrank }; + int recvbuf[2] = { 0xdeadbeef, 0xdeadbeef }; + int recvcounts[2] = { 1, 1 }; + int displs[2] = { 1, 0}; + + /* should see one send to each neighbor (rank-1 and rank+1) and one receive + * each from same, but put them in opposite slots in the buffer */ + MPI_Neighbor_allgatherv(sendbuf, 1, MPI_INT, recvbuf, recvcounts, displs, MPI_INT, cart); + + if (wrank == 0) + check(recvbuf[1] == 0xdeadbeef); + else + check(recvbuf[1] == wrank - 1); + + if (wrank == wsize - 1) + check(recvbuf[0] == 0xdeadbeef); + else + check(recvbuf[0] == wrank + 1); + } + + /* alltoall */ + { + int sendbuf[2] = { -(wrank+1), wrank+1 }; + int recvbuf[2] = { 0xdeadbeef, 0xdeadbeef }; + + /* should see one send to each neighbor (rank-1 and rank+1) and one + * receive each from same */ + MPI_Neighbor_alltoall(sendbuf, 1, MPI_INT, recvbuf, 1, MPI_INT, cart); + + if (wrank == 0) + check(recvbuf[0] == 0xdeadbeef); + else + check(recvbuf[0] == wrank); + + if (wrank == wsize - 1) + check(recvbuf[1] == 0xdeadbeef); + else + check(recvbuf[1] == -(wrank + 2)); + } + + /* alltoallv */ + { + int sendbuf[2] = { -(wrank+1), wrank+1 }; + int recvbuf[2] = { 0xdeadbeef, 0xdeadbeef }; + int sendcounts[2] = { 1, 1 }; + int recvcounts[2] = { 1, 1 }; + int sdispls[2] = { 0, 1 }; + int rdispls[2] = { 1, 0 }; + + /* should see one send to each neighbor (rank-1 and rank+1) and one receive + * each from same, but put them in opposite slots in the buffer */ + MPI_Neighbor_alltoallv(sendbuf, sendcounts, sdispls, MPI_INT, + recvbuf, recvcounts, rdispls, MPI_INT, + cart); + + if (wrank == 0) + check(recvbuf[1] == 0xdeadbeef); + else + check(recvbuf[1] == wrank); + + if (wrank == wsize - 1) + check(recvbuf[0] == 0xdeadbeef); + else + check(recvbuf[0] == -(wrank + 2)); + } + + /* alltoallw */ + { + int sendbuf[2] = { -(wrank+1), wrank+1 }; + int recvbuf[2] = { 0xdeadbeef, 0xdeadbeef }; + int sendcounts[2] = { 1, 1 }; + int recvcounts[2] = { 1, 1 }; + MPI_Aint sdispls[2] = { 0, sizeof(int) }; + MPI_Aint rdispls[2] = { sizeof(int), 0 }; + MPI_Datatype sendtypes[2] = { MPI_INT, MPI_INT }; + MPI_Datatype recvtypes[2] = { MPI_INT, MPI_INT }; + + /* should see one send to each neighbor (rank-1 and rank+1) and one receive + * each from same, but put them in opposite slots in the buffer */ + MPI_Neighbor_alltoallw(sendbuf, sendcounts, sdispls, sendtypes, + recvbuf, recvcounts, rdispls, recvtypes, + cart); + + if (wrank == 0) + check(recvbuf[1] == 0xdeadbeef); + else + check(recvbuf[1] == wrank); + + if (wrank == wsize - 1) + check(recvbuf[0] == 0xdeadbeef); + else + check(recvbuf[0] == -(wrank + 2)); + } + + + MPI_Comm_free(&cart); +#endif /* defined(TEST_NEIGHB_COLL) */ + + MPI_Reduce((wrank == 0 ? MPI_IN_PLACE : &errs), &errs, 1, MPI_INT, MPI_SUM, 0, MPI_COMM_WORLD); + if (wrank == 0) { + if (errs) { + printf("found %d errors\n", errs); + } + else { + printf(" No errors\n"); + } + } + MPI_Finalize(); + + return 0; +} + diff --git a/teshsuite/smpi/mpich3-test/topo/testlist b/teshsuite/smpi/mpich3-test/topo/testlist new file mode 100644 index 0000000000..0ec8867d09 --- /dev/null +++ b/teshsuite/smpi/mpich3-test/topo/testlist @@ -0,0 +1,21 @@ +#need Cart implem +#cartmap1 4 +#cartzero 4 +#cartshift1 4 +#cartsuball 4 +#cartcreates 4 +#need MPI_Dims_create +#dims1 4 +#dims2 1 +#need MPI_Error_class, MPI_Comm_remote_size, MPI_Graph_map +#graphmap1 4 +#need MPI_Topo_test, MPI_Cart_create +#topotest 4 +#need MPI_Cart_create, MPI_Cart_get, MPI_Comm_remote_size, MPI_Dims_create ... +#topodup 4 +#need MPI_Graph* +#graphcr 4 +#graphcr2 4 +#distgraph1 4 mpiversion=2.2 +#dgraph_unwgt 4 mpiversion=2.2 +#neighb_coll 4 mpiversion=3.0 diff --git a/teshsuite/smpi/mpich3-test/topo/topodup.c b/teshsuite/smpi/mpich3-test/topo/topodup.c new file mode 100644 index 0000000000..f1c5515ff1 --- /dev/null +++ b/teshsuite/smpi/mpich3-test/topo/topodup.c @@ -0,0 +1,129 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * + * (C) 2003 by Argonne National Laboratory. + * See COPYRIGHT in top-level directory. + */ +#include "mpi.h" +#include +#include +#include "mpitest.h" + +int main( int argc, char *argv[] ) +{ + int errs = 0, i, k; + int dims[2], periods[2], wsize; + int outdims[2], outperiods[2], outcoords[2]; + int topo_type; + int *index, *edges, *outindex, *outedges; + MPI_Comm comm1, comm2; + + MTest_Init( &argc, &argv ); + + MPI_Comm_size( MPI_COMM_WORLD, &wsize ); + + /* Create a cartesian topology, get its characteristics, then + dup it and check that the new communicator has the same properties */ + dims[0] = dims[1] = 0; + MPI_Dims_create( wsize, 2, dims ); + periods[0] = periods[1] = 0; + MPI_Cart_create( MPI_COMM_WORLD, 2, dims, periods, 0, &comm1 ); + + MPI_Comm_dup( comm1, &comm2 ); + MPI_Topo_test( comm2, &topo_type ); + if (topo_type != MPI_CART) { + errs++; + printf( "Topo type of duped cart was not cart\n" ); + } + else { + MPI_Cart_get( comm2, 2, outdims, outperiods, outcoords ); + for (i=0; i<2; i++) { + if (outdims[i] != dims[i]) { + errs++; + printf( "%d = outdims[%d] != dims[%d] = %d\n", outdims[i], + i, i, dims[i] ); + } + if (outperiods[i] != periods[i]) { + errs++; + printf( "%d = outperiods[%d] != periods[%d] = %d\n", + outperiods[i], i, i, periods[i] ); + } + } + } + MPI_Comm_free( &comm2 ); + MPI_Comm_free( &comm1 ); + + /* Now do the same with a graph topology */ + if (wsize >= 3) { + index = (int*)malloc(wsize * sizeof(int) ); + edges = (int*)malloc(wsize * 2 * sizeof(int) ); + if (!index || !edges) { + printf( "Unable to allocate %d words for index or edges\n", + 3 * wsize ); + MPI_Abort( MPI_COMM_WORLD, 1 ); + } + index[0] = 2; + for (i=1; i +#include "mpitest.h" + +int main( int argc, char *argv[] ) +{ + int errs = 0; + int topo_type, size, dims[1], periods[1]; + MPI_Comm comm; + + MTest_Init( &argc, &argv ); + + /* Check that topo test returns the correct type, including + MPI_UNDEFINED */ + + MPI_Topo_test( MPI_COMM_WORLD, &topo_type ); + if (topo_type != MPI_UNDEFINED) { + errs++; + printf( "Topo type of comm world is not UNDEFINED\n" ); + } + + MPI_Comm_size( MPI_COMM_WORLD, &size ); + dims[0] = size; + periods[0] = 0; + MPI_Cart_create( MPI_COMM_WORLD, 1, dims, periods, 0, &comm ); + MPI_Topo_test( comm, &topo_type ); + if (topo_type != MPI_CART) { + errs++; + printf( "Topo type of cart comm is not CART\n" ); + } + + MPI_Comm_free( &comm ); + /* FIXME: still need graph example */ + + MTest_Finalize( errs ); + MPI_Finalize(); + return 0; + +}