Function scope

Source
pub fn scope<'a, F, R>(f: F) -> R
where 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
Hide additional 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}