Skip to main content

spawn/
spawn.rs

1//! Dynamic process spawning (`MPI_Comm_spawn`). Run the parent as a normal MPI
2//! job (or singleton); it spawns child processes of the same binary. A child
3//! detects it was spawned via `world.parent()`.
4//!
5//! ```text
6//! ./target/debug/examples/spawn          # singleton parent spawns 3 children
7//! mpiexec -n 2 ./target/debug/examples/spawn   # 2 parents collectively spawn
8//! ```
9
10use mpi::traits::*;
11
12const N_CHILDREN: i32 = 3;
13
14fn main() {
15    let universe = mpi::initialize().unwrap();
16    let world = universe.world();
17
18    if let Some(parent) = world.parent() {
19        // ---- child side ----
20        let rank = world.rank();
21        // Receive a value from parent rank 0, send it back incremented.
22        let (val, status) = parent.process_at_rank(0).receive::<i32>();
23        assert_eq!(status.source_rank(), 0);
24        parent.process_at_rank(0).send(&(val + 1));
25        println!(
26            "child {rank}/{} (parent group size {}) got {val}",
27            world.size(),
28            parent.remote_size()
29        );
30    } else {
31        // ---- parent side ----
32        let exe = std::env::current_exe().unwrap();
33        let inter = world
34            .process_at_rank(0)
35            .spawn(exe.to_str().unwrap(), &[], N_CHILDREN)
36            .expect("spawn failed");
37
38        assert_eq!(inter.remote_size(), N_CHILDREN, "wrong child count");
39
40        if world.rank() == 0 {
41            for c in 0..inter.remote_size() {
42                inter.process_at_rank(c).send(&(100 + c));
43                let (reply, _) = inter.process_at_rank(c).receive::<i32>();
44                assert_eq!(reply, 100 + c + 1, "child reply mismatch");
45            }
46            println!(
47                "SPAWN PASS: parent (size {}) round-tripped with {} spawned children.",
48                world.size(),
49                inter.remote_size()
50            );
51        }
52        world.barrier();
53    }
54}