1use mpi::collective::SystemOperation;
6use mpi::traits::*;
7
8fn main() {
9 let universe = mpi::initialize().unwrap();
10 let world = universe.world();
11 let rank = world.rank();
12 let size = world.size();
13
14 if size >= 2 {
15 let latency_iters = 2000;
16 let bw_iters = 100;
17 let bw_bytes = 1 << 20; if rank == 0 {
20 let small = [0u8; 8];
22 for _ in 0..100 {
24 world.process_at_rank(1).send(&small[..]);
25 let _ = world.process_at_rank(1).receive_vec::<u8>();
26 }
27 let t0 = mpi::time();
28 for _ in 0..latency_iters {
29 world.process_at_rank(1).send(&small[..]);
30 let _ = world.process_at_rank(1).receive_vec::<u8>();
31 }
32 let dt = mpi::time() - t0;
33 let lat_us = dt / latency_iters as f64 / 2.0 * 1e6;
34 println!("latency: {lat_us:.2} µs (8 B, half round-trip, {latency_iters} iters)");
35
36 let big = vec![0u8; bw_bytes];
38 let t0 = mpi::time();
39 for _ in 0..bw_iters {
40 world.process_at_rank(1).send(&big[..]);
41 let _ = world.process_at_rank(1).receive_vec::<u8>();
42 }
43 let dt = mpi::time() - t0;
44 let mb = bw_bytes as f64 * bw_iters as f64 * 2.0 / 1e6;
45 println!("bandwidth: {:.1} MB/s (1 MiB, {bw_iters} iters)", mb / dt);
46 } else if rank == 1 {
47 let small = [0u8; 8];
48 for _ in 0..latency_iters + 100 {
49 let _ = world.process_at_rank(0).receive_vec::<u8>();
50 world.process_at_rank(0).send(&small[..]);
51 }
52 for _ in 0..bw_iters {
53 let (v, _) = world.process_at_rank(0).receive_vec::<u8>();
54 world.process_at_rank(0).send(&v[..]);
55 }
56 }
57 }
58
59 world.barrier();
61 let coll_iters = 1000;
62 let x = rank;
63 let mut acc = 0i32;
64 let t0 = mpi::time();
65 for _ in 0..coll_iters {
66 world.all_reduce_into(&x, &mut acc, SystemOperation::sum());
67 }
68 let dt = mpi::time() - t0;
69 if rank == 0 {
70 println!(
71 "all_reduce: {:.2} µs/op over {size} ranks ({coll_iters} iters), result {acc}",
72 dt / coll_iters as f64 * 1e6
73 );
74 }
75 world.barrier();
76}