pub struct Status { /* private fields */ }Expand description
The outcome of a receive or probe (MPI_Status).
Implementations§
Source§impl Status
impl Status
Sourcepub fn source_rank(&self) -> Rank
pub fn source_rank(&self) -> Rank
The rank (within the communicator) that sent the message.
Examples found in repository?
examples/ring.rs (line 28)
7fn main() {
8 let universe = mpi::initialize().unwrap();
9 let world = universe.world();
10 let size = world.size();
11 let rank = world.rank();
12
13 let next_rank = (rank + 1) % size;
14 let previous_rank = (rank - 1 + size) % size;
15
16 let msg = [rank, 2 * rank, 4 * rank];
17 mpi::request::scope(|scope| {
18 let _sreq = WaitGuard::from(
19 world
20 .process_at_rank(next_rank)
21 .immediate_send(scope, &msg[..]),
22 );
23
24 let (msg, status) = world.any_process().receive_vec::<i32>();
25
26 println!(
27 "Rank {rank} received {msg:?} from rank {} (tag {}).",
28 status.source_rank(),
29 status.tag()
30 );
31 assert_eq!(status.source_rank(), previous_rank);
32 let x = previous_rank;
33 assert_eq!(vec![x, 2 * x, 4 * x], msg);
34 });
35
36 world.barrier();
37 if rank == 0 {
38 println!("Ring exchange completed successfully.");
39 }
40}More examples
examples/cluster.rs (line 34)
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}examples/spawn.rs (line 23)
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}examples/selftest.rs (line 24)
11fn main() {
12 let universe = mpi::initialize().unwrap();
13 let world = universe.world();
14 let rank = world.rank();
15 let size = world.size();
16
17 // ---- point-to-point: typed scalar ----
18 if size >= 2 {
19 if rank == 0 {
20 world.process_at_rank(1).send(&42u64);
21 } else if rank == 1 {
22 let (v, status) = world.process_at_rank(0).receive::<u64>();
23 assert_eq!(v, 42);
24 assert_eq!(status.source_rank(), 0);
25 }
26 }
27
28 // ---- point-to-point: vector + probe ----
29 if size >= 2 {
30 if rank == 0 {
31 let data: Vec<i32> = vec![10, 20, 30, 40, 50];
32 world.process_at_rank(1).send(&data[..]);
33 } else if rank == 1 {
34 let status = world.process_at_rank(0).probe();
35 let count = status.count(i32::equivalent_datatype());
36 assert_eq!(count, 5, "probe reported wrong count");
37 let (data, _s) = world.process_at_rank(0).receive_vec::<i32>();
38 assert_eq!(data, vec![10, 20, 30, 40, 50]);
39 }
40 }
41
42 // ---- send_receive ring ----
43 {
44 let next = (rank + 1) % size;
45 let prev = (rank - 1 + size) % size;
46 let (got, _status): (i32, _) = mpi::point_to_point::send_receive(
47 &rank,
48 &world.process_at_rank(next),
49 &world.process_at_rank(prev),
50 );
51 assert_eq!(got, prev, "send_receive ring mismatch");
52 }
53
54 // ---- broadcast ----
55 {
56 let root = world.process_at_rank(0);
57 let mut buf = if rank == 0 {
58 vec![2, 4, 8, 16]
59 } else {
60 vec![0; 4]
61 };
62 root.broadcast_into(&mut buf[..]);
63 assert_eq!(buf, vec![2, 4, 8, 16], "broadcast mismatch");
64 }
65
66 // ---- scatter ----
67 {
68 let root = world.process_at_rank(0);
69 let mut mine = 0i32;
70 if rank == 0 {
71 let send: Vec<i32> = (0..size).collect();
72 root.scatter_into_root(&send[..], &mut mine);
73 } else {
74 root.scatter_into(&mut mine);
75 }
76 assert_eq!(mine, rank, "scatter mismatch");
77 }
78
79 // ---- gather ----
80 {
81 let root = world.process_at_rank(0);
82 if rank == 0 {
83 let mut buf = vec![-1i32; size as usize];
84 root.gather_into_root(&rank, &mut buf[..]);
85 let expected: Vec<i32> = (0..size).collect();
86 assert_eq!(buf, expected, "gather mismatch");
87 } else {
88 root.gather_into(&rank);
89 }
90 }
91
92 // ---- all_gather ----
93 {
94 let mut buf = vec![-1i32; size as usize];
95 world.all_gather_into(&rank, &mut buf[..]);
96 let expected: Vec<i32> = (0..size).collect();
97 assert_eq!(buf, expected, "all_gather mismatch");
98 }
99
100 // ---- all_to_all ----
101 {
102 let send: Vec<i32> = (0..size).map(|j| rank * 100 + j).collect();
103 let mut recv = vec![-1i32; size as usize];
104 world.all_to_all_into(&send[..], &mut recv[..]);
105 for i in 0..size {
106 assert_eq!(recv[i as usize], i * 100 + rank, "all_to_all mismatch");
107 }
108 }
109
110 // ---- reduce to root (sum) ----
111 {
112 let root = world.process_at_rank(0);
113 if rank == 0 {
114 let mut sum = 0i32;
115 root.reduce_into_root(&rank, &mut sum, SystemOperation::sum());
116 assert_eq!(sum, (0..size).sum::<i32>(), "reduce sum mismatch");
117 } else {
118 root.reduce_into(&rank, SystemOperation::sum());
119 }
120 }
121
122 // ---- all_reduce (max) ----
123 {
124 let mut m = 0i32;
125 world.all_reduce_into(&rank, &mut m, SystemOperation::max());
126 assert_eq!(m, size - 1, "all_reduce max mismatch");
127 }
128
129 // ---- inclusive scan ----
130 {
131 let mut acc = 0i32;
132 world.scan_into(&rank, &mut acc, SystemOperation::sum());
133 let expected: i32 = (0..=rank).sum();
134 assert_eq!(acc, expected, "scan mismatch");
135 }
136
137 // ---- exclusive scan ----
138 {
139 let mut acc = -1i32;
140 world.exclusive_scan_into(&rank, &mut acc, SystemOperation::sum());
141 if rank > 0 {
142 let expected: i32 = (0..rank).sum();
143 assert_eq!(acc, expected, "exclusive_scan mismatch");
144 }
145 }
146
147 // ---- reduce_scatter_block ----
148 {
149 let send: Vec<i32> = vec![rank + 1; size as usize];
150 let mut recv = [0i32; 1];
151 world.reduce_scatter_block_into(&send[..], &mut recv[..], SystemOperation::sum());
152 let expected: i32 = (0..size).map(|k| k + 1).sum();
153 assert_eq!(recv[0], expected, "reduce_scatter_block mismatch");
154 }
155
156 // ---- user-defined operation (sum) matches built-in ----
157 {
158 let op = UserOperation::commutative(|inv: &[i32], inout: &mut [i32]| {
159 for (i, o) in inv.iter().zip(inout.iter_mut()) {
160 *o += *i;
161 }
162 });
163 let mut u = 0i32;
164 world.all_reduce_into(&rank, &mut u, op);
165 assert_eq!(u, (0..size).sum::<i32>(), "user op mismatch");
166 }
167
168 // ---- communicator split by parity ----
169 {
170 let color = mpi::topology::Color::with_value(rank % 2);
171 let sub = world.split_by_color(color).expect("split produced None");
172 let expected_size = (0..size).filter(|r| r % 2 == rank % 2).count() as i32;
173 assert_eq!(sub.size(), expected_size, "split size mismatch");
174 // Ranks in the sub-communicator sum to a known value.
175 let mut s = 0i32;
176 sub.all_reduce_into(&sub.rank(), &mut s, SystemOperation::sum());
177 let expected_sum: i32 = (0..sub.size()).sum();
178 assert_eq!(s, expected_sum, "split all_reduce mismatch");
179 }
180
181 // ---- communicator duplicate ----
182 {
183 let dup = world.duplicate();
184 assert_eq!(dup.size(), size);
185 assert_eq!(dup.rank(), rank);
186 dup.barrier();
187 }
188
189 // ---- group ----
190 {
191 let g = world.group();
192 assert_eq!(g.size(), size, "group size mismatch");
193 assert_eq!(g.rank(), Some(rank), "group rank mismatch");
194 }
195
196 // ---- group set algebra ----
197 {
198 let g = world.group();
199 let evens: Vec<i32> = (0..size).filter(|r| r % 2 == 0).collect();
200 let odds: Vec<i32> = (0..size).filter(|r| r % 2 == 1).collect();
201 let ge = g.include(&evens);
202 let go = g.include(&odds);
203 assert_eq!(ge.size() + go.size(), size, "group split size mismatch");
204 assert_eq!(ge.union(&go).size(), size, "group union mismatch");
205 assert_eq!(
206 ge.intersection(&go).size(),
207 0,
208 "group intersection mismatch"
209 );
210 }
211
212 // ---- varying-count all-gather (allgatherv) ----
213 {
214 let counts: Vec<i32> = (0..size).map(|i| i + 1).collect();
215 let mut displs = vec![0i32; size as usize];
216 for i in 1..size as usize {
217 displs[i] = displs[i - 1] + counts[i - 1];
218 }
219 let total: i32 = counts.iter().sum();
220 let send = vec![rank; (rank + 1) as usize];
221 let mut recvbuf = vec![-1i32; total as usize];
222 {
223 let mut part = PartitionMut::new(&mut recvbuf[..], counts.clone(), displs.clone());
224 world.all_gather_varcount_into(&send[..], &mut part);
225 }
226 for i in 0..size as usize {
227 let start = displs[i] as usize;
228 for k in 0..counts[i] as usize {
229 assert_eq!(recvbuf[start + k], i as i32, "allgatherv mismatch");
230 }
231 }
232 }
233
234 // ---- varying-count all-to-all (alltoallv) ----
235 {
236 let counts: Vec<i32> = vec![1; size as usize];
237 let displs: Vec<i32> = (0..size).collect();
238 let send: Vec<i32> = (0..size).map(|j| rank * 10 + j).collect();
239 let mut recv = vec![-1i32; size as usize];
240 {
241 let sp = Partition::new(&send[..], counts.clone(), displs.clone());
242 let mut rp = PartitionMut::new(&mut recv[..], counts.clone(), displs.clone());
243 world.all_to_all_varcount_into(&sp, &mut rp);
244 }
245 for i in 0..size {
246 assert_eq!(recv[i as usize], i * 10 + rank, "alltoallv mismatch");
247 }
248 }
249
250 // ---- Cartesian topology (1-D periodic ring) ----
251 {
252 let cart = world
253 .create_cartesian_communicator(&[size], &[true], false)
254 .expect("cartesian create returned None");
255 assert_eq!(cart.my_coordinates(), vec![rank], "cart coords mismatch");
256 let (src, dst) = cart.shift(0, 1);
257 assert_eq!(dst, Some((rank + 1) % size), "cart shift dest mismatch");
258 assert_eq!(
259 src,
260 Some((rank - 1 + size) % size),
261 "cart shift source mismatch"
262 );
263 assert_eq!(cart.rank_from_coordinates(&[0]), Some(0));
264 cart.barrier();
265 }
266
267 // ---- error handlers ----
268 {
269 use mpi::error::{class, error_string, ErrorHandler};
270 world.set_error_handler(ErrorHandler::Return);
271 assert_eq!(
272 world.error_handler(),
273 ErrorHandler::Return,
274 "errhandler mismatch"
275 );
276 world.set_error_handler(ErrorHandler::Fatal);
277 assert_eq!(world.error_handler(), ErrorHandler::Fatal);
278 assert!(!error_string(class::TRUNCATE).is_empty());
279 }
280
281 // ---- generalized request (completed from another thread) ----
282 {
283 use mpi::request::GeneralizedRequest;
284 let (req, completer) = GeneralizedRequest::start();
285 let handle = std::thread::spawn(move || completer.complete());
286 let _status = req.wait();
287 handle.join().unwrap();
288 }
289
290 // ---- pack / unpack ----
291 {
292 let val = vec![rank, rank * 2, rank * 3];
293 let packed = world.pack(&val[..]);
294 let mut out = vec![0i32; 3];
295 let pos = unsafe { world.unpack_into(&packed, &mut out[..], 0) };
296 assert_eq!(out, val, "pack/unpack mismatch");
297 assert_eq!(pos as usize, packed.len(), "unpack position mismatch");
298 }
299
300 // ---- communicator naming ----
301 {
302 assert_eq!(world.get_name(), "MPI_COMM_WORLD", "comm name mismatch");
303 let d = world.duplicate();
304 d.set_name("dup");
305 assert_eq!(d.get_name(), "dup", "set/get name mismatch");
306 }
307
308 // ---- non-blocking all-reduce + barrier ----
309 {
310 let send = rank;
311 let mut recv = 0i32;
312 mpi::request::scope(|s| {
313 world
314 .immediate_all_reduce_into(s, &send, &mut recv, SystemOperation::sum())
315 .wait();
316 });
317 assert_eq!(
318 recv,
319 (0..size).sum::<i32>(),
320 "immediate all_reduce mismatch"
321 );
322 world.immediate_barrier().wait();
323 }
324
325 // ---- non-blocking broadcast (Root) ----
326 {
327 let root = world.process_at_rank(0);
328 let mut buf = if rank == 0 {
329 vec![7, 7, 7]
330 } else {
331 vec![0, 0, 0]
332 };
333 mpi::request::scope(|s| {
334 root.immediate_broadcast_into(s, &mut buf[..]).wait();
335 });
336 assert_eq!(buf, vec![7, 7, 7], "immediate broadcast mismatch");
337 }
338
339 // ---- in-place all-reduce (MPI_IN_PLACE) ----
340 {
341 let mut b = vec![rank, rank + 1];
342 world.all_reduce_into_in_place(&mut b[..], SystemOperation::sum());
343 let s: i32 = (0..size).sum();
344 assert_eq!(b, vec![s, s + size], "in-place all_reduce mismatch");
345 }
346
347 // ---- persistent send/receive, reused across iterations ----
348 {
349 let next = (rank + 1) % size;
350 let prev = (rank - 1 + size) % size;
351 let sendbuf = [rank, rank * 2];
352 let mut recvbuf = vec![-1i32; 2];
353 {
354 let mut sreq = world.process_at_rank(next).send_init(&sendbuf[..]);
355 let mut rreq = world.process_at_rank(prev).receive_init(&mut recvbuf[..]);
356 for _ in 0..3 {
357 rreq.start();
358 sreq.start();
359 sreq.wait();
360 rreq.wait();
361 }
362 } // requests dropped -> buffer borrows released
363 assert_eq!(recvbuf, vec![prev, prev * 2], "persistent request mismatch");
364 }
365
366 world.barrier();
367 if rank == 0 {
368 println!("SELFTEST PASS: all checks passed on {size} ranks.");
369 }
370}Sourcepub fn tag(&self) -> Tag
pub fn tag(&self) -> Tag
The tag the message was sent with.
Examples found in repository?
examples/ring.rs (line 29)
7fn main() {
8 let universe = mpi::initialize().unwrap();
9 let world = universe.world();
10 let size = world.size();
11 let rank = world.rank();
12
13 let next_rank = (rank + 1) % size;
14 let previous_rank = (rank - 1 + size) % size;
15
16 let msg = [rank, 2 * rank, 4 * rank];
17 mpi::request::scope(|scope| {
18 let _sreq = WaitGuard::from(
19 world
20 .process_at_rank(next_rank)
21 .immediate_send(scope, &msg[..]),
22 );
23
24 let (msg, status) = world.any_process().receive_vec::<i32>();
25
26 println!(
27 "Rank {rank} received {msg:?} from rank {} (tag {}).",
28 status.source_rank(),
29 status.tag()
30 );
31 assert_eq!(status.source_rank(), previous_rank);
32 let x = previous_rank;
33 assert_eq!(vec![x, 2 * x, 4 * x], msg);
34 });
35
36 world.barrier();
37 if rank == 0 {
38 println!("Ring exchange completed successfully.");
39 }
40}More examples
examples/thread_multiple.rs (line 28)
10fn main() {
11 let universe = mpi::initialize().unwrap();
12 let world = universe.world();
13 let rank = world.rank();
14 let size = world.size();
15
16 let next = (rank + 1) % size;
17 let prev = (rank - 1 + size) % size;
18
19 let handles: Vec<_> = (0..THREADS)
20 .map(|t| {
21 let w = world.clone(); // SimpleCommunicator is Send + Sync (Arc)
22 thread::spawn(move || {
23 let tag = 1000 + t;
24 let msg = [rank * 100 + t, rank, t];
25 // Concurrent send + receive on this thread's own tag.
26 w.process_at_rank(next).send_with_tag(&msg[..], tag);
27 let (got, status) = w.process_at_rank(prev).receive_vec_with_tag::<i32>(tag);
28 assert_eq!(status.tag(), tag, "tag mismatch");
29 assert_eq!(
30 got,
31 vec![prev * 100 + t, prev, t],
32 "thread {t} payload mismatch"
33 );
34 })
35 })
36 .collect();
37
38 for h in handles {
39 h.join().expect("thread panicked");
40 }
41
42 world.barrier();
43 if rank == 0 {
44 println!(
45 "THREAD PASS: {THREADS} threads/rank did concurrent tagged exchanges on {size} ranks."
46 );
47 }
48}Sourcepub fn count(&self, dt: DatatypeRef) -> Count
pub fn count(&self, dt: DatatypeRef) -> Count
Number of elements of datatype dt in the message.
Examples found in repository?
examples/selftest.rs (line 35)
11fn main() {
12 let universe = mpi::initialize().unwrap();
13 let world = universe.world();
14 let rank = world.rank();
15 let size = world.size();
16
17 // ---- point-to-point: typed scalar ----
18 if size >= 2 {
19 if rank == 0 {
20 world.process_at_rank(1).send(&42u64);
21 } else if rank == 1 {
22 let (v, status) = world.process_at_rank(0).receive::<u64>();
23 assert_eq!(v, 42);
24 assert_eq!(status.source_rank(), 0);
25 }
26 }
27
28 // ---- point-to-point: vector + probe ----
29 if size >= 2 {
30 if rank == 0 {
31 let data: Vec<i32> = vec![10, 20, 30, 40, 50];
32 world.process_at_rank(1).send(&data[..]);
33 } else if rank == 1 {
34 let status = world.process_at_rank(0).probe();
35 let count = status.count(i32::equivalent_datatype());
36 assert_eq!(count, 5, "probe reported wrong count");
37 let (data, _s) = world.process_at_rank(0).receive_vec::<i32>();
38 assert_eq!(data, vec![10, 20, 30, 40, 50]);
39 }
40 }
41
42 // ---- send_receive ring ----
43 {
44 let next = (rank + 1) % size;
45 let prev = (rank - 1 + size) % size;
46 let (got, _status): (i32, _) = mpi::point_to_point::send_receive(
47 &rank,
48 &world.process_at_rank(next),
49 &world.process_at_rank(prev),
50 );
51 assert_eq!(got, prev, "send_receive ring mismatch");
52 }
53
54 // ---- broadcast ----
55 {
56 let root = world.process_at_rank(0);
57 let mut buf = if rank == 0 {
58 vec![2, 4, 8, 16]
59 } else {
60 vec![0; 4]
61 };
62 root.broadcast_into(&mut buf[..]);
63 assert_eq!(buf, vec![2, 4, 8, 16], "broadcast mismatch");
64 }
65
66 // ---- scatter ----
67 {
68 let root = world.process_at_rank(0);
69 let mut mine = 0i32;
70 if rank == 0 {
71 let send: Vec<i32> = (0..size).collect();
72 root.scatter_into_root(&send[..], &mut mine);
73 } else {
74 root.scatter_into(&mut mine);
75 }
76 assert_eq!(mine, rank, "scatter mismatch");
77 }
78
79 // ---- gather ----
80 {
81 let root = world.process_at_rank(0);
82 if rank == 0 {
83 let mut buf = vec![-1i32; size as usize];
84 root.gather_into_root(&rank, &mut buf[..]);
85 let expected: Vec<i32> = (0..size).collect();
86 assert_eq!(buf, expected, "gather mismatch");
87 } else {
88 root.gather_into(&rank);
89 }
90 }
91
92 // ---- all_gather ----
93 {
94 let mut buf = vec![-1i32; size as usize];
95 world.all_gather_into(&rank, &mut buf[..]);
96 let expected: Vec<i32> = (0..size).collect();
97 assert_eq!(buf, expected, "all_gather mismatch");
98 }
99
100 // ---- all_to_all ----
101 {
102 let send: Vec<i32> = (0..size).map(|j| rank * 100 + j).collect();
103 let mut recv = vec![-1i32; size as usize];
104 world.all_to_all_into(&send[..], &mut recv[..]);
105 for i in 0..size {
106 assert_eq!(recv[i as usize], i * 100 + rank, "all_to_all mismatch");
107 }
108 }
109
110 // ---- reduce to root (sum) ----
111 {
112 let root = world.process_at_rank(0);
113 if rank == 0 {
114 let mut sum = 0i32;
115 root.reduce_into_root(&rank, &mut sum, SystemOperation::sum());
116 assert_eq!(sum, (0..size).sum::<i32>(), "reduce sum mismatch");
117 } else {
118 root.reduce_into(&rank, SystemOperation::sum());
119 }
120 }
121
122 // ---- all_reduce (max) ----
123 {
124 let mut m = 0i32;
125 world.all_reduce_into(&rank, &mut m, SystemOperation::max());
126 assert_eq!(m, size - 1, "all_reduce max mismatch");
127 }
128
129 // ---- inclusive scan ----
130 {
131 let mut acc = 0i32;
132 world.scan_into(&rank, &mut acc, SystemOperation::sum());
133 let expected: i32 = (0..=rank).sum();
134 assert_eq!(acc, expected, "scan mismatch");
135 }
136
137 // ---- exclusive scan ----
138 {
139 let mut acc = -1i32;
140 world.exclusive_scan_into(&rank, &mut acc, SystemOperation::sum());
141 if rank > 0 {
142 let expected: i32 = (0..rank).sum();
143 assert_eq!(acc, expected, "exclusive_scan mismatch");
144 }
145 }
146
147 // ---- reduce_scatter_block ----
148 {
149 let send: Vec<i32> = vec![rank + 1; size as usize];
150 let mut recv = [0i32; 1];
151 world.reduce_scatter_block_into(&send[..], &mut recv[..], SystemOperation::sum());
152 let expected: i32 = (0..size).map(|k| k + 1).sum();
153 assert_eq!(recv[0], expected, "reduce_scatter_block mismatch");
154 }
155
156 // ---- user-defined operation (sum) matches built-in ----
157 {
158 let op = UserOperation::commutative(|inv: &[i32], inout: &mut [i32]| {
159 for (i, o) in inv.iter().zip(inout.iter_mut()) {
160 *o += *i;
161 }
162 });
163 let mut u = 0i32;
164 world.all_reduce_into(&rank, &mut u, op);
165 assert_eq!(u, (0..size).sum::<i32>(), "user op mismatch");
166 }
167
168 // ---- communicator split by parity ----
169 {
170 let color = mpi::topology::Color::with_value(rank % 2);
171 let sub = world.split_by_color(color).expect("split produced None");
172 let expected_size = (0..size).filter(|r| r % 2 == rank % 2).count() as i32;
173 assert_eq!(sub.size(), expected_size, "split size mismatch");
174 // Ranks in the sub-communicator sum to a known value.
175 let mut s = 0i32;
176 sub.all_reduce_into(&sub.rank(), &mut s, SystemOperation::sum());
177 let expected_sum: i32 = (0..sub.size()).sum();
178 assert_eq!(s, expected_sum, "split all_reduce mismatch");
179 }
180
181 // ---- communicator duplicate ----
182 {
183 let dup = world.duplicate();
184 assert_eq!(dup.size(), size);
185 assert_eq!(dup.rank(), rank);
186 dup.barrier();
187 }
188
189 // ---- group ----
190 {
191 let g = world.group();
192 assert_eq!(g.size(), size, "group size mismatch");
193 assert_eq!(g.rank(), Some(rank), "group rank mismatch");
194 }
195
196 // ---- group set algebra ----
197 {
198 let g = world.group();
199 let evens: Vec<i32> = (0..size).filter(|r| r % 2 == 0).collect();
200 let odds: Vec<i32> = (0..size).filter(|r| r % 2 == 1).collect();
201 let ge = g.include(&evens);
202 let go = g.include(&odds);
203 assert_eq!(ge.size() + go.size(), size, "group split size mismatch");
204 assert_eq!(ge.union(&go).size(), size, "group union mismatch");
205 assert_eq!(
206 ge.intersection(&go).size(),
207 0,
208 "group intersection mismatch"
209 );
210 }
211
212 // ---- varying-count all-gather (allgatherv) ----
213 {
214 let counts: Vec<i32> = (0..size).map(|i| i + 1).collect();
215 let mut displs = vec![0i32; size as usize];
216 for i in 1..size as usize {
217 displs[i] = displs[i - 1] + counts[i - 1];
218 }
219 let total: i32 = counts.iter().sum();
220 let send = vec![rank; (rank + 1) as usize];
221 let mut recvbuf = vec![-1i32; total as usize];
222 {
223 let mut part = PartitionMut::new(&mut recvbuf[..], counts.clone(), displs.clone());
224 world.all_gather_varcount_into(&send[..], &mut part);
225 }
226 for i in 0..size as usize {
227 let start = displs[i] as usize;
228 for k in 0..counts[i] as usize {
229 assert_eq!(recvbuf[start + k], i as i32, "allgatherv mismatch");
230 }
231 }
232 }
233
234 // ---- varying-count all-to-all (alltoallv) ----
235 {
236 let counts: Vec<i32> = vec![1; size as usize];
237 let displs: Vec<i32> = (0..size).collect();
238 let send: Vec<i32> = (0..size).map(|j| rank * 10 + j).collect();
239 let mut recv = vec![-1i32; size as usize];
240 {
241 let sp = Partition::new(&send[..], counts.clone(), displs.clone());
242 let mut rp = PartitionMut::new(&mut recv[..], counts.clone(), displs.clone());
243 world.all_to_all_varcount_into(&sp, &mut rp);
244 }
245 for i in 0..size {
246 assert_eq!(recv[i as usize], i * 10 + rank, "alltoallv mismatch");
247 }
248 }
249
250 // ---- Cartesian topology (1-D periodic ring) ----
251 {
252 let cart = world
253 .create_cartesian_communicator(&[size], &[true], false)
254 .expect("cartesian create returned None");
255 assert_eq!(cart.my_coordinates(), vec![rank], "cart coords mismatch");
256 let (src, dst) = cart.shift(0, 1);
257 assert_eq!(dst, Some((rank + 1) % size), "cart shift dest mismatch");
258 assert_eq!(
259 src,
260 Some((rank - 1 + size) % size),
261 "cart shift source mismatch"
262 );
263 assert_eq!(cart.rank_from_coordinates(&[0]), Some(0));
264 cart.barrier();
265 }
266
267 // ---- error handlers ----
268 {
269 use mpi::error::{class, error_string, ErrorHandler};
270 world.set_error_handler(ErrorHandler::Return);
271 assert_eq!(
272 world.error_handler(),
273 ErrorHandler::Return,
274 "errhandler mismatch"
275 );
276 world.set_error_handler(ErrorHandler::Fatal);
277 assert_eq!(world.error_handler(), ErrorHandler::Fatal);
278 assert!(!error_string(class::TRUNCATE).is_empty());
279 }
280
281 // ---- generalized request (completed from another thread) ----
282 {
283 use mpi::request::GeneralizedRequest;
284 let (req, completer) = GeneralizedRequest::start();
285 let handle = std::thread::spawn(move || completer.complete());
286 let _status = req.wait();
287 handle.join().unwrap();
288 }
289
290 // ---- pack / unpack ----
291 {
292 let val = vec![rank, rank * 2, rank * 3];
293 let packed = world.pack(&val[..]);
294 let mut out = vec![0i32; 3];
295 let pos = unsafe { world.unpack_into(&packed, &mut out[..], 0) };
296 assert_eq!(out, val, "pack/unpack mismatch");
297 assert_eq!(pos as usize, packed.len(), "unpack position mismatch");
298 }
299
300 // ---- communicator naming ----
301 {
302 assert_eq!(world.get_name(), "MPI_COMM_WORLD", "comm name mismatch");
303 let d = world.duplicate();
304 d.set_name("dup");
305 assert_eq!(d.get_name(), "dup", "set/get name mismatch");
306 }
307
308 // ---- non-blocking all-reduce + barrier ----
309 {
310 let send = rank;
311 let mut recv = 0i32;
312 mpi::request::scope(|s| {
313 world
314 .immediate_all_reduce_into(s, &send, &mut recv, SystemOperation::sum())
315 .wait();
316 });
317 assert_eq!(
318 recv,
319 (0..size).sum::<i32>(),
320 "immediate all_reduce mismatch"
321 );
322 world.immediate_barrier().wait();
323 }
324
325 // ---- non-blocking broadcast (Root) ----
326 {
327 let root = world.process_at_rank(0);
328 let mut buf = if rank == 0 {
329 vec![7, 7, 7]
330 } else {
331 vec![0, 0, 0]
332 };
333 mpi::request::scope(|s| {
334 root.immediate_broadcast_into(s, &mut buf[..]).wait();
335 });
336 assert_eq!(buf, vec![7, 7, 7], "immediate broadcast mismatch");
337 }
338
339 // ---- in-place all-reduce (MPI_IN_PLACE) ----
340 {
341 let mut b = vec![rank, rank + 1];
342 world.all_reduce_into_in_place(&mut b[..], SystemOperation::sum());
343 let s: i32 = (0..size).sum();
344 assert_eq!(b, vec![s, s + size], "in-place all_reduce mismatch");
345 }
346
347 // ---- persistent send/receive, reused across iterations ----
348 {
349 let next = (rank + 1) % size;
350 let prev = (rank - 1 + size) % size;
351 let sendbuf = [rank, rank * 2];
352 let mut recvbuf = vec![-1i32; 2];
353 {
354 let mut sreq = world.process_at_rank(next).send_init(&sendbuf[..]);
355 let mut rreq = world.process_at_rank(prev).receive_init(&mut recvbuf[..]);
356 for _ in 0..3 {
357 rreq.start();
358 sreq.start();
359 sreq.wait();
360 rreq.wait();
361 }
362 } // requests dropped -> buffer borrows released
363 assert_eq!(recvbuf, vec![prev, prev * 2], "persistent request mismatch");
364 }
365
366 world.barrier();
367 if rank == 0 {
368 println!("SELFTEST PASS: all checks passed on {size} ranks.");
369 }
370}Sourcepub fn is_cancelled(&self) -> bool
pub fn is_cancelled(&self) -> bool
Whether the matching operation was cancelled. Always false in this
implementation (cancellation of already-buffered messages is a no-op).
Sourcepub fn is_canceled(&self) -> bool
pub fn is_canceled(&self) -> bool
American-spelling alias of Status::is_cancelled.
Trait Implementations§
impl Copy for Status
impl Eq for Status
impl StructuralPartialEq for Status
Auto Trait Implementations§
impl Freeze for Status
impl RefUnwindSafe for Status
impl Send for Status
impl Sync for Status
impl Unpin for Status
impl UnsafeUnpin for Status
impl UnwindSafe for Status
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more