pub struct Window<T: RmaElement> { /* private fields */ }Expand description
MPI-allocated homogeneous memory exposed to the communicator.
Send + Sync once constructed. Construction requires
MPI_THREAD_MULTIPLE; the access epoch is entered inside allocate and
left in close or Drop, and no public API exposes
epoch transitions. All reads and writes are issued through the
put/get/fetch_add family, each completed at the target before
returning; no Rust reference into remotely mutable storage is ever
exposed.
Implementations§
Source§impl<T: RmaElement> Window<T>
impl<T: RmaElement> Window<T>
Sourcepub fn len(&self) -> usize
pub fn len(&self) -> usize
Number of locally allocated elements.
Examples found in repository?
11fn main() {
12 let (universe, provided) =
13 mpi::initialize_with_threading(Threading::Multiple).expect("MPI must initialize once");
14 assert_eq!(provided, Threading::Multiple);
15 let world = universe.world();
16 let rank = world.rank();
17 let size = world.size();
18 assert_eq!(size, 2);
19 let next = (rank + 1) % size;
20 let prev = (rank + size - 1) % size;
21
22 // Element type must agree across ranks.
23 if rank == 0 {
24 assert!(matches!(
25 world.allocate_window::<u8>(1),
26 Err(Error::Window("element type differs between ranks"))
27 ));
28 } else {
29 assert!(matches!(
30 world.allocate_window::<u64>(2),
31 Err(Error::Window("element type differs between ranks"))
32 ));
33 }
34
35 // Self put/get, bounds, fetch_add; relies on Drop for shutdown.
36 {
37 let win = world.allocate_window::<u64>(8).unwrap();
38 win.put(rank, 0, &[rank as u64 + 10, rank as u64 + 20])
39 .unwrap();
40 let mut got = [0; 8];
41 win.get(rank, 0, &mut got).unwrap();
42 assert_eq!(got[0], rank as u64 + 10);
43 assert_eq!(got[1], rank as u64 + 20);
44
45 assert!(matches!(
46 win.put(rank, win.len(), &[1]),
47 Err(Error::Range { .. })
48 ));
49 assert!(matches!(win.put(-1, 0, &[1]), Err(Error::Rank(-1))));
50 assert!(matches!(win.put(size, 0, &[1]), Err(Error::Rank(_))));
51 assert!(matches!(
52 win.get(rank, win.len(), &mut [0]),
53 Err(Error::Range { .. })
54 ));
55
56 assert_eq!(win.fetch_add(rank, 7, rank as u64 + 1).unwrap(), 0);
57 assert_eq!(win.fetch_add(rank, 7, 0).unwrap(), rank as u64 + 1);
58 world.barrier();
59 }
60
61 // Cross-rank exchange.
62 {
63 let win = world.allocate_window::<u64>(8).unwrap();
64 win.put(next, 0, &[rank as u64 + 100]).unwrap();
65 world.barrier();
66 let mut got = [0u64; 1];
67 win.get(rank, 0, &mut got).unwrap();
68 assert_eq!(got[0], prev as u64 + 100);
69 world.barrier();
70 win.close().unwrap();
71 }
72
73 if rank == 0 {
74 println!("test_window: ok");
75 }
76}Sourcepub fn memory_model(&self) -> MemoryModel
pub fn memory_model(&self) -> MemoryModel
Memory model reported by MPI_WIN_MODEL.
Sourcepub fn sync(&self) -> Result<(), Error>
pub fn sync(&self) -> Result<(), Error>
Make remote updates visible to local memory accesses.
Required after a remote put on a separate-model window before any local read can observe the new contents.
Sourcepub fn read_local(&self, disp: usize, out: &mut [T]) -> Result<(), Error>
pub fn read_local(&self, disp: usize, out: &mut [T]) -> Result<(), Error>
Copy a region from this rank’s local window storage.
Concurrent remote updates to the same region yield undefined
contents; the caller is responsible for the ordering. Volatile
reads of single scalars are provided by
read_local_volatile.
Sourcepub fn read_local_volatile(
&self,
disp: usize,
out: &mut [T],
) -> Result<(), Error>
pub fn read_local_volatile( &self, disp: usize, out: &mut [T], ) -> Result<(), Error>
Volatile local copy for scalars concurrently mutated by an RMA operation.
Sourcepub fn put(&self, dest: Rank, disp: usize, data: &[T]) -> Result<(), Error>
pub fn put(&self, dest: Rank, disp: usize, data: &[T]) -> Result<(), Error>
Put a contiguous region and complete the transfer at the target before return.
The transfer reaches remote completion (target’s public window
visible to subsequent get from any process) before this returns.
§Errors
Error::Rankifdestis outside the window communicator.Error::Rangeifdisp + data.len()exceeds the target’s window length.Error::CountOverflowifdata.len()does not fit anMPI Count.Error::Mpiif the MPI call fails.
Examples found in repository?
11fn main() {
12 let (universe, provided) =
13 mpi::initialize_with_threading(Threading::Multiple).expect("MPI must initialize once");
14 assert_eq!(provided, Threading::Multiple);
15 let world = universe.world();
16 let rank = world.rank();
17 let size = world.size();
18 assert_eq!(size, 2);
19 let next = (rank + 1) % size;
20 let prev = (rank + size - 1) % size;
21
22 // Element type must agree across ranks.
23 if rank == 0 {
24 assert!(matches!(
25 world.allocate_window::<u8>(1),
26 Err(Error::Window("element type differs between ranks"))
27 ));
28 } else {
29 assert!(matches!(
30 world.allocate_window::<u64>(2),
31 Err(Error::Window("element type differs between ranks"))
32 ));
33 }
34
35 // Self put/get, bounds, fetch_add; relies on Drop for shutdown.
36 {
37 let win = world.allocate_window::<u64>(8).unwrap();
38 win.put(rank, 0, &[rank as u64 + 10, rank as u64 + 20])
39 .unwrap();
40 let mut got = [0; 8];
41 win.get(rank, 0, &mut got).unwrap();
42 assert_eq!(got[0], rank as u64 + 10);
43 assert_eq!(got[1], rank as u64 + 20);
44
45 assert!(matches!(
46 win.put(rank, win.len(), &[1]),
47 Err(Error::Range { .. })
48 ));
49 assert!(matches!(win.put(-1, 0, &[1]), Err(Error::Rank(-1))));
50 assert!(matches!(win.put(size, 0, &[1]), Err(Error::Rank(_))));
51 assert!(matches!(
52 win.get(rank, win.len(), &mut [0]),
53 Err(Error::Range { .. })
54 ));
55
56 assert_eq!(win.fetch_add(rank, 7, rank as u64 + 1).unwrap(), 0);
57 assert_eq!(win.fetch_add(rank, 7, 0).unwrap(), rank as u64 + 1);
58 world.barrier();
59 }
60
61 // Cross-rank exchange.
62 {
63 let win = world.allocate_window::<u64>(8).unwrap();
64 win.put(next, 0, &[rank as u64 + 100]).unwrap();
65 world.barrier();
66 let mut got = [0u64; 1];
67 win.get(rank, 0, &mut got).unwrap();
68 assert_eq!(got[0], prev as u64 + 100);
69 world.barrier();
70 win.close().unwrap();
71 }
72
73 if rank == 0 {
74 println!("test_window: ok");
75 }
76}Sourcepub fn get(&self, source: Rank, disp: usize, out: &mut [T]) -> Result<(), Error>
pub fn get(&self, source: Rank, disp: usize, out: &mut [T]) -> Result<(), Error>
Get a contiguous region and complete the transfer before return.
§Errors
Error::Rankifsourceis outside the window communicator.Error::Rangeifdisp + out.len()exceeds the source’s window length.Error::CountOverflowifout.len()does not fit anMPI Count.Error::Mpiif the MPI call fails.
Examples found in repository?
11fn main() {
12 let (universe, provided) =
13 mpi::initialize_with_threading(Threading::Multiple).expect("MPI must initialize once");
14 assert_eq!(provided, Threading::Multiple);
15 let world = universe.world();
16 let rank = world.rank();
17 let size = world.size();
18 assert_eq!(size, 2);
19 let next = (rank + 1) % size;
20 let prev = (rank + size - 1) % size;
21
22 // Element type must agree across ranks.
23 if rank == 0 {
24 assert!(matches!(
25 world.allocate_window::<u8>(1),
26 Err(Error::Window("element type differs between ranks"))
27 ));
28 } else {
29 assert!(matches!(
30 world.allocate_window::<u64>(2),
31 Err(Error::Window("element type differs between ranks"))
32 ));
33 }
34
35 // Self put/get, bounds, fetch_add; relies on Drop for shutdown.
36 {
37 let win = world.allocate_window::<u64>(8).unwrap();
38 win.put(rank, 0, &[rank as u64 + 10, rank as u64 + 20])
39 .unwrap();
40 let mut got = [0; 8];
41 win.get(rank, 0, &mut got).unwrap();
42 assert_eq!(got[0], rank as u64 + 10);
43 assert_eq!(got[1], rank as u64 + 20);
44
45 assert!(matches!(
46 win.put(rank, win.len(), &[1]),
47 Err(Error::Range { .. })
48 ));
49 assert!(matches!(win.put(-1, 0, &[1]), Err(Error::Rank(-1))));
50 assert!(matches!(win.put(size, 0, &[1]), Err(Error::Rank(_))));
51 assert!(matches!(
52 win.get(rank, win.len(), &mut [0]),
53 Err(Error::Range { .. })
54 ));
55
56 assert_eq!(win.fetch_add(rank, 7, rank as u64 + 1).unwrap(), 0);
57 assert_eq!(win.fetch_add(rank, 7, 0).unwrap(), rank as u64 + 1);
58 world.barrier();
59 }
60
61 // Cross-rank exchange.
62 {
63 let win = world.allocate_window::<u64>(8).unwrap();
64 win.put(next, 0, &[rank as u64 + 100]).unwrap();
65 world.barrier();
66 let mut got = [0u64; 1];
67 win.get(rank, 0, &mut got).unwrap();
68 assert_eq!(got[0], prev as u64 + 100);
69 world.barrier();
70 win.close().unwrap();
71 }
72
73 if rank == 0 {
74 println!("test_window: ok");
75 }
76}Sourcepub fn fetch_add(&self, dest: Rank, disp: usize, value: T) -> Result<T, Error>
pub fn fetch_add(&self, dest: Rank, disp: usize, value: T) -> Result<T, Error>
Atomically add value at the target and return the previous value.
§Errors
Error::Rankifdestis outside the window communicator.Error::Rangeifdispis outside the target’s window length.Error::Mpiif the MPI call fails.
Examples found in repository?
11fn main() {
12 let (universe, provided) =
13 mpi::initialize_with_threading(Threading::Multiple).expect("MPI must initialize once");
14 assert_eq!(provided, Threading::Multiple);
15 let world = universe.world();
16 let rank = world.rank();
17 let size = world.size();
18 assert_eq!(size, 2);
19 let next = (rank + 1) % size;
20 let prev = (rank + size - 1) % size;
21
22 // Element type must agree across ranks.
23 if rank == 0 {
24 assert!(matches!(
25 world.allocate_window::<u8>(1),
26 Err(Error::Window("element type differs between ranks"))
27 ));
28 } else {
29 assert!(matches!(
30 world.allocate_window::<u64>(2),
31 Err(Error::Window("element type differs between ranks"))
32 ));
33 }
34
35 // Self put/get, bounds, fetch_add; relies on Drop for shutdown.
36 {
37 let win = world.allocate_window::<u64>(8).unwrap();
38 win.put(rank, 0, &[rank as u64 + 10, rank as u64 + 20])
39 .unwrap();
40 let mut got = [0; 8];
41 win.get(rank, 0, &mut got).unwrap();
42 assert_eq!(got[0], rank as u64 + 10);
43 assert_eq!(got[1], rank as u64 + 20);
44
45 assert!(matches!(
46 win.put(rank, win.len(), &[1]),
47 Err(Error::Range { .. })
48 ));
49 assert!(matches!(win.put(-1, 0, &[1]), Err(Error::Rank(-1))));
50 assert!(matches!(win.put(size, 0, &[1]), Err(Error::Rank(_))));
51 assert!(matches!(
52 win.get(rank, win.len(), &mut [0]),
53 Err(Error::Range { .. })
54 ));
55
56 assert_eq!(win.fetch_add(rank, 7, rank as u64 + 1).unwrap(), 0);
57 assert_eq!(win.fetch_add(rank, 7, 0).unwrap(), rank as u64 + 1);
58 world.barrier();
59 }
60
61 // Cross-rank exchange.
62 {
63 let win = world.allocate_window::<u64>(8).unwrap();
64 win.put(next, 0, &[rank as u64 + 100]).unwrap();
65 world.barrier();
66 let mut got = [0u64; 1];
67 win.get(rank, 0, &mut got).unwrap();
68 assert_eq!(got[0], prev as u64 + 100);
69 world.barrier();
70 win.close().unwrap();
71 }
72
73 if rank == 0 {
74 println!("test_window: ok");
75 }
76}Sourcepub fn close(self) -> Result<(), Error>
pub fn close(self) -> Result<(), Error>
Close the window. Collective over the window group.
Prefer this over relying on Drop: the destructor’s shutdown runs
the same steps but the collective boundary is implicit.
Examples found in repository?
11fn main() {
12 let (universe, provided) =
13 mpi::initialize_with_threading(Threading::Multiple).expect("MPI must initialize once");
14 assert_eq!(provided, Threading::Multiple);
15 let world = universe.world();
16 let rank = world.rank();
17 let size = world.size();
18 assert_eq!(size, 2);
19 let next = (rank + 1) % size;
20 let prev = (rank + size - 1) % size;
21
22 // Element type must agree across ranks.
23 if rank == 0 {
24 assert!(matches!(
25 world.allocate_window::<u8>(1),
26 Err(Error::Window("element type differs between ranks"))
27 ));
28 } else {
29 assert!(matches!(
30 world.allocate_window::<u64>(2),
31 Err(Error::Window("element type differs between ranks"))
32 ));
33 }
34
35 // Self put/get, bounds, fetch_add; relies on Drop for shutdown.
36 {
37 let win = world.allocate_window::<u64>(8).unwrap();
38 win.put(rank, 0, &[rank as u64 + 10, rank as u64 + 20])
39 .unwrap();
40 let mut got = [0; 8];
41 win.get(rank, 0, &mut got).unwrap();
42 assert_eq!(got[0], rank as u64 + 10);
43 assert_eq!(got[1], rank as u64 + 20);
44
45 assert!(matches!(
46 win.put(rank, win.len(), &[1]),
47 Err(Error::Range { .. })
48 ));
49 assert!(matches!(win.put(-1, 0, &[1]), Err(Error::Rank(-1))));
50 assert!(matches!(win.put(size, 0, &[1]), Err(Error::Rank(_))));
51 assert!(matches!(
52 win.get(rank, win.len(), &mut [0]),
53 Err(Error::Range { .. })
54 ));
55
56 assert_eq!(win.fetch_add(rank, 7, rank as u64 + 1).unwrap(), 0);
57 assert_eq!(win.fetch_add(rank, 7, 0).unwrap(), rank as u64 + 1);
58 world.barrier();
59 }
60
61 // Cross-rank exchange.
62 {
63 let win = world.allocate_window::<u64>(8).unwrap();
64 win.put(next, 0, &[rank as u64 + 100]).unwrap();
65 world.barrier();
66 let mut got = [0u64; 1];
67 win.get(rank, 0, &mut got).unwrap();
68 assert_eq!(got[0], prev as u64 + 100);
69 world.barrier();
70 win.close().unwrap();
71 }
72
73 if rank == 0 {
74 println!("test_window: ok");
75 }
76}