Skip to main content

topo_inter/
topo_inter.rs

1//! Self test for graph topologies and inter-communicators.
2
3use mpi::traits::*;
4
5fn main() {
6    let universe = mpi::initialize().unwrap();
7    let world = universe.world();
8    let rank = world.rank();
9    let size = world.size();
10
11    // ---- graph topology: a ring, node i adjacent to i-1 and i+1 ----
12    if size >= 2 {
13        let mut index = Vec::new();
14        let mut edges = Vec::new();
15        for i in 0..size {
16            edges.push((i - 1 + size) % size);
17            edges.push((i + 1) % size);
18            index.push(2 * (i + 1));
19        }
20        let g = world
21            .create_graph_communicator(&index, &edges)
22            .expect("graph create returned None");
23        let expected = vec![(rank - 1 + size) % size, (rank + 1) % size];
24        assert_eq!(g.my_neighbors(), expected, "graph neighbours mismatch");
25        assert_eq!(g.neighbor_count(rank), 2);
26        // Neighbourhood all-gather: each neighbour contributes its own rank.
27        let mut ng = vec![-1i32; 2];
28        g.neighbor_all_gather_into(&rank, &mut ng[..]);
29        assert_eq!(ng, expected, "neighbor_all_gather mismatch");
30        g.barrier();
31    }
32
33    // ---- distributed-graph adjacent: directed ring (recv prev, send next) ----
34    if size >= 2 {
35        let prev = (rank - 1 + size) % size;
36        let next = (rank + 1) % size;
37        let dg = world.create_dist_graph_adjacent(&[prev], &[next]);
38        assert_eq!(dg.in_degree(), 1, "dist-graph in-degree");
39        assert_eq!(dg.out_degree(), 1, "dist-graph out-degree");
40        let mut r = vec![-1i32; 1];
41        dg.neighbor_all_gather_into(&rank, &mut r[..]);
42        assert_eq!(r, vec![prev], "dist-graph neighbor mismatch");
43        dg.barrier();
44    }
45
46    // ---- inter-communicator: split world into two halves ----
47    if size >= 2 {
48        let half = size / 2;
49        let in_a = rank < half;
50        let inter = world.split_intercommunicator(in_a);
51        assert_eq!(
52            inter.local_size() + inter.remote_size(),
53            size,
54            "intercomm size mismatch"
55        );
56
57        // Leaders of the two groups exchange their world ranks across the
58        // inter-communicator.
59        if inter.rank() == 0 {
60            if in_a {
61                inter.process_at_rank(0).send(&rank);
62                let (peer, _): (i32, _) = inter.process_at_rank(0).receive();
63                assert_eq!(peer, half, "intercomm exchange mismatch (A)");
64            } else {
65                let (peer, _): (i32, _) = inter.process_at_rank(0).receive();
66                assert_eq!(peer, 0, "intercomm exchange mismatch (B)");
67                inter.process_at_rank(0).send(&rank);
68            }
69        }
70
71        // Merge back into one intra-communicator spanning everyone.
72        let merged = inter.merge();
73        assert_eq!(merged.size(), size, "merge size mismatch");
74        merged.barrier();
75    }
76
77    world.barrier();
78    if rank == 0 {
79        println!("TOPO/INTER PASS: graph + inter-communicator verified on {size} ranks.");
80    }
81}