pub trait Root: AsCommunicator {
Show 25 methods
// Required method
fn root_rank(&self) -> Rank;
// Provided methods
fn broadcast_into<Buf>(&self, buffer: &mut Buf)
where Buf: BufferMut + ?Sized { ... }
fn gather_into<S>(&self, sendbuf: &S)
where S: Buffer + ?Sized { ... }
fn gather_into_root<S, R>(&self, sendbuf: &S, recvbuf: &mut R)
where S: Buffer + ?Sized,
R: BufferMut + ?Sized { ... }
fn gather_varcount_into<S>(&self, sendbuf: &S)
where S: Buffer + ?Sized { ... }
fn gather_varcount_into_root<S, R>(&self, sendbuf: &S, recvbuf: &mut R)
where S: Buffer + ?Sized,
R: PartitionedBufferMut + ?Sized { ... }
fn scatter_into<R>(&self, recvbuf: &mut R)
where R: BufferMut + ?Sized { ... }
fn scatter_into_root<S, R>(&self, sendbuf: &S, recvbuf: &mut R)
where S: Buffer + ?Sized,
R: BufferMut + ?Sized { ... }
fn scatter_varcount_into<R>(&self, recvbuf: &mut R)
where R: BufferMut + ?Sized { ... }
fn scatter_varcount_into_root<S, R>(&self, sendbuf: &S, recvbuf: &mut R)
where S: PartitionedBuffer + ?Sized,
R: BufferMut + ?Sized { ... }
fn reduce_into<S, O>(&self, sendbuf: &S, op: O)
where S: Buffer + ?Sized,
O: Operation { ... }
fn reduce_into_root<S, R, O>(&self, sendbuf: &S, recvbuf: &mut R, op: O)
where S: Buffer + ?Sized,
R: BufferMut + ?Sized,
O: Operation { ... }
fn immediate_broadcast_into<'a, Buf, Sc>(
&self,
scope: Sc,
buf: &'a mut Buf,
) -> Request<'a, Buf, Sc>
where Buf: 'a + BufferMut + ?Sized,
Sc: Scope<'a> { ... }
fn immediate_gather_into<'a, S, Sc>(
&self,
scope: Sc,
sendbuf: &'a S,
) -> Request<'a, S, Sc>
where S: 'a + Buffer + ?Sized,
Sc: Scope<'a> { ... }
fn immediate_gather_into_root<'a, S, R, Sc>(
&self,
scope: Sc,
sendbuf: &'a S,
recvbuf: &'a mut R,
) -> Request<'a, R, Sc>
where S: 'a + Buffer + ?Sized,
R: 'a + BufferMut + ?Sized,
Sc: Scope<'a> { ... }
fn immediate_gather_varcount_into<'a, Sc, S>(
&self,
scope: Sc,
sendbuf: &'a S,
) -> Request<'a, S, Sc>
where S: 'a + Buffer + ?Sized,
Sc: Scope<'a> { ... }
fn immediate_gather_varcount_into_root<'a, Sc, S, R>(
&self,
scope: Sc,
sendbuf: &'a S,
recvbuf: &'a mut R,
) -> Request<'a, R, Sc>
where S: 'a + Buffer + ?Sized,
R: 'a + PartitionedBufferMut + ?Sized,
Sc: Scope<'a> { ... }
fn immediate_scatter_into<'a, Sc, R>(
&self,
scope: Sc,
recvbuf: &'a mut R,
) -> Request<'a, R, Sc>
where R: 'a + BufferMut + ?Sized,
Sc: Scope<'a> { ... }
fn immediate_scatter_into_root<'a, Sc, S, R>(
&self,
scope: Sc,
sendbuf: &'a S,
recvbuf: &'a mut R,
) -> Request<'a, R, Sc>
where S: 'a + Buffer + ?Sized,
R: 'a + BufferMut + ?Sized,
Sc: Scope<'a> { ... }
fn immediate_scatter_varcount_into<'a, Sc, R>(
&self,
scope: Sc,
recvbuf: &'a mut R,
) -> Request<'a, R, Sc>
where R: 'a + BufferMut + ?Sized,
Sc: Scope<'a> { ... }
fn immediate_scatter_varcount_into_root<'a, Sc, S, R>(
&self,
scope: Sc,
sendbuf: &'a S,
recvbuf: &'a mut R,
) -> Request<'a, R, Sc>
where S: 'a + PartitionedBuffer + ?Sized,
R: 'a + BufferMut + ?Sized,
Sc: Scope<'a> { ... }
fn immediate_reduce_into<'a, Sc, S, O>(
&self,
scope: Sc,
sendbuf: &'a S,
op: O,
) -> Request<'a, S, Sc>
where S: 'a + Buffer + ?Sized,
O: 'a + Operation,
Sc: Scope<'a> { ... }
fn immediate_reduce_into_root<'a, Sc, S, R, O>(
&self,
scope: Sc,
sendbuf: &'a S,
recvbuf: &'a mut R,
op: O,
) -> Request<'a, R, Sc>
where S: 'a + Buffer + ?Sized,
R: 'a + BufferMut + ?Sized,
O: 'a + Operation,
Sc: Scope<'a> { ... }
fn spawn(
&self,
command: &Command,
maxprocs: Rank,
) -> Result<InterCommunicator, MpiError> { ... }
fn spawn_multiple(
&self,
commands: &[Command],
maxprocs: &[Rank],
) -> Result<InterCommunicator, MpiError> { ... }
}
Expand description
Something that can take the role of ‘root’ in a collective operation.
Many collective operations define a ‘root’ process that takes a special role in the communication. These collective operations are implemented as default methods of this trait.
Required Methods§
Provided Methods§
Sourcefn broadcast_into<Buf>(&self, buffer: &mut Buf)
fn broadcast_into<Buf>(&self, buffer: &mut Buf)
Broadcast of the contents of a buffer
After the call completes, the Buffer
on all processes in the Communicator
of the Root
&self
will contain what it contains on the Root
.
§Examples
See examples/broadcast.rs
§Standard section(s)
5.4
Examples found in repository?
6fn main() {
7 let universe = mpi::initialize().unwrap();
8 let world = universe.world();
9
10 let root_process = world.process_at_rank(0);
11
12 let int_type = i32::equivalent_datatype().dup();
13
14 let mut ints = if world.rank() == 0 {
15 [1i32, 2, 3, 4]
16 } else {
17 [0, 0, 0, 0]
18 };
19
20 let mut buffer =
21 unsafe { DynBufferMut::from_raw(ints.as_mut_ptr(), ints.count(), int_type.as_ref()) };
22
23 root_process.broadcast_into(&mut buffer);
24
25 assert_eq!([1, 2, 3, 4], ints);
26}
More examples
50fn main() {
51 let universe = mpi::initialize().unwrap();
52 let world = universe.world();
53
54 let root_process = world.process_at_rank(0);
55
56 let mut data = if world.rank() == 0 {
57 ComplexDatatype {
58 b: true,
59 ints: [1, -2, 3, -4],
60 tuple: TupleType([-0.1, 0.1], 7),
61 }
62 } else {
63 ComplexDatatype::default()
64 };
65
66 root_process.broadcast_into(&mut data);
67
68 assert_eq!(true, data.b);
69 assert_eq!([1, -2, 3, -4], data.ints);
70 assert_eq!([-0.1, 0.1], data.tuple.0);
71 assert_eq!(7, data.tuple.1);
72}
30fn main() {
31 let universe = mpi::initialize().unwrap();
32 let world = universe.world();
33
34 let root_process = world.process_at_rank(0);
35 let second_root = world.process_at_rank(1 % world.size());
36
37 if root_process.is_self() {
38 let mut ints = MyInts([3, 2, 1]);
39 root_process.broadcast_into(&mut ints);
40 assert_eq!([3, 2, 1], ints.0);
41 prepare_on_root(second_root, &mut ints.0);
42 second_root.broadcast_into(&mut ints);
43 assert_eq!([13, 12, 11], ints.0);
44 } else {
45 let mut ints: [i32; 3] = [0, 0, 0];
46 root_process.broadcast_into(&mut ints[..]);
47 assert_eq!([1, 2, 3], ints);
48 prepare_on_root(second_root, &mut ints);
49 second_root.broadcast_into(&mut ints);
50 assert_eq!([11, 12, 13], ints);
51 }
52}
5fn main() {
6 let universe = mpi::initialize().unwrap();
7 let world = universe.world();
8 let root_rank = 0;
9 let root_process = world.process_at_rank(root_rank);
10
11 let mut x;
12 if world.rank() == root_rank {
13 x = 2_u64.pow(10);
14 println!("Root broadcasting value: {}.", x);
15 } else {
16 x = 0_u64;
17 }
18 root_process.broadcast_into(&mut x);
19 println!("Rank {} received value: {}.", world.rank(), x);
20 assert_eq!(x, 1024);
21 println!();
22
23 let mut a;
24 let n = 4;
25 if world.rank() == root_rank {
26 a = (1..).map(|i| 2_u64.pow(i)).take(n).collect::<Vec<_>>();
27 println!("Root broadcasting value: {:?}.", &a[..]);
28 } else {
29 a = std::iter::repeat(0_u64).take(n).collect::<Vec<_>>();
30 }
31 root_process.broadcast_into(&mut a);
32 println!("Rank {} received value: {:?}.", world.rank(), &a[..]);
33 assert_eq!(&a[..], &[2, 4, 8, 16]);
34}
6fn main() {
7 let universe = mpi::initialize().unwrap();
8 let world = universe.world();
9 let size = world.size();
10 let rank = world.rank();
11
12 let next_rank = (rank + 1) % size;
13 let previous_rank = (rank - 1 + size) % size;
14
15 let msg = vec![rank, 2 * rank, 4 * rank];
16 mpi::request::scope(|scope| {
17 let _sreq = WaitGuard::from(
18 world
19 .process_at_rank(next_rank)
20 .immediate_send(scope, &msg[..]),
21 );
22
23 let (msg, status) = world.any_process().receive_vec();
24
25 println!(
26 "Process {} got message {:?}.\nStatus is: {:?}",
27 rank, msg, status
28 );
29 let x = status.source_rank();
30 assert_eq!(x, previous_rank);
31 assert_eq!(vec![x, 2 * x, 4 * x], msg);
32
33 let root_rank = 0;
34 let root_process = world.process_at_rank(root_rank);
35
36 let mut a;
37 if world.rank() == root_rank {
38 a = vec![2, 4, 8, 16];
39 println!("Root broadcasting value: {:?}.", &a[..]);
40 } else {
41 a = vec![0; 4];
42 }
43 root_process.broadcast_into(&mut a[..]);
44 println!("Rank {} received value: {:?}.", world.rank(), &a[..]);
45 assert_eq!(&a[..], &[2, 4, 8, 16]);
46 });
47}
Sourcefn gather_into<S>(&self, sendbuf: &S)
fn gather_into<S>(&self, sendbuf: &S)
Gather contents of buffers on Root
.
After the call completes, the contents of the Buffer
s on all ranks will be
concatenated into the Buffer
on Root
.
All send Buffer
s must have the same count of elements.
This function must be called on all non-root processes.
§Examples
See examples/gather.rs
§Standard section(s)
5.5
Examples found in repository?
7fn main() {
8 let universe = mpi::initialize().unwrap();
9 let world = universe.world();
10 let root_rank = 0;
11 let root_process = world.process_at_rank(root_rank);
12
13 let count = world.size() as usize;
14 let i = 2_u64.pow(world.rank() as u32 + 1);
15
16 if world.rank() == root_rank {
17 let mut a = vec![0u64; count];
18 root_process.gather_into_root(&i, &mut a[..]);
19 println!("Root gathered sequence: {:?}.", a);
20 assert!(a
21 .iter()
22 .enumerate()
23 .all(|(a, &b)| b == 2u64.pow(a as u32 + 1)));
24 } else {
25 root_process.gather_into(&i);
26 }
27
28 let factor = world.rank() as u64 + 1;
29 let a = (1_u64..)
30 .take(count)
31 .map(|x| x * factor)
32 .collect::<Vec<_>>();
33
34 if world.rank() == root_rank {
35 let mut t = vec![0u64; count * count];
36 root_process.gather_into_root(&a[..], &mut t[..]);
37 println!("Root gathered table:");
38 for r in t.chunks(count) {
39 println!("{:?}", r);
40 }
41 assert!((0_u64..)
42 .zip(t.iter())
43 .all(|(a, &b)| b == (a / count as u64 + 1) * (a % count as u64 + 1)));
44 } else {
45 root_process.gather_into(&a[..]);
46 }
47
48 let d = UserDatatype::contiguous(count as Count, &u64::equivalent_datatype());
49 let sv = unsafe { View::with_count_and_datatype(&a[..], 1, &d) };
50
51 if world.rank() == root_rank {
52 let mut t = vec![0u64; count * count];
53
54 {
55 let mut rv =
56 unsafe { MutView::with_count_and_datatype(&mut t[..], count as Count, &d) };
57 root_process.gather_into_root(&sv, &mut rv);
58 }
59
60 println!("Root gathered table:");
61 for r in t.chunks(count) {
62 println!("{:?}", r);
63 }
64 assert!((0_u64..)
65 .zip(t.iter())
66 .all(|(a, &b)| b == (a / count as u64 + 1) * (a % count as u64 + 1)));
67 } else {
68 root_process.gather_into(&sv);
69 }
70}
Sourcefn gather_into_root<S, R>(&self, sendbuf: &S, recvbuf: &mut R)
fn gather_into_root<S, R>(&self, sendbuf: &S, recvbuf: &mut R)
Gather contents of buffers on Root
.
After the call completes, the contents of the Buffer
s on all ranks will be
concatenated into the Buffer
on Root
.
All send Buffer
s must have the same count of elements.
This function must be called on the root process.
§Examples
See examples/gather.rs
§Standard section(s)
5.5
Examples found in repository?
7fn main() {
8 let universe = mpi::initialize().unwrap();
9 let world = universe.world();
10 let root_rank = 0;
11 let root_process = world.process_at_rank(root_rank);
12
13 let count = world.size() as usize;
14 let i = 2_u64.pow(world.rank() as u32 + 1);
15
16 if world.rank() == root_rank {
17 let mut a = vec![0u64; count];
18 root_process.gather_into_root(&i, &mut a[..]);
19 println!("Root gathered sequence: {:?}.", a);
20 assert!(a
21 .iter()
22 .enumerate()
23 .all(|(a, &b)| b == 2u64.pow(a as u32 + 1)));
24 } else {
25 root_process.gather_into(&i);
26 }
27
28 let factor = world.rank() as u64 + 1;
29 let a = (1_u64..)
30 .take(count)
31 .map(|x| x * factor)
32 .collect::<Vec<_>>();
33
34 if world.rank() == root_rank {
35 let mut t = vec![0u64; count * count];
36 root_process.gather_into_root(&a[..], &mut t[..]);
37 println!("Root gathered table:");
38 for r in t.chunks(count) {
39 println!("{:?}", r);
40 }
41 assert!((0_u64..)
42 .zip(t.iter())
43 .all(|(a, &b)| b == (a / count as u64 + 1) * (a % count as u64 + 1)));
44 } else {
45 root_process.gather_into(&a[..]);
46 }
47
48 let d = UserDatatype::contiguous(count as Count, &u64::equivalent_datatype());
49 let sv = unsafe { View::with_count_and_datatype(&a[..], 1, &d) };
50
51 if world.rank() == root_rank {
52 let mut t = vec![0u64; count * count];
53
54 {
55 let mut rv =
56 unsafe { MutView::with_count_and_datatype(&mut t[..], count as Count, &d) };
57 root_process.gather_into_root(&sv, &mut rv);
58 }
59
60 println!("Root gathered table:");
61 for r in t.chunks(count) {
62 println!("{:?}", r);
63 }
64 assert!((0_u64..)
65 .zip(t.iter())
66 .all(|(a, &b)| b == (a / count as u64 + 1) * (a % count as u64 + 1)));
67 } else {
68 root_process.gather_into(&sv);
69 }
70}
Sourcefn gather_varcount_into<S>(&self, sendbuf: &S)
fn gather_varcount_into<S>(&self, sendbuf: &S)
Gather contents of buffers on Root
.
After the call completes, the contents of the Buffer
s on all ranks will be
concatenated into the Buffer
on Root
.
The send Buffer
s may contain different counts of elements on different processes. The
distribution of elements in the receive Buffer
is specified via Partitioned
.
This function must be called on all non-root processes.
§Examples
See examples/gather_varcount.rs
§Standard section(s)
5.5
Examples found in repository?
7fn main() {
8 let universe = mpi::initialize().unwrap();
9 let world = universe.world();
10
11 let rank = world.rank();
12 let size = world.size();
13
14 let root_rank = 0;
15 let root_process = world.process_at_rank(root_rank);
16
17 let msg: Vec<_> = (0..rank).collect();
18
19 if rank == root_rank {
20 let counts: Vec<Count> = (0..size).collect();
21 let displs: Vec<Count> = counts
22 .iter()
23 .scan(0, |acc, &x| {
24 let tmp = *acc;
25 *acc += x;
26 Some(tmp)
27 })
28 .collect();
29
30 let mut buf = vec![0; (size * (size - 1) / 2) as usize];
31 {
32 let mut partition = PartitionMut::new(&mut buf[..], counts, &displs[..]);
33 root_process.gather_varcount_into_root(&msg[..], &mut partition);
34 }
35
36 assert!(buf
37 .iter()
38 .zip((0..size).flat_map(|r| (0..r)))
39 .all(|(&i, j)| i == j));
40 println!("{:?}", buf);
41 } else {
42 root_process.gather_varcount_into(&msg[..]);
43 }
44}
Sourcefn gather_varcount_into_root<S, R>(&self, sendbuf: &S, recvbuf: &mut R)
fn gather_varcount_into_root<S, R>(&self, sendbuf: &S, recvbuf: &mut R)
Gather contents of buffers on Root
.
After the call completes, the contents of the Buffer
s on all ranks will be
concatenated into the Buffer
on Root
.
The send Buffer
s may contain different counts of elements on different processes. The
distribution of elements in the receive Buffer
is specified via Partitioned
.
This function must be called on the root process.
§Examples
See examples/gather_varcount.rs
§Standard section(s)
5.5
Examples found in repository?
7fn main() {
8 let universe = mpi::initialize().unwrap();
9 let world = universe.world();
10
11 let rank = world.rank();
12 let size = world.size();
13
14 let root_rank = 0;
15 let root_process = world.process_at_rank(root_rank);
16
17 let msg: Vec<_> = (0..rank).collect();
18
19 if rank == root_rank {
20 let counts: Vec<Count> = (0..size).collect();
21 let displs: Vec<Count> = counts
22 .iter()
23 .scan(0, |acc, &x| {
24 let tmp = *acc;
25 *acc += x;
26 Some(tmp)
27 })
28 .collect();
29
30 let mut buf = vec![0; (size * (size - 1) / 2) as usize];
31 {
32 let mut partition = PartitionMut::new(&mut buf[..], counts, &displs[..]);
33 root_process.gather_varcount_into_root(&msg[..], &mut partition);
34 }
35
36 assert!(buf
37 .iter()
38 .zip((0..size).flat_map(|r| (0..r)))
39 .all(|(&i, j)| i == j));
40 println!("{:?}", buf);
41 } else {
42 root_process.gather_varcount_into(&msg[..]);
43 }
44}
Sourcefn scatter_into<R>(&self, recvbuf: &mut R)
fn scatter_into<R>(&self, recvbuf: &mut R)
Scatter contents of a buffer on the root process to all processes.
After the call completes each participating process will have received a part of the send
Buffer
on the root process.
All send Buffer
s must have the same count of elements.
This function must be called on all non-root processes.
§Examples
See examples/scatter.rs
§Standard section(s)
5.6
Examples found in repository?
6fn main() {
7 let universe = mpi::initialize().unwrap();
8 let world = universe.world();
9 let rank = world.rank();
10 let size = world.size();
11 let root_rank = 0;
12 let root_process = world.process_at_rank(root_rank);
13
14 let mut x = 0 as Rank;
15 if rank == root_rank {
16 let v = (0..size).collect::<Vec<_>>();
17 root_process.scatter_into_root(&v, &mut x);
18 } else {
19 root_process.scatter_into(&mut x);
20 }
21 assert_eq!(x, rank);
22}
Sourcefn scatter_into_root<S, R>(&self, sendbuf: &S, recvbuf: &mut R)
fn scatter_into_root<S, R>(&self, sendbuf: &S, recvbuf: &mut R)
Scatter contents of a buffer on the root process to all processes.
After the call completes each participating process will have received a part of the send
Buffer
on the root process.
All send Buffer
s must have the same count of elements.
This function must be called on the root process.
§Examples
See examples/scatter.rs
§Standard section(s)
5.6
Examples found in repository?
6fn main() {
7 let universe = mpi::initialize().unwrap();
8 let world = universe.world();
9 let rank = world.rank();
10 let size = world.size();
11 let root_rank = 0;
12 let root_process = world.process_at_rank(root_rank);
13
14 let mut x = 0 as Rank;
15 if rank == root_rank {
16 let v = (0..size).collect::<Vec<_>>();
17 root_process.scatter_into_root(&v, &mut x);
18 } else {
19 root_process.scatter_into(&mut x);
20 }
21 assert_eq!(x, rank);
22}
Sourcefn scatter_varcount_into<R>(&self, recvbuf: &mut R)
fn scatter_varcount_into<R>(&self, recvbuf: &mut R)
Scatter contents of a buffer on the root process to all processes.
After the call completes each participating process will have received a part of the send
Buffer
on the root process.
The send Buffer
may contain different counts of elements for different processes. The
distribution of elements in the send Buffer
is specified via Partitioned
.
This function must be called on all non-root processes.
§Examples
See examples/scatter_varcount.rs
§Standard section(s)
5.6
Examples found in repository?
7fn main() {
8 let universe = mpi::initialize().unwrap();
9 let world = universe.world();
10
11 let rank = world.rank();
12 let size = world.size();
13
14 let root_rank = 0;
15 let root_process = world.process_at_rank(root_rank);
16
17 let mut buf = vec![0; rank as usize];
18
19 if rank == root_rank {
20 let msg: Vec<_> = (0..size).flat_map(|i| (0..i)).collect();
21 let counts: Vec<Count> = (0..size).collect();
22 let displs: Vec<Count> = counts
23 .iter()
24 .scan(0, |acc, &x| {
25 let tmp = *acc;
26 *acc += x;
27 Some(tmp)
28 })
29 .collect();
30 let partition = Partition::new(&msg[..], counts, &displs[..]);
31 root_process.scatter_varcount_into_root(&partition, &mut buf[..]);
32 } else {
33 root_process.scatter_varcount_into(&mut buf[..]);
34 }
35
36 assert!(buf.iter().zip(0..rank).all(|(&i, j)| i == j));
37 println!("Process {} got message: {:?}", rank, buf);
38}
Sourcefn scatter_varcount_into_root<S, R>(&self, sendbuf: &S, recvbuf: &mut R)
fn scatter_varcount_into_root<S, R>(&self, sendbuf: &S, recvbuf: &mut R)
Scatter contents of a buffer on the root process to all processes.
After the call completes each participating process will have received a part of the send
Buffer
on the root process.
The send Buffer
may contain different counts of elements for different processes. The
distribution of elements in the send Buffer
is specified via Partitioned
.
This function must be called on the root process.
§Examples
See examples/scatter_varcount.rs
§Standard section(s)
5.6
Examples found in repository?
7fn main() {
8 let universe = mpi::initialize().unwrap();
9 let world = universe.world();
10
11 let rank = world.rank();
12 let size = world.size();
13
14 let root_rank = 0;
15 let root_process = world.process_at_rank(root_rank);
16
17 let mut buf = vec![0; rank as usize];
18
19 if rank == root_rank {
20 let msg: Vec<_> = (0..size).flat_map(|i| (0..i)).collect();
21 let counts: Vec<Count> = (0..size).collect();
22 let displs: Vec<Count> = counts
23 .iter()
24 .scan(0, |acc, &x| {
25 let tmp = *acc;
26 *acc += x;
27 Some(tmp)
28 })
29 .collect();
30 let partition = Partition::new(&msg[..], counts, &displs[..]);
31 root_process.scatter_varcount_into_root(&partition, &mut buf[..]);
32 } else {
33 root_process.scatter_varcount_into(&mut buf[..]);
34 }
35
36 assert!(buf.iter().zip(0..rank).all(|(&i, j)| i == j));
37 println!("Process {} got message: {:?}", rank, buf);
38}
Sourcefn reduce_into<S, O>(&self, sendbuf: &S, op: O)
fn reduce_into<S, O>(&self, sendbuf: &S, op: O)
Performs a global reduction under the operation op
of the input data in sendbuf
and
stores the result on the Root
process.
This function must be called on all non-root processes.
§Examples
See examples/reduce.rs
§Standard section(s)
5.9.1
Examples found in repository?
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 world
78 .process_at_rank(root_rank)
79 .reduce_into_root(&rank, &mut sum, SystemOperation::sum());
80 assert_eq!(sum, size * (size - 1) / 2);
81 } else {
82 world
83 .process_at_rank(root_rank)
84 .reduce_into(&rank, SystemOperation::sum());
85 }
86
87 let mut max: Rank = -1;
88
89 world.all_reduce_into(&rank, &mut max, SystemOperation::max());
90 assert_eq!(max, size - 1);
91
92 let a: u16 = 0b0000_1111_1111_0000;
93 let b: u16 = 0b0011_1100_0011_1100;
94
95 let mut c = b;
96 collective::reduce_local_into(&a, &mut c, SystemOperation::bitwise_and());
97 assert_eq!(c, 0b0000_1100_0011_0000);
98
99 let mut d = b;
100 collective::reduce_local_into(&a, &mut d, SystemOperation::bitwise_or());
101 assert_eq!(d, 0b0011_1111_1111_1100);
102
103 let mut e = b;
104 collective::reduce_local_into(&a, &mut e, SystemOperation::bitwise_xor());
105 assert_eq!(e, 0b0011_0011_1100_1100);
106
107 let f = (0..size).collect::<Vec<_>>();
108 let mut g: Rank = 0;
109
110 world.reduce_scatter_block_into(&f[..], &mut g, SystemOperation::product());
111 assert_eq!(g, rank.wrapping_pow(size as u32));
112
113 test_user_operations(universe.world());
114
115 let mut i = 0;
116 let op = unsafe { UnsafeUserOperation::commutative(unsafe_add) };
117 world.all_reduce_into(&(rank + 1), &mut i, &op);
118 assert_eq!(i, size * (size + 1) / 2);
119}
Sourcefn reduce_into_root<S, R, O>(&self, sendbuf: &S, recvbuf: &mut R, op: O)
fn reduce_into_root<S, R, O>(&self, sendbuf: &S, recvbuf: &mut R, op: O)
Performs a global reduction under the operation op
of the input data in sendbuf
and
stores the result on the Root
process.
This function must be called on the root process.
§Examples
See examples/reduce.rs
§Standard section(s)
5.9.1
Examples found in repository?
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 world
78 .process_at_rank(root_rank)
79 .reduce_into_root(&rank, &mut sum, SystemOperation::sum());
80 assert_eq!(sum, size * (size - 1) / 2);
81 } else {
82 world
83 .process_at_rank(root_rank)
84 .reduce_into(&rank, SystemOperation::sum());
85 }
86
87 let mut max: Rank = -1;
88
89 world.all_reduce_into(&rank, &mut max, SystemOperation::max());
90 assert_eq!(max, size - 1);
91
92 let a: u16 = 0b0000_1111_1111_0000;
93 let b: u16 = 0b0011_1100_0011_1100;
94
95 let mut c = b;
96 collective::reduce_local_into(&a, &mut c, SystemOperation::bitwise_and());
97 assert_eq!(c, 0b0000_1100_0011_0000);
98
99 let mut d = b;
100 collective::reduce_local_into(&a, &mut d, SystemOperation::bitwise_or());
101 assert_eq!(d, 0b0011_1111_1111_1100);
102
103 let mut e = b;
104 collective::reduce_local_into(&a, &mut e, SystemOperation::bitwise_xor());
105 assert_eq!(e, 0b0011_0011_1100_1100);
106
107 let f = (0..size).collect::<Vec<_>>();
108 let mut g: Rank = 0;
109
110 world.reduce_scatter_block_into(&f[..], &mut g, SystemOperation::product());
111 assert_eq!(g, rank.wrapping_pow(size as u32));
112
113 test_user_operations(universe.world());
114
115 let mut i = 0;
116 let op = unsafe { UnsafeUserOperation::commutative(unsafe_add) };
117 world.all_reduce_into(&(rank + 1), &mut i, &op);
118 assert_eq!(i, size * (size + 1) / 2);
119}
Sourcefn immediate_broadcast_into<'a, Buf, Sc>(
&self,
scope: Sc,
buf: &'a mut Buf,
) -> Request<'a, Buf, Sc>
fn immediate_broadcast_into<'a, Buf, Sc>( &self, scope: Sc, buf: &'a mut Buf, ) -> Request<'a, Buf, Sc>
Initiate broadcast of a value from the Root
process to all other processes.
§Examples
See examples/immediate_broadcast.rs
§Standard section(s)
5.12.2
Examples found in repository?
5fn main() {
6 let universe = mpi::initialize().unwrap();
7 let world = universe.world();
8 let root_rank = 0;
9 let root_process = world.process_at_rank(root_rank);
10
11 let mut x;
12 if world.rank() == root_rank {
13 x = 2_u64.pow(10);
14 println!("Root broadcasting value: {}.", x);
15 } else {
16 x = 0_u64;
17 }
18 mpi::request::scope(|scope| {
19 root_process.immediate_broadcast_into(scope, &mut x).wait();
20 });
21 println!("Rank {} received value: {}.", world.rank(), x);
22 assert_eq!(x, 1024);
23 println!();
24
25 let mut a;
26 let n = 4;
27 if world.rank() == root_rank {
28 a = (1..).map(|i| 2_u64.pow(i)).take(n).collect::<Vec<_>>();
29 println!("Root broadcasting value: {:?}.", &a[..]);
30 } else {
31 a = std::iter::repeat(0_u64).take(n).collect::<Vec<_>>();
32 }
33 mpi::request::scope(|scope| {
34 root_process
35 .immediate_broadcast_into(scope, &mut a[..])
36 .wait();
37 });
38 println!("Rank {} received value: {:?}.", world.rank(), &a[..]);
39 assert_eq!(&a[..], &[2, 4, 8, 16]);
40}
Sourcefn immediate_gather_into<'a, S, Sc>(
&self,
scope: Sc,
sendbuf: &'a S,
) -> Request<'a, S, Sc>
fn immediate_gather_into<'a, S, Sc>( &self, scope: Sc, sendbuf: &'a S, ) -> Request<'a, S, Sc>
Initiate non-blocking gather of the contents of all sendbuf
s on Root
&self
.
This function must be called on all non-root processes.
§Examples
See examples/immediate_gather.rs
§Standard section(s)
5.12.3
Examples found in repository?
7fn main() {
8 let universe = mpi::initialize().unwrap();
9 let world = universe.world();
10 let root_rank = 0;
11 let root_process = world.process_at_rank(root_rank);
12
13 let count = world.size() as usize;
14 let i = 2_u64.pow(world.rank() as u32 + 1);
15
16 if world.rank() == root_rank {
17 let mut a = vec![0u64; count];
18 mpi::request::scope(|scope| {
19 root_process
20 .immediate_gather_into_root(scope, &i, &mut a[..])
21 .wait();
22 });
23 println!("Root gathered sequence: {:?}.", a);
24 assert!(a
25 .iter()
26 .enumerate()
27 .all(|(a, &b)| b == 2u64.pow(a as u32 + 1)));
28 } else {
29 mpi::request::scope(|scope| {
30 root_process.immediate_gather_into(scope, &i).wait();
31 });
32 }
33
34 let factor = world.rank() as u64 + 1;
35 let a = (1_u64..)
36 .take(count)
37 .map(|x| x * factor)
38 .collect::<Vec<_>>();
39
40 if world.rank() == root_rank {
41 let mut t = vec![0u64; count * count];
42 mpi::request::scope(|scope| {
43 root_process
44 .immediate_gather_into_root(scope, &a[..], &mut t[..])
45 .wait();
46 });
47 println!("Root gathered table:");
48 for r in t.chunks(count) {
49 println!("{:?}", r);
50 }
51 assert!((0_u64..)
52 .zip(t.iter())
53 .all(|(a, &b)| b == (a / count as u64 + 1) * (a % count as u64 + 1)));
54 } else {
55 mpi::request::scope(|scope| {
56 root_process.immediate_gather_into(scope, &a[..]).wait();
57 });
58 }
59
60 let d = UserDatatype::contiguous(count as Count, &u64::equivalent_datatype());
61 let sv = unsafe { View::with_count_and_datatype(&a[..], 1, &d) };
62
63 if world.rank() == root_rank {
64 let mut t = vec![0u64; count * count];
65
66 {
67 let mut rv =
68 unsafe { MutView::with_count_and_datatype(&mut t[..], count as Count, &d) };
69 mpi::request::scope(|scope| {
70 root_process
71 .immediate_gather_into_root(scope, &sv, &mut rv)
72 .wait();
73 });
74 }
75
76 println!("Root gathered table:");
77 for r in t.chunks(count) {
78 println!("{:?}", r);
79 }
80 assert!((0_u64..)
81 .zip(t.iter())
82 .all(|(a, &b)| b == (a / count as u64 + 1) * (a % count as u64 + 1)));
83 } else {
84 mpi::request::scope(|scope| {
85 root_process.immediate_gather_into(scope, &sv).wait();
86 });
87 }
88}
Sourcefn immediate_gather_into_root<'a, S, R, Sc>(
&self,
scope: Sc,
sendbuf: &'a S,
recvbuf: &'a mut R,
) -> Request<'a, R, Sc>
fn immediate_gather_into_root<'a, S, R, Sc>( &self, scope: Sc, sendbuf: &'a S, recvbuf: &'a mut R, ) -> Request<'a, R, Sc>
Initiate non-blocking gather of the contents of all sendbuf
s on Root
&self
.
This function must be called on the root processes.
§Examples
See examples/immediate_gather.rs
§Standard section(s)
5.12.3
Examples found in repository?
7fn main() {
8 let universe = mpi::initialize().unwrap();
9 let world = universe.world();
10 let root_rank = 0;
11 let root_process = world.process_at_rank(root_rank);
12
13 let count = world.size() as usize;
14 let i = 2_u64.pow(world.rank() as u32 + 1);
15
16 if world.rank() == root_rank {
17 let mut a = vec![0u64; count];
18 mpi::request::scope(|scope| {
19 root_process
20 .immediate_gather_into_root(scope, &i, &mut a[..])
21 .wait();
22 });
23 println!("Root gathered sequence: {:?}.", a);
24 assert!(a
25 .iter()
26 .enumerate()
27 .all(|(a, &b)| b == 2u64.pow(a as u32 + 1)));
28 } else {
29 mpi::request::scope(|scope| {
30 root_process.immediate_gather_into(scope, &i).wait();
31 });
32 }
33
34 let factor = world.rank() as u64 + 1;
35 let a = (1_u64..)
36 .take(count)
37 .map(|x| x * factor)
38 .collect::<Vec<_>>();
39
40 if world.rank() == root_rank {
41 let mut t = vec![0u64; count * count];
42 mpi::request::scope(|scope| {
43 root_process
44 .immediate_gather_into_root(scope, &a[..], &mut t[..])
45 .wait();
46 });
47 println!("Root gathered table:");
48 for r in t.chunks(count) {
49 println!("{:?}", r);
50 }
51 assert!((0_u64..)
52 .zip(t.iter())
53 .all(|(a, &b)| b == (a / count as u64 + 1) * (a % count as u64 + 1)));
54 } else {
55 mpi::request::scope(|scope| {
56 root_process.immediate_gather_into(scope, &a[..]).wait();
57 });
58 }
59
60 let d = UserDatatype::contiguous(count as Count, &u64::equivalent_datatype());
61 let sv = unsafe { View::with_count_and_datatype(&a[..], 1, &d) };
62
63 if world.rank() == root_rank {
64 let mut t = vec![0u64; count * count];
65
66 {
67 let mut rv =
68 unsafe { MutView::with_count_and_datatype(&mut t[..], count as Count, &d) };
69 mpi::request::scope(|scope| {
70 root_process
71 .immediate_gather_into_root(scope, &sv, &mut rv)
72 .wait();
73 });
74 }
75
76 println!("Root gathered table:");
77 for r in t.chunks(count) {
78 println!("{:?}", r);
79 }
80 assert!((0_u64..)
81 .zip(t.iter())
82 .all(|(a, &b)| b == (a / count as u64 + 1) * (a % count as u64 + 1)));
83 } else {
84 mpi::request::scope(|scope| {
85 root_process.immediate_gather_into(scope, &sv).wait();
86 });
87 }
88}
Sourcefn immediate_gather_varcount_into<'a, Sc, S>(
&self,
scope: Sc,
sendbuf: &'a S,
) -> Request<'a, S, Sc>
fn immediate_gather_varcount_into<'a, Sc, S>( &self, scope: Sc, sendbuf: &'a S, ) -> Request<'a, S, Sc>
Initiate non-blocking gather of the contents of all sendbuf
s on Root
&self
.
This function must be called on all non-root processes.
§Examples
See examples/immediate_gather_varcount.rs
§Standard section(s)
5.12.3
Examples found in repository?
7fn main() {
8 let universe = mpi::initialize().unwrap();
9 let world = universe.world();
10
11 let rank = world.rank();
12 let size = world.size();
13
14 let root_rank = 0;
15 let root_process = world.process_at_rank(root_rank);
16
17 let msg: Vec<_> = (0..rank).collect();
18
19 if rank == root_rank {
20 let counts: Vec<Count> = (0..size).collect();
21 let displs: Vec<Count> = counts
22 .iter()
23 .scan(0, |acc, &x| {
24 let tmp = *acc;
25 *acc += x;
26 Some(tmp)
27 })
28 .collect();
29
30 let mut buf = vec![0; (size * (size - 1) / 2) as usize];
31 {
32 let mut partition = PartitionMut::new(&mut buf[..], counts, &displs[..]);
33 mpi::request::scope(|scope| {
34 root_process
35 .immediate_gather_varcount_into_root(scope, &msg[..], &mut partition)
36 .wait();
37 })
38 }
39
40 assert!(buf
41 .iter()
42 .zip((0..size).flat_map(|r| (0..r)))
43 .all(|(&i, j)| i == j));
44 println!("{:?}", buf);
45 } else {
46 mpi::request::scope(|scope| {
47 root_process
48 .immediate_gather_varcount_into(scope, &msg[..])
49 .wait();
50 });
51 }
52}
Sourcefn immediate_gather_varcount_into_root<'a, Sc, S, R>(
&self,
scope: Sc,
sendbuf: &'a S,
recvbuf: &'a mut R,
) -> Request<'a, R, Sc>
fn immediate_gather_varcount_into_root<'a, Sc, S, R>( &self, scope: Sc, sendbuf: &'a S, recvbuf: &'a mut R, ) -> Request<'a, R, Sc>
Initiate non-blocking gather of the contents of all sendbuf
s on Root
&self
.
This function must be called on the root processes.
§Examples
See examples/immediate_gather_varcount.rs
§Standard section(s)
5.12.3
Examples found in repository?
7fn main() {
8 let universe = mpi::initialize().unwrap();
9 let world = universe.world();
10
11 let rank = world.rank();
12 let size = world.size();
13
14 let root_rank = 0;
15 let root_process = world.process_at_rank(root_rank);
16
17 let msg: Vec<_> = (0..rank).collect();
18
19 if rank == root_rank {
20 let counts: Vec<Count> = (0..size).collect();
21 let displs: Vec<Count> = counts
22 .iter()
23 .scan(0, |acc, &x| {
24 let tmp = *acc;
25 *acc += x;
26 Some(tmp)
27 })
28 .collect();
29
30 let mut buf = vec![0; (size * (size - 1) / 2) as usize];
31 {
32 let mut partition = PartitionMut::new(&mut buf[..], counts, &displs[..]);
33 mpi::request::scope(|scope| {
34 root_process
35 .immediate_gather_varcount_into_root(scope, &msg[..], &mut partition)
36 .wait();
37 })
38 }
39
40 assert!(buf
41 .iter()
42 .zip((0..size).flat_map(|r| (0..r)))
43 .all(|(&i, j)| i == j));
44 println!("{:?}", buf);
45 } else {
46 mpi::request::scope(|scope| {
47 root_process
48 .immediate_gather_varcount_into(scope, &msg[..])
49 .wait();
50 });
51 }
52}
Sourcefn immediate_scatter_into<'a, Sc, R>(
&self,
scope: Sc,
recvbuf: &'a mut R,
) -> Request<'a, R, Sc>
fn immediate_scatter_into<'a, Sc, R>( &self, scope: Sc, recvbuf: &'a mut R, ) -> Request<'a, R, Sc>
Initiate non-blocking scatter of the contents of sendbuf
from Root
&self
.
This function must be called on all non-root processes.
§Examples
See examples/immediate_scatter.rs
§Standard section(s)
5.12.4
Examples found in repository?
6fn main() {
7 let universe = mpi::initialize().unwrap();
8 let world = universe.world();
9 let rank = world.rank();
10 let size = world.size();
11 let root_rank = 0;
12 let root_process = world.process_at_rank(root_rank);
13
14 let mut x = 0 as Rank;
15 if rank == root_rank {
16 let v = (0..size).collect::<Vec<_>>();
17 mpi::request::scope(|scope| {
18 let req = root_process.immediate_scatter_into_root(scope, &v[..], &mut x);
19 req.wait();
20 });
21 } else {
22 mpi::request::scope(|scope| {
23 let req = root_process.immediate_scatter_into(scope, &mut x);
24 req.wait();
25 });
26 }
27 assert_eq!(x, rank);
28}
Sourcefn immediate_scatter_into_root<'a, Sc, S, R>(
&self,
scope: Sc,
sendbuf: &'a S,
recvbuf: &'a mut R,
) -> Request<'a, R, Sc>
fn immediate_scatter_into_root<'a, Sc, S, R>( &self, scope: Sc, sendbuf: &'a S, recvbuf: &'a mut R, ) -> Request<'a, R, Sc>
Initiate non-blocking scatter of the contents of sendbuf
from Root
&self
.
This function must be called on the root processes.
§Examples
See examples/immediate_scatter.rs
§Standard section(s)
5.12.4
Examples found in repository?
6fn main() {
7 let universe = mpi::initialize().unwrap();
8 let world = universe.world();
9 let rank = world.rank();
10 let size = world.size();
11 let root_rank = 0;
12 let root_process = world.process_at_rank(root_rank);
13
14 let mut x = 0 as Rank;
15 if rank == root_rank {
16 let v = (0..size).collect::<Vec<_>>();
17 mpi::request::scope(|scope| {
18 let req = root_process.immediate_scatter_into_root(scope, &v[..], &mut x);
19 req.wait();
20 });
21 } else {
22 mpi::request::scope(|scope| {
23 let req = root_process.immediate_scatter_into(scope, &mut x);
24 req.wait();
25 });
26 }
27 assert_eq!(x, rank);
28}
Sourcefn immediate_scatter_varcount_into<'a, Sc, R>(
&self,
scope: Sc,
recvbuf: &'a mut R,
) -> Request<'a, R, Sc>
fn immediate_scatter_varcount_into<'a, Sc, R>( &self, scope: Sc, recvbuf: &'a mut R, ) -> Request<'a, R, Sc>
Initiate non-blocking scatter of the contents of sendbuf
from Root
&self
.
This function must be called on all non-root processes.
§Examples
See examples/immediate_scatter_varcount.rs
§Standard section(s)
5.12.4
Examples found in repository?
7fn main() {
8 let universe = mpi::initialize().unwrap();
9 let world = universe.world();
10
11 let rank = world.rank();
12 let size = world.size();
13
14 let root_rank = 0;
15 let root_process = world.process_at_rank(root_rank);
16
17 let mut buf = vec![0; rank as usize];
18
19 if rank == root_rank {
20 let msg: Vec<_> = (0..size).flat_map(|i| (0..i)).collect();
21 let counts: Vec<Count> = (0..size).collect();
22 let displs: Vec<Count> = counts
23 .iter()
24 .scan(0, |acc, &x| {
25 let tmp = *acc;
26 *acc += x;
27 Some(tmp)
28 })
29 .collect();
30 let partition = Partition::new(&msg[..], counts, &displs[..]);
31 mpi::request::scope(|scope| {
32 root_process
33 .immediate_scatter_varcount_into_root(scope, &partition, &mut buf[..])
34 .wait();
35 });
36 } else {
37 mpi::request::scope(|scope| {
38 root_process
39 .immediate_scatter_varcount_into(scope, &mut buf[..])
40 .wait();
41 });
42 }
43
44 assert!(buf.iter().zip(0..rank).all(|(&i, j)| i == j));
45 println!("Process {} got message: {:?}", rank, buf);
46}
Sourcefn immediate_scatter_varcount_into_root<'a, Sc, S, R>(
&self,
scope: Sc,
sendbuf: &'a S,
recvbuf: &'a mut R,
) -> Request<'a, R, Sc>
fn immediate_scatter_varcount_into_root<'a, Sc, S, R>( &self, scope: Sc, sendbuf: &'a S, recvbuf: &'a mut R, ) -> Request<'a, R, Sc>
Initiate non-blocking scatter of the contents of sendbuf
from Root
&self
.
This function must be called on the root processes.
§Examples
See examples/immediate_scatter_varcount.rs
§Standard section(s)
5.12.4
Examples found in repository?
7fn main() {
8 let universe = mpi::initialize().unwrap();
9 let world = universe.world();
10
11 let rank = world.rank();
12 let size = world.size();
13
14 let root_rank = 0;
15 let root_process = world.process_at_rank(root_rank);
16
17 let mut buf = vec![0; rank as usize];
18
19 if rank == root_rank {
20 let msg: Vec<_> = (0..size).flat_map(|i| (0..i)).collect();
21 let counts: Vec<Count> = (0..size).collect();
22 let displs: Vec<Count> = counts
23 .iter()
24 .scan(0, |acc, &x| {
25 let tmp = *acc;
26 *acc += x;
27 Some(tmp)
28 })
29 .collect();
30 let partition = Partition::new(&msg[..], counts, &displs[..]);
31 mpi::request::scope(|scope| {
32 root_process
33 .immediate_scatter_varcount_into_root(scope, &partition, &mut buf[..])
34 .wait();
35 });
36 } else {
37 mpi::request::scope(|scope| {
38 root_process
39 .immediate_scatter_varcount_into(scope, &mut buf[..])
40 .wait();
41 });
42 }
43
44 assert!(buf.iter().zip(0..rank).all(|(&i, j)| i == j));
45 println!("Process {} got message: {:?}", rank, buf);
46}
Sourcefn immediate_reduce_into<'a, Sc, S, O>(
&self,
scope: Sc,
sendbuf: &'a S,
op: O,
) -> Request<'a, S, Sc>
fn immediate_reduce_into<'a, Sc, S, O>( &self, scope: Sc, sendbuf: &'a S, op: O, ) -> Request<'a, S, Sc>
Initiates a non-blacking global reduction under the operation op
of the input data in
sendbuf
and stores the result on the Root
process.
This function must be called on all non-root processes.
§Examples
See examples/immediate_reduce.rs
§Standard section(s)
5.12.7
Examples found in repository?
67fn main() {
68 let universe = mpi::initialize().unwrap();
69 let world = universe.world();
70 let rank = world.rank();
71 let size = world.size();
72 let root_rank = 0;
73
74 if rank == root_rank {
75 let mut sum: Rank = 0;
76 mpi::request::scope(|scope| {
77 world
78 .process_at_rank(root_rank)
79 .immediate_reduce_into_root(scope, &rank, &mut sum, SystemOperation::sum())
80 .wait();
81 });
82 assert_eq!(sum, size * (size - 1) / 2);
83 } else {
84 mpi::request::scope(|scope| {
85 world
86 .process_at_rank(root_rank)
87 .immediate_reduce_into(scope, &rank, SystemOperation::sum())
88 .wait();
89 });
90 }
91
92 let mut max: Rank = -1;
93
94 mpi::request::scope(|scope| {
95 world
96 .immediate_all_reduce_into(scope, &rank, &mut max, SystemOperation::max())
97 .wait();
98 });
99 assert_eq!(max, size - 1);
100
101 let a = (0..size).collect::<Vec<_>>();
102 let mut b: Rank = 0;
103
104 mpi::request::scope(|scope| {
105 world
106 .immediate_reduce_scatter_block_into(scope, &a[..], &mut b, SystemOperation::product())
107 .wait();
108 });
109 assert_eq!(b, rank.wrapping_pow(size as u32));
110
111 test_user_operations(universe.world());
112
113 let mut d = 0;
114 let op = unsafe { UnsafeUserOperation::commutative(unsafe_add) };
115 mpi::request::scope(|scope| {
116 world
117 .immediate_all_reduce_into(scope, &rank, &mut d, &op)
118 .wait();
119 });
120 assert_eq!(d, size * (size - 1) / 2);
121}
Sourcefn immediate_reduce_into_root<'a, Sc, S, R, O>(
&self,
scope: Sc,
sendbuf: &'a S,
recvbuf: &'a mut R,
op: O,
) -> Request<'a, R, Sc>
fn immediate_reduce_into_root<'a, Sc, S, R, O>( &self, scope: Sc, sendbuf: &'a S, recvbuf: &'a mut R, op: O, ) -> Request<'a, R, Sc>
Initiates a non-blocking global reduction under the operation op
of the input data in
sendbuf
and stores the result on the Root
process.
§Examples
See examples/immediate_reduce.rs
This function must be called on the root process.
§Standard section(s)
5.12.7
Examples found in repository?
67fn main() {
68 let universe = mpi::initialize().unwrap();
69 let world = universe.world();
70 let rank = world.rank();
71 let size = world.size();
72 let root_rank = 0;
73
74 if rank == root_rank {
75 let mut sum: Rank = 0;
76 mpi::request::scope(|scope| {
77 world
78 .process_at_rank(root_rank)
79 .immediate_reduce_into_root(scope, &rank, &mut sum, SystemOperation::sum())
80 .wait();
81 });
82 assert_eq!(sum, size * (size - 1) / 2);
83 } else {
84 mpi::request::scope(|scope| {
85 world
86 .process_at_rank(root_rank)
87 .immediate_reduce_into(scope, &rank, SystemOperation::sum())
88 .wait();
89 });
90 }
91
92 let mut max: Rank = -1;
93
94 mpi::request::scope(|scope| {
95 world
96 .immediate_all_reduce_into(scope, &rank, &mut max, SystemOperation::max())
97 .wait();
98 });
99 assert_eq!(max, size - 1);
100
101 let a = (0..size).collect::<Vec<_>>();
102 let mut b: Rank = 0;
103
104 mpi::request::scope(|scope| {
105 world
106 .immediate_reduce_scatter_block_into(scope, &a[..], &mut b, SystemOperation::product())
107 .wait();
108 });
109 assert_eq!(b, rank.wrapping_pow(size as u32));
110
111 test_user_operations(universe.world());
112
113 let mut d = 0;
114 let op = unsafe { UnsafeUserOperation::commutative(unsafe_add) };
115 mpi::request::scope(|scope| {
116 world
117 .immediate_all_reduce_into(scope, &rank, &mut d, &op)
118 .wait();
119 });
120 assert_eq!(d, size * (size - 1) / 2);
121}
Sourcefn spawn(
&self,
command: &Command,
maxprocs: Rank,
) -> Result<InterCommunicator, MpiError>
fn spawn( &self, command: &Command, maxprocs: Rank, ) -> Result<InterCommunicator, MpiError>
Examples found in repository?
8fn main() -> Result<(), mpi::MpiError> {
9 let universe = mpi::initialize().unwrap();
10 let world = universe.world();
11
12 let merged = if let Some(parent) = world.parent() {
13 assert_eq!("from_parent", env::args().skip(1).next().unwrap());
14
15 parent.process_at_rank(0).send(&7i32);
16
17 println!(
18 "[{}/{}] Child universe {:?}",
19 world.rank(),
20 world.size(),
21 universe.size()
22 );
23 parent.merge(MergeOrder::High)
24 } else {
25 let child_size = 1;
26 let mut exe = Command::new(env::current_exe().unwrap());
27 exe.arg("from_parent");
28
29 let child = world.process_at_rank(0).spawn(&exe, child_size)?;
30
31 assert_eq!(child_size, child.remote_size());
32
33 if world.rank() == 0 {
34 assert_eq!(7i32, child.process_at_rank(0).receive().0);
35 }
36 println!(
37 "[{}/{}] Parent universe {:?} appnum {}",
38 world.rank(),
39 world.size(),
40 universe.size(),
41 universe.appnum().unwrap_or(-1),
42 );
43 child.merge(MergeOrder::Low)
44 };
45 println!(
46 "[{}/{}] Merged is World {}/{}",
47 merged.rank(),
48 merged.size(),
49 world.rank(),
50 world.size()
51 );
52 Ok(())
53}
Sourcefn spawn_multiple(
&self,
commands: &[Command],
maxprocs: &[Rank],
) -> Result<InterCommunicator, MpiError>
fn spawn_multiple( &self, commands: &[Command], maxprocs: &[Rank], ) -> Result<InterCommunicator, MpiError>
Examples found in repository?
7fn main() -> Result<(), mpi::MpiError> {
8 let universe = mpi::initialize().unwrap();
9 let world = universe.world();
10
11 if let Some(parent) = world.parent() {
12 let child_name = env::args().skip(1).next().unwrap();
13 let appnum = universe.appnum().unwrap_or(-1);
14 println!(
15 "[{}/{}] {} ({}) has parent size {}, universe {:?}",
16 world.rank(),
17 world.size(),
18 child_name,
19 appnum,
20 parent.remote_size(),
21 universe.size(),
22 );
23 } else {
24 fn self_with_arg(arg: &str) -> Command {
25 let mut exe = Command::new(env::current_exe().unwrap());
26 exe.arg(arg);
27 exe
28 }
29 let child_sizes = [2, 1];
30 let commands = vec![self_with_arg("FirstChild"), self_with_arg("SecondChild")];
31
32 let child = world
33 .process_at_rank(0)
34 .spawn_multiple(&commands, &child_sizes)?;
35
36 assert_eq!(child_sizes.iter().sum::<i32>(), child.remote_size());
37
38 println!(
39 "[{}/{}] Parent universe {:?}",
40 world.rank(),
41 world.size(),
42 universe.size(),
43 );
44 }
45 Ok(())
46}
Dyn Compatibility§
This trait is not dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.