pub fn scope<'a, F, R>(f: F) -> Rwhere
F: FnOnce(&LocalScope<'a>) -> R,
Expand description
Used to create a LocalScope
The function creates a LocalScope
and then passes it into the given
closure as an argument.
For safety reasons, all variables and buffers associated with a request must exist outside the scope with which the request is registered.
It is typically used like this:
/* declare variables and buffers here ... */
mpi_fork_fnsp::request::scope(|scope| {
/* perform sends and/or receives using 'scope' */
});
/* at end of scope, panic if there are requests that have not yet completed */
ยงExamples
See examples/immediate.rs
Examples found in repository?
examples/immediate_all_to_all.rs (lines 15-19)
6fn main() {
7 let universe = mpi::initialize().unwrap();
8 let world = universe.world();
9 let rank = world.rank();
10 let size = world.size();
11
12 let u = vec![rank; size as usize];
13 let mut v = vec![0; size as usize];
14
15 mpi::request::scope(|scope| {
16 world
17 .immediate_all_to_all_into(scope, &u[..], &mut v[..])
18 .wait();
19 });
20
21 println!("u: {:?}", u);
22 println!("v: {:?}", v);
23
24 assert!(v.into_iter().zip(0..size).all(|(i, j)| i == j));
25}
More examples
examples/immediate_reduce.rs (lines 26-29)
15fn test_user_operations<C: Communicator>(comm: C) {
16 let op = UserOperation::commutative(|x, y| {
17 let x: &[Rank] = x.downcast().unwrap();
18 let y: &mut [Rank] = y.downcast().unwrap();
19 for (&x_i, y_i) in x.iter().zip(y) {
20 *y_i += x_i;
21 }
22 });
23 let rank = comm.rank();
24 let size = comm.size();
25 let mut c = 0;
26 mpi::request::scope(|scope| {
27 comm.immediate_all_reduce_into(scope, &rank, &mut c, &op)
28 .wait();
29 });
30 assert_eq!(c, size * (size - 1) / 2);
31}
32
33#[cfg(not(feature = "user-operations"))]
34fn test_user_operations<C: Communicator>(_: C) {}
35
36#[cfg(not(all(msmpi, target_arch = "x86")))]
37unsafe extern "C" fn unsafe_add(
38 invec: *mut c_void,
39 inoutvec: *mut c_void,
40 len: *mut c_int,
41 _datatype: *mut MPI_Datatype,
42) {
43 use std::slice;
44
45 let x: &[Rank] = slice::from_raw_parts(invec as *const Rank, *len as usize);
46 let y: &mut [Rank] = slice::from_raw_parts_mut(inoutvec as *mut Rank, *len as usize);
47 for (&x_i, y_i) in x.iter().zip(y) {
48 *y_i += x_i;
49 }
50}
51
52#[cfg(all(msmpi, target_arch = "x86"))]
53unsafe extern "stdcall" fn unsafe_add(
54 invec: *mut c_void,
55 inoutvec: *mut c_void,
56 len: *mut c_int,
57 _datatype: *mut MPI_Datatype,
58) {
59 use std::slice;
60
61 let x: &[Rank] = slice::from_raw_parts(invec as *const Rank, *len as usize);
62 let y: &mut [Rank] = slice::from_raw_parts_mut(inoutvec as *mut Rank, *len as usize);
63 for (&x_i, y_i) in x.iter().zip(y) {
64 *y_i += x_i;
65 }
66}
67
68fn main() {
69 let universe = mpi::initialize().unwrap();
70 let world = universe.world();
71 let rank = world.rank();
72 let size = world.size();
73 let root_rank = 0;
74
75 if rank == root_rank {
76 let mut sum: Rank = 0;
77 mpi::request::scope(|scope| {
78 world
79 .process_at_rank(root_rank)
80 .immediate_reduce_into_root(scope, &rank, &mut sum, SystemOperation::sum())
81 .wait();
82 });
83 assert_eq!(sum, size * (size - 1) / 2);
84 } else {
85 mpi::request::scope(|scope| {
86 world
87 .process_at_rank(root_rank)
88 .immediate_reduce_into(scope, &rank, SystemOperation::sum())
89 .wait();
90 });
91 }
92
93 let mut max: Rank = -1;
94
95 mpi::request::scope(|scope| {
96 world
97 .immediate_all_reduce_into(scope, &rank, &mut max, SystemOperation::max())
98 .wait();
99 });
100 assert_eq!(max, size - 1);
101
102 let a = (0..size).collect::<Vec<_>>();
103 let mut b: Rank = 0;
104
105 mpi::request::scope(|scope| {
106 world
107 .immediate_reduce_scatter_block_into(scope, &a[..], &mut b, SystemOperation::product())
108 .wait();
109 });
110 assert_eq!(b, rank.wrapping_pow(size as u32));
111
112 test_user_operations(universe.world());
113
114 let mut d = 0;
115 let op = unsafe { UnsafeUserOperation::commutative(unsafe_add) };
116 mpi::request::scope(|scope| {
117 world
118 .immediate_all_reduce_into(scope, &rank, &mut d, &op)
119 .wait();
120 });
121 assert_eq!(d, size * (size - 1) / 2);
122}
examples/immediate_scan.rs (lines 18-22)
12fn main() {
13 let universe = mpi::initialize().unwrap();
14 let world = universe.world();
15 let rank = world.rank();
16
17 let mut x = 0;
18 mpi::request::scope(|scope| {
19 world
20 .immediate_scan_into(scope, &rank, &mut x, SystemOperation::sum())
21 .wait();
22 });
23 assert_eq!(x, (rank * (rank + 1)) / 2);
24
25 let y = rank + 1;
26 let mut z = 0;
27 mpi::request::scope(|scope| {
28 world
29 .immediate_exclusive_scan_into(scope, &y, &mut z, SystemOperation::product())
30 .wait();
31 });
32 if rank > 0 {
33 assert_eq!(z, fac(y - 1));
34 }
35}
examples/immediate_scatter.rs (lines 18-21)
7fn main() {
8 let universe = mpi::initialize().unwrap();
9 let world = universe.world();
10 let rank = world.rank();
11 let size = world.size();
12 let root_rank = 0;
13 let root_process = world.process_at_rank(root_rank);
14
15 let mut x = 0 as Rank;
16 if rank == root_rank {
17 let v = (0..size).collect::<Vec<_>>();
18 mpi::request::scope(|scope| {
19 let req = root_process.immediate_scatter_into_root(scope, &v[..], &mut x);
20 req.wait();
21 });
22 } else {
23 mpi::request::scope(|scope| {
24 let req = root_process.immediate_scatter_into(scope, &mut x);
25 req.wait();
26 });
27 }
28 assert_eq!(x, rank);
29}
examples/buffered.rs (lines 24-31)
9fn main() {
10 let mut universe = mpi::initialize().unwrap();
11 // Try to attach a buffer.
12 universe.set_buffer_size(BUFFER_SIZE);
13 // Check buffer size matches.
14 assert_eq!(universe.buffer_size(), BUFFER_SIZE);
15 // Try to detach the buffer.
16 universe.detach_buffer();
17 // Attach another buffer.
18 universe.set_buffer_size(BUFFER_SIZE);
19
20 let world = universe.world();
21
22 let x = vec![std::f32::consts::PI; 1024];
23 let mut y = vec![0.0; 1024];
24 mpi::request::scope(|scope| {
25 let _rreq = WaitGuard::from(
26 world
27 .any_process()
28 .immediate_receive_into(scope, &mut y[..]),
29 );
30 world.this_process().buffered_send(&x[..]);
31 });
32 assert_eq!(x, y);
33}
examples/ready_send.rs (lines 19-33)
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 if rank > 0 {
14 let msg = rank as u8;
15 world.barrier();
16 world.process_at_rank(0).ready_send(&msg);
17 } else {
18 let mut v = vec![0u8; (size - 1) as usize];
19 mpi::request::scope(|scope| {
20 let reqs = v
21 .iter_mut()
22 .zip(1..)
23 .map(|(x, i)| {
24 world
25 .process_at_rank(i as Rank)
26 .immediate_receive_into(scope, x)
27 })
28 .collect::<Vec<_>>();
29 world.barrier();
30 for req in reqs {
31 req.wait();
32 }
33 });
34 println!("Got message: {:?}", v);
35 assert!(v.iter().zip(1..).all(|(x, i)| i == *x as usize));
36 }
37}
Additional examples can be found in: