|
Packit Service |
c5cf8c |
/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
|
|
Packit Service |
c5cf8c |
/*
|
|
Packit Service |
c5cf8c |
*
|
|
Packit Service |
c5cf8c |
* (C) 2011 by Argonne National Laboratory.
|
|
Packit Service |
c5cf8c |
* See COPYRIGHT in top-level directory.
|
|
Packit Service |
c5cf8c |
*/
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
#include <stdio.h>
|
|
Packit Service |
c5cf8c |
#include <stdlib.h>
|
|
Packit Service |
c5cf8c |
#include <string.h>
|
|
Packit Service |
c5cf8c |
#include "mpi.h"
|
|
Packit Service |
c5cf8c |
#include "mpitest.h"
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
#define RING_NUM_NEIGHBORS 2
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
static int validate_dgraph(MPI_Comm dgraph_comm)
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
int comm_topo;
|
|
Packit Service |
c5cf8c |
int src_sz, dest_sz;
|
|
Packit Service |
c5cf8c |
int wgt_flag, ierr;
|
|
Packit Service |
c5cf8c |
int srcs[RING_NUM_NEIGHBORS], dests[RING_NUM_NEIGHBORS];
|
|
Packit Service |
c5cf8c |
int *src_wgts, *dest_wgts;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
int world_rank, world_size;
|
|
Packit Service |
c5cf8c |
int idx, nbr_sep;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
comm_topo = MPI_UNDEFINED;
|
|
Packit Service |
c5cf8c |
MPI_Topo_test(dgraph_comm, &comm_topo);
|
|
Packit Service |
c5cf8c |
switch (comm_topo) {
|
|
Packit Service |
c5cf8c |
case MPI_DIST_GRAPH:
|
|
Packit Service |
c5cf8c |
break;
|
|
Packit Service |
c5cf8c |
default:
|
|
Packit Service |
c5cf8c |
fprintf(stderr, "dgraph_comm is NOT of type MPI_DIST_GRAPH\n");
|
|
Packit Service |
c5cf8c |
return 0;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
ierr = MPI_Dist_graph_neighbors_count(dgraph_comm, &src_sz, &dest_sz, &wgt_flag);
|
|
Packit Service |
c5cf8c |
if (ierr != MPI_SUCCESS) {
|
|
Packit Service |
c5cf8c |
fprintf(stderr, "MPI_Dist_graph_neighbors_count() fails!\n");
|
|
Packit Service |
c5cf8c |
return 0;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
/*
|
|
Packit Service |
c5cf8c |
else
|
|
Packit Service |
c5cf8c |
fprintf(stderr, "MPI_Dist_graph_neighbors_count() succeeds!\n");
|
|
Packit Service |
c5cf8c |
*/
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
if (wgt_flag) {
|
|
Packit Service |
c5cf8c |
fprintf(stderr, "dgraph_comm is NOT created with MPI_UNWEIGHTED\n");
|
|
Packit Service |
c5cf8c |
return 0;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
/*
|
|
Packit Service |
c5cf8c |
else
|
|
Packit Service |
c5cf8c |
fprintf(stderr, "dgraph_comm is created with MPI_UNWEIGHTED\n");
|
|
Packit Service |
c5cf8c |
*/
|
|
Packit Service |
c5cf8c |
if (src_sz != RING_NUM_NEIGHBORS || dest_sz != RING_NUM_NEIGHBORS) {
|
|
Packit Service |
c5cf8c |
fprintf(stderr, "source or destination edge array is not of size %d.\n",
|
|
Packit Service |
c5cf8c |
RING_NUM_NEIGHBORS);
|
|
Packit Service |
c5cf8c |
fprintf(stderr, "src_sz = %d, dest_sz = %d\n", src_sz, dest_sz);
|
|
Packit Service |
c5cf8c |
return 0;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/*
|
|
Packit Service |
c5cf8c |
* src_wgts and dest_wgts could be anything, e.g. NULL, since
|
|
Packit Service |
c5cf8c |
* MPI_Dist_graph_neighbors_count() returns MPI_UNWEIGHTED.
|
|
Packit Service |
c5cf8c |
* Since this program has a Fortran77 version, and standard Fortran77
|
|
Packit Service |
c5cf8c |
* has no pointer and NULL, so use MPI_UNWEIGHTED for the weighted arrays.
|
|
Packit Service |
c5cf8c |
*/
|
|
Packit Service |
c5cf8c |
src_wgts = MPI_UNWEIGHTED;
|
|
Packit Service |
c5cf8c |
dest_wgts = MPI_UNWEIGHTED;
|
|
Packit Service |
c5cf8c |
ierr = MPI_Dist_graph_neighbors(dgraph_comm, src_sz, srcs, src_wgts, dest_sz, dests, dest_wgts);
|
|
Packit Service |
c5cf8c |
if (ierr != MPI_SUCCESS) {
|
|
Packit Service |
c5cf8c |
fprintf(stderr, "MPI_Dist_graph_neighbors() fails!\n");
|
|
Packit Service |
c5cf8c |
return 0;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
/*
|
|
Packit Service |
c5cf8c |
else
|
|
Packit Service |
c5cf8c |
fprintf(stderr, "MPI_Dist_graph_neighbors() succeeds!\n");
|
|
Packit Service |
c5cf8c |
*/
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/*
|
|
Packit Service |
c5cf8c |
* Check if the neighbors returned from MPI are really
|
|
Packit Service |
c5cf8c |
* the nearest neighbors within a ring.
|
|
Packit Service |
c5cf8c |
*/
|
|
Packit Service |
c5cf8c |
MPI_Comm_size(MPI_COMM_WORLD, &world_size);
|
|
Packit Service |
c5cf8c |
MPI_Comm_rank(MPI_COMM_WORLD, &world_rank);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
for (idx = 0; idx < src_sz; idx++) {
|
|
Packit Service |
c5cf8c |
nbr_sep = abs(srcs[idx] - world_rank);
|
|
Packit Service |
c5cf8c |
if (nbr_sep != 1 && nbr_sep != (world_size - 1)) {
|
|
Packit Service |
c5cf8c |
fprintf(stderr, "srcs[%d]=%d is NOT a neighbor of my rank %d.\n",
|
|
Packit Service |
c5cf8c |
idx, srcs[idx], world_rank);
|
|
Packit Service |
c5cf8c |
return 0;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
for (idx = 0; idx < dest_sz; idx++) {
|
|
Packit Service |
c5cf8c |
nbr_sep = abs(dests[idx] - world_rank);
|
|
Packit Service |
c5cf8c |
if (nbr_sep != 1 && nbr_sep != (world_size - 1)) {
|
|
Packit Service |
c5cf8c |
fprintf(stderr, "dests[%d]=%d is NOT a neighbor of my rank %d.\n",
|
|
Packit Service |
c5cf8c |
idx, dests[idx], world_rank);
|
|
Packit Service |
c5cf8c |
return 0;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/*
|
|
Packit Service |
c5cf8c |
* fprintf(stderr, "dgraph_comm is of type MPI_DIST_GRAPH "
|
|
Packit Service |
c5cf8c |
* "of a bidirectional ring.\n");
|
|
Packit Service |
c5cf8c |
*/
|
|
Packit Service |
c5cf8c |
return 1;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/*
|
|
Packit Service |
c5cf8c |
Specify a distributed graph of a bidirectional ring of the MPI_COMM_WORLD,
|
|
Packit Service |
c5cf8c |
i.e. everyone only talks to left and right neighbors.
|
|
Packit Service |
c5cf8c |
*/
|
|
Packit Service |
c5cf8c |
int main(int argc, char *argv[])
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
MPI_Comm dgraph_comm;
|
|
Packit Service |
c5cf8c |
int world_size, world_rank, ierr;
|
|
Packit Service |
c5cf8c |
int errs = 0;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
int src_sz, dest_sz;
|
|
Packit Service |
c5cf8c |
int degs[1];
|
|
Packit Service |
c5cf8c |
int srcs[RING_NUM_NEIGHBORS], dests[RING_NUM_NEIGHBORS];
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
MTest_Init(&argc, &argv);
|
|
Packit Service |
c5cf8c |
MPI_Comm_size(MPI_COMM_WORLD, &world_size);
|
|
Packit Service |
c5cf8c |
MPI_Comm_rank(MPI_COMM_WORLD, &world_rank);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
degs[0] = 2;
|
|
Packit Service |
c5cf8c |
srcs[0] = world_rank;
|
|
Packit Service |
c5cf8c |
dests[0] = world_rank - 1 < 0 ? world_size - 1 : world_rank - 1;
|
|
Packit Service |
c5cf8c |
dests[1] = world_rank + 1 >= world_size ? 0 : world_rank + 1;
|
|
Packit Service |
c5cf8c |
ierr = MPI_Dist_graph_create(MPI_COMM_WORLD, 1, srcs, degs, dests,
|
|
Packit Service |
c5cf8c |
MPI_UNWEIGHTED, MPI_INFO_NULL, 1, &dgraph_comm);
|
|
Packit Service |
c5cf8c |
if (ierr != MPI_SUCCESS) {
|
|
Packit Service |
c5cf8c |
fprintf(stderr, "MPI_Dist_graph_create() fails!\n");
|
|
Packit Service |
c5cf8c |
MPI_Abort(MPI_COMM_WORLD, 1);
|
|
Packit Service |
c5cf8c |
return 1;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
if (!validate_dgraph(dgraph_comm)) {
|
|
Packit Service |
c5cf8c |
fprintf(stderr, "MPI_Dist_graph_create() does NOT create " "a bidirectional ring graph!\n");
|
|
Packit Service |
c5cf8c |
MPI_Abort(MPI_COMM_WORLD, 1);
|
|
Packit Service |
c5cf8c |
return 1;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
MPI_Comm_free(&dgraph_comm);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
src_sz = 2;
|
|
Packit Service |
c5cf8c |
srcs[0] = world_rank - 1 < 0 ? world_size - 1 : world_rank - 1;
|
|
Packit Service |
c5cf8c |
srcs[1] = world_rank + 1 >= world_size ? 0 : world_rank + 1;
|
|
Packit Service |
c5cf8c |
dest_sz = 2;
|
|
Packit Service |
c5cf8c |
dests[0] = world_rank - 1 < 0 ? world_size - 1 : world_rank - 1;
|
|
Packit Service |
c5cf8c |
dests[1] = world_rank + 1 >= world_size ? 0 : world_rank + 1;
|
|
Packit Service |
c5cf8c |
ierr = MPI_Dist_graph_create_adjacent(MPI_COMM_WORLD,
|
|
Packit Service |
c5cf8c |
src_sz, srcs, MPI_UNWEIGHTED,
|
|
Packit Service |
c5cf8c |
dest_sz, dests, MPI_UNWEIGHTED,
|
|
Packit Service |
c5cf8c |
MPI_INFO_NULL, 1, &dgraph_comm);
|
|
Packit Service |
c5cf8c |
if (ierr != MPI_SUCCESS) {
|
|
Packit Service |
c5cf8c |
fprintf(stderr, "MPI_Dist_graph_create_adjacent() fails!\n");
|
|
Packit Service |
c5cf8c |
MPI_Abort(MPI_COMM_WORLD, 1);
|
|
Packit Service |
c5cf8c |
return 1;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
if (!validate_dgraph(dgraph_comm)) {
|
|
Packit Service |
c5cf8c |
fprintf(stderr, "MPI_Dist_graph_create_adjacent() does NOT create "
|
|
Packit Service |
c5cf8c |
"a bidirectional ring graph!\n");
|
|
Packit Service |
c5cf8c |
MPI_Abort(MPI_COMM_WORLD, 1);
|
|
Packit Service |
c5cf8c |
return 1;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
MPI_Comm_free(&dgraph_comm);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
MTest_Finalize(errs);
|
|
Packit Service |
c5cf8c |
return MTestReturnValue(errs);
|
|
Packit Service |
c5cf8c |
}
|