1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172
|
/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
/*
*
* (C) 2011 by Argonne National Laboratory.
* See COPYRIGHT in top-level directory.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#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);
return MTestReturnValue(errs);
}
|