Skip to main content

cluster/
cluster.rs

1//! Multi-host demo: prints each rank's OS/arch (to show heterogeneity) and
2//! exercises real cross-node communication — a send/receive ring, an
3//! all-reduce, and a broadcast.
4//!
5//! ```text
6//! mpiexec -n 2 --host localhost,msi --remote-bin /tmp/cluster ./target/debug/examples/cluster
7//! ```
8
9use mpi::collective::SystemOperation;
10use mpi::traits::*;
11
12fn main() {
13    let universe = mpi::initialize().unwrap();
14    let world = universe.world();
15    let rank = world.rank();
16    let size = world.size();
17
18    println!(
19        "rank {rank}/{size}: os={} arch={}",
20        std::env::consts::OS,
21        std::env::consts::ARCH
22    );
23
24    // Ring send/receive across nodes.
25    let next = (rank + 1) % size;
26    let prev = (rank - 1 + size) % size;
27    let msg = rank * 1000;
28    let (got, status): (i32, _) = mpi::point_to_point::send_receive(
29        &msg,
30        &world.process_at_rank(next),
31        &world.process_at_rank(prev),
32    );
33    assert_eq!(got, prev * 1000, "ring mismatch");
34    assert_eq!(status.source_rank(), prev);
35
36    // All-reduce sum of ranks.
37    let mut sum = 0i32;
38    world.all_reduce_into(&rank, &mut sum, SystemOperation::sum());
39    assert_eq!(sum, (0..size).sum::<i32>(), "allreduce mismatch");
40
41    // Broadcast from rank 0.
42    let mut buf = if rank == 0 {
43        vec![42i32; 3]
44    } else {
45        vec![0; 3]
46    };
47    world.process_at_rank(0).broadcast_into(&mut buf[..]);
48    assert_eq!(buf, vec![42, 42, 42], "broadcast mismatch");
49
50    world.barrier();
51    println!("rank {rank}: cross-node comm OK (sum of ranks = {sum})");
52    if rank == 0 {
53        println!("CLUSTER PASS: {size} ranks communicated across hosts.");
54    }
55}