Trait Communicator

Source
pub trait Communicator: AsHandle {
Show 26 methods // Required method fn target_size(&self) -> Rank; // Provided methods fn size(&self) -> Rank { ... } fn rank(&self) -> Rank { ... } fn process_at_rank(&self, r: Rank) -> Process<'_> { ... } fn any_process(&self) -> AnyProcess<'_> { ... } fn this_process(&self) -> Process<'_> { ... } fn compare(&self, other: &dyn Communicator) -> CommunicatorRelation { ... } fn duplicate(&self) -> SimpleCommunicator { ... } fn split_by_color(&self, color: Color) -> Option<SimpleCommunicator> { ... } fn split_by_color_with_key( &self, color: Color, key: Key, ) -> Option<SimpleCommunicator> { ... } fn split_shared(&self, key: c_int) -> SimpleCommunicator { ... } fn split_by_subgroup_collective( &self, group: &dyn Group, ) -> Option<SimpleCommunicator> { ... } fn split_by_subgroup(&self, group: &dyn Group) -> Option<SimpleCommunicator> { ... } fn split_by_subgroup_with_tag( &self, group: &dyn Group, tag: Tag, ) -> Option<SimpleCommunicator> { ... } fn group(&self) -> UserGroup { ... } fn abort(&self, errorcode: c_int) -> ! { ... } fn test_inter(&self) -> bool { ... } fn set_name(&self, name: &str) { ... } fn get_name(&self) -> String { ... } fn create_cartesian_communicator( &self, dims: &[Count], periods: &[bool], reorder: bool, ) -> Option<CartesianCommunicator> { ... } fn cartesian_map(&self, dims: &[Count], periods: &[bool]) -> Option<Rank> { ... } fn pack_size<Dt>(&self, incount: Count, datatype: &Dt) -> Count where Dt: Datatype, Self: Sized { ... } fn pack<Buf>(&self, inbuf: &Buf) -> Vec<u8> where Buf: ?Sized + Buffer, Self: Sized { ... } fn pack_into<Buf>( &self, inbuf: &Buf, outbuf: &mut [u8], position: Count, ) -> Count where Buf: ?Sized + Buffer, Self: Sized { ... } unsafe fn unpack_into<Buf>( &self, inbuf: &[u8], outbuf: &mut Buf, position: Count, ) -> Count where Buf: ?Sized + BufferMut, Self: Sized { ... } fn parent(&self) -> Option<InterCommunicator> { ... }
}
Expand description

Communicators are contexts for communication

Required Methods§

Source

fn target_size(&self) -> Rank

Returns the number of processes available to communicate with in this Communicator. For intra-communicators, this is equivalent to size. For inter-communicators, this is equivalent to remote_size.

Provided Methods§

Source

fn size(&self) -> Rank

Number of processes in this communicator

§Examples

See examples/simple.rs

§Standard section(s)

6.4.1

Examples found in repository?
examples/simple.rs (line 11)
5fn main() {
6    let universe = mpi::initialize().unwrap();
7    let world = universe.world();
8    println!(
9        "Hello parallel world from process {} of {}!",
10        world.rank(),
11        world.size()
12    );
13}
More examples
Hide additional examples
examples/cartesian_map.rs (line 10)
5fn main() {
6    let universe = mpi::initialize().unwrap();
7
8    let comm = universe.world();
9
10    let new_rank = comm.cartesian_map(&[2, comm.size() / 4], &[false, false]);
11
12    println!("{} -> {:?}", comm.rank(), new_rank);
13}
examples/all_gather_bool.rs (line 10)
5fn main() {
6    let universe = mpi::initialize().unwrap();
7    let world = universe.world();
8
9    let rank = world.rank();
10    let count = world.size() as usize;
11
12    let mut a = vec![false; count];
13    world.all_gather_into(&(rank % 2 == 0), &mut a[..]);
14
15    let answer: Vec<_> = (0..count).map(|i| i % 2 == 0).collect();
16
17    assert_eq!(answer, a);
18}
examples/all_to_all.rs (line 9)
5fn main() {
6    let universe = mpi::initialize().unwrap();
7    let world = universe.world();
8    let rank = world.rank();
9    let size = world.size();
10
11    let u = vec![rank; size as usize];
12    let mut v = vec![0; size as usize];
13
14    world.all_to_all_into(&u[..], &mut v[..]);
15
16    println!("u: {:?}", u);
17    println!("v: {:?}", v);
18
19    assert!(v.into_iter().zip(0..size).all(|(i, j)| i == j));
20}
examples/scatter.rs (line 10)
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}
examples/immediate_all_to_all.rs (line 9)
5fn main() {
6    let universe = mpi::initialize().unwrap();
7    let world = universe.world();
8    let rank = world.rank();
9    let size = world.size();
10
11    let u = vec![rank; size as usize];
12    let mut v = vec![0; size as usize];
13
14    mpi::request::scope(|scope| {
15        world
16            .immediate_all_to_all_into(scope, &u[..], &mut v[..])
17            .wait();
18    });
19
20    println!("u: {:?}", u);
21    println!("v: {:?}", v);
22
23    assert!(v.into_iter().zip(0..size).all(|(i, j)| i == j));
24}
Source

fn rank(&self) -> Rank

The Rank that identifies the calling process within this communicator

§Examples

See examples/simple.rs

§Standard section(s)

6.4.1

Examples found in repository?
examples/simple.rs (line 10)
5fn main() {
6    let universe = mpi::initialize().unwrap();
7    let world = universe.world();
8    println!(
9        "Hello parallel world from process {} of {}!",
10        world.rank(),
11        world.size()
12    );
13}
More examples
Hide additional examples
examples/cartesian_map.rs (line 12)
5fn main() {
6    let universe = mpi::initialize().unwrap();
7
8    let comm = universe.world();
9
10    let new_rank = comm.cartesian_map(&[2, comm.size() / 4], &[false, false]);
11
12    println!("{} -> {:?}", comm.rank(), new_rank);
13}
examples/dyn_communicator.rs (line 29)
28fn prefix_sum(comm: &dyn Communicator, output_prefix: &str) {
29    let rank = comm.rank() as usize;
30    let mut target = 0;
31
32    comm.scan_into(&rank, &mut target, SystemOperation::sum());
33
34    println!("{} rank {}: {:?}", output_prefix, rank, target);
35}
examples/all_gather_bool.rs (line 9)
5fn main() {
6    let universe = mpi::initialize().unwrap();
7    let world = universe.world();
8
9    let rank = world.rank();
10    let count = world.size() as usize;
11
12    let mut a = vec![false; count];
13    world.all_gather_into(&(rank % 2 == 0), &mut a[..]);
14
15    let answer: Vec<_> = (0..count).map(|i| i % 2 == 0).collect();
16
17    assert_eq!(answer, a);
18}
examples/all_to_all.rs (line 8)
5fn main() {
6    let universe = mpi::initialize().unwrap();
7    let world = universe.world();
8    let rank = world.rank();
9    let size = world.size();
10
11    let u = vec![rank; size as usize];
12    let mut v = vec![0; size as usize];
13
14    world.all_to_all_into(&u[..], &mut v[..]);
15
16    println!("u: {:?}", u);
17    println!("v: {:?}", v);
18
19    assert!(v.into_iter().zip(0..size).all(|(i, j)| i == j));
20}
examples/scan.rs (line 14)
11fn main() {
12    let universe = mpi::initialize().unwrap();
13    let world = universe.world();
14    let rank = world.rank();
15
16    let mut x = 0;
17    world.scan_into(&rank, &mut x, &SystemOperation::sum());
18    assert_eq!(x, (rank * (rank + 1)) / 2);
19
20    let y = rank + 1;
21    let mut z = 0;
22    world.exclusive_scan_into(&y, &mut z, &SystemOperation::product());
23    if rank > 0 {
24        assert_eq!(z, fac(y - 1));
25    }
26}
Source

fn process_at_rank(&self, r: Rank) -> Process<'_>

Bundles a reference to this communicator with a specific Rank into a Process.

§Examples

See examples/broadcast.rs examples/gather.rs examples/send_receive.rs

Examples found in repository?
examples/scatter.rs (line 12)
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}
More examples
Hide additional examples
examples/datatype_dup.rs (line 10)
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}
examples/immediate_multiple_test.rs (line 19)
9fn send_recv<'a, S: Scope<'a> + Copy>(
10    world: &impl Communicator,
11    scope: S,
12    coll: &mut RequestCollection<'a, [i32; 4]>,
13    next_proc: Rank,
14    prev_proc: Rank,
15    x: &'a [[i32; 4]],
16    recv: &'a mut [[i32; 4]],
17) {
18    for elm in x {
19        let sreq = world.process_at_rank(next_proc).immediate_send(scope, elm);
20        coll.add(sreq);
21    }
22    for elm in recv.iter_mut() {
23        let rreq = world
24            .process_at_rank(prev_proc)
25            .immediate_receive_into(scope, elm);
26        coll.add(rreq);
27    }
28}
examples/complex_datatype.rs (line 54)
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}
examples/immediate_scatter.rs (line 12)
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}
examples/barrier.rs (line 24)
5fn main() {
6    let universe = mpi::initialize().unwrap();
7    let world = universe.world();
8    let receiver_rank = 0;
9
10    if world.rank() == receiver_rank {
11        let n = (world.size() - 1) as usize;
12        let mut buf = vec![0u64; 2 * n];
13        for x in buf[0..n].iter_mut() {
14            world.any_process().receive_into(x);
15        }
16        world.barrier();
17        for x in buf[n..2 * n].iter_mut() {
18            world.any_process().receive_into(x);
19        }
20        println!("{:?}", buf);
21        assert!(buf[0..n].iter().all(|&x| x == 1));
22        assert!(buf[n..2 * n].iter().all(|&x| x == 2));
23    } else {
24        world.process_at_rank(0).send(&1u64);
25        world.barrier();
26        world.process_at_rank(0).send(&2u64);
27    }
28}
Source

fn any_process(&self) -> AnyProcess<'_>

Returns an AnyProcess identifier that can be used, e.g. as a Source in point to point communication.

Examples found in repository?
examples/barrier.rs (line 14)
5fn main() {
6    let universe = mpi::initialize().unwrap();
7    let world = universe.world();
8    let receiver_rank = 0;
9
10    if world.rank() == receiver_rank {
11        let n = (world.size() - 1) as usize;
12        let mut buf = vec![0u64; 2 * n];
13        for x in buf[0..n].iter_mut() {
14            world.any_process().receive_into(x);
15        }
16        world.barrier();
17        for x in buf[n..2 * n].iter_mut() {
18            world.any_process().receive_into(x);
19        }
20        println!("{:?}", buf);
21        assert!(buf[0..n].iter().all(|&x| x == 1));
22        assert!(buf[n..2 * n].iter().all(|&x| x == 2));
23    } else {
24        world.process_at_rank(0).send(&1u64);
25        world.barrier();
26        world.process_at_rank(0).send(&2u64);
27    }
28}
More examples
Hide additional examples
examples/buffered.rs (line 26)
8fn main() {
9    let mut universe = mpi::initialize().unwrap();
10    // Try to attach a buffer.
11    universe.set_buffer_size(BUFFER_SIZE);
12    // Check buffer size matches.
13    assert_eq!(universe.buffer_size(), BUFFER_SIZE);
14    // Try to detach the buffer.
15    universe.detach_buffer();
16    // Attach another buffer.
17    universe.set_buffer_size(BUFFER_SIZE);
18
19    let world = universe.world();
20
21    let x = vec![std::f32::consts::PI; 1024];
22    let mut y = vec![0.0; 1024];
23    mpi::request::scope(|scope| {
24        let _rreq = WaitGuard::from(
25            world
26                .any_process()
27                .immediate_receive_into(scope, &mut y[..]),
28        );
29        world.this_process().buffered_send(&x[..]);
30    });
31    assert_eq!(x, y);
32}
examples/wait_any.rs (line 35)
7fn main() {
8    let universe = mpi::initialize().unwrap();
9    let world = universe.world();
10
11    let x = std::f32::consts::PI;
12    let mut y: f32 = 0.0;
13
14    mpi::request::scope(|scope| {
15        if world.rank() == 0 {
16            let mut requests = Vec::new();
17            for i in 1..world.size() {
18                requests.push(
19                    world
20                        .process_at_rank(i)
21                        .immediate_synchronous_send(scope, &x),
22                );
23            }
24
25            println!("World size {}", world.size());
26            while let Some((index, _status)) = mpi::request::wait_any(&mut requests) {
27                println!("Request with index {} completed", index);
28            }
29            println!("All requests completed");
30        } else {
31            let secs = time::Duration::from_secs(world.rank() as u64);
32
33            thread::sleep(secs);
34
35            let rreq = world.any_process().immediate_receive_into(scope, &mut y);
36            rreq.wait();
37            println!("Process {} received data", world.rank());
38        }
39    });
40}
examples/readme.rs (line 23)
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}
examples/send_receive.rs (line 31)
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 next_process = world.process_at_rank(next_rank);
15    let previous_rank = (rank - 1 + size) % size;
16    let previous_process = world.process_at_rank(previous_rank);
17
18    let (msg, status): (Rank, _) = p2p::send_receive(&rank, &previous_process, &next_process);
19    println!(
20        "Process {} got message {}.\nStatus is: {:?}",
21        rank, msg, status
22    );
23    world.barrier();
24    assert_eq!(msg, next_rank);
25
26    if rank > 0 {
27        let msg: [Rank; 3] = [rank, rank + 1, rank - 1];
28        world.process_at_rank(0).send(&msg);
29    } else {
30        for _ in 1..size {
31            let (msg, status) = world.any_process().receive_vec::<Rank>();
32            println!(
33                "Process {} got long message {:?}.\nStatus is: {:?}",
34                rank, msg, status
35            );
36
37            let x = status.source_rank();
38            let v = vec![x, x + 1, x - 1];
39            assert_eq!(v, msg);
40        }
41    }
42    world.barrier();
43
44    let mut x = rank;
45    p2p::send_receive_replace_into(&mut x, &next_process, &previous_process);
46    assert_eq!(x, previous_rank);
47}
examples/immediate_barrier.rs (line 23)
10fn main() {
11    use mpi::traits::*;
12    let universe = mpi::initialize().unwrap();
13    let world = universe.world();
14    let size = world.size();
15    let receiver_rank = 0;
16
17    if world.rank() == receiver_rank {
18        // receiver process
19        let n = (size - 1) as usize;
20        let mut buf = vec![0u64; 3 * n];
21        // receive first 2 * n messages
22        for x in buf[0..2 * n].iter_mut() {
23            world.any_process().receive_into(x);
24        }
25        // signal the waiting senders that 2 * n messages have been received
26        let breq = world.immediate_barrier();
27        // receive remaining n messages
28        for x in buf[2 * n..3 * n].iter_mut() {
29            world.any_process().receive_into(x);
30        }
31        println!("{:?}", buf);
32        // messages "1" and "2" may be interleaved, but all have to be contained within the first
33        // 2 * n slots of the buffer
34        assert_eq!(buf[0..2 * n].iter().filter(|&&x| x == 1).count(), n);
35        assert_eq!(buf[0..2 * n].iter().filter(|&&x| x == 2).count(), n);
36        // the last n slots in the buffer may only contain message "3"
37        assert!(buf[2 * n..3 * n].iter().all(|&x| x == 3));
38        // clean up the barrier request
39        breq.wait();
40    } else {
41        // sender processes
42        // send message "1"
43        world.process_at_rank(0).send(&1u64);
44        // join barrier, but do not block
45        let breq = world.immediate_barrier();
46        // send message "2"
47        world.process_at_rank(0).send(&2u64);
48        // wait for receiver process to receive the first 2 * n messages
49        breq.wait();
50        // send message "3"
51        world.process_at_rank(0).send(&3u64);
52    }
53}
Source

fn this_process(&self) -> Process<'_>

A Process for the calling process

Examples found in repository?
examples/buffered.rs (line 29)
8fn main() {
9    let mut universe = mpi::initialize().unwrap();
10    // Try to attach a buffer.
11    universe.set_buffer_size(BUFFER_SIZE);
12    // Check buffer size matches.
13    assert_eq!(universe.buffer_size(), BUFFER_SIZE);
14    // Try to detach the buffer.
15    universe.detach_buffer();
16    // Attach another buffer.
17    universe.set_buffer_size(BUFFER_SIZE);
18
19    let world = universe.world();
20
21    let x = vec![std::f32::consts::PI; 1024];
22    let mut y = vec![0.0; 1024];
23    mpi::request::scope(|scope| {
24        let _rreq = WaitGuard::from(
25            world
26                .any_process()
27                .immediate_receive_into(scope, &mut y[..]),
28        );
29        world.this_process().buffered_send(&x[..]);
30    });
31    assert_eq!(x, y);
32}
More examples
Hide additional examples
examples/immediate.rs (line 15)
7fn main() {
8    let universe = mpi::initialize().unwrap();
9    let world = universe.world();
10
11    let x = std::f32::consts::PI;
12    let mut y: f32 = 0.0;
13
14    mpi::request::scope(|scope| {
15        let mut sreq = world.this_process().immediate_send(scope, &x);
16        let rreq = world.any_process().immediate_receive_into(scope, &mut y);
17        rreq.wait();
18        loop {
19            match sreq.test() {
20                Ok(_) => {
21                    break;
22                }
23                Err(req) => {
24                    sreq = req;
25                }
26            }
27        }
28    });
29    assert_eq!(x, y);
30
31    y = 0.0;
32    mpi::request::scope(|scope| {
33        let _rreq = WaitGuard::from(world.any_process().immediate_receive_into(scope, &mut y));
34        // WARNING: the *ready* send is *only* permissible here because we're
35        // sending to self. Use of *ready* would be a race condition and thus
36        // erroneous otherwise.
37        //
38        // One would typically use `immediate_send` to avoid the unsafety.
39        let _sreq =
40            WaitGuard::from(unsafe { world.this_process().immediate_ready_send(scope, &x) });
41    });
42    assert_eq!(x, y);
43
44    assert!(world.any_process().immediate_probe().is_none());
45    assert!(world.any_process().immediate_matched_probe().is_none());
46
47    y = 0.0;
48    mpi::request::scope(|scope| {
49        let _sreq: WaitGuard<_, _> = world
50            .this_process()
51            .immediate_synchronous_send(scope, &x)
52            .into();
53        let (msg, _) = loop {
54            // Spin for message availability. There is no guarantee that
55            // immediate sends, even to the same process, will be immediately
56            // visible to an immediate probe.
57            let preq = world.any_process().immediate_matched_probe();
58            if let Some(p) = preq {
59                break p;
60            }
61        };
62        let _rreq: WaitGuard<_, _> = msg.immediate_matched_receive_into(scope, &mut y).into();
63    });
64    assert_eq!(x, y);
65
66    let future = world.any_process().immediate_receive();
67    world.this_process().send(&x);
68    let (msg, _) = future.get();
69    assert_eq!(x, msg);
70
71    let future = world.any_process().immediate_receive();
72    let res = future.r#try();
73    assert!(res.is_err());
74    let mut future = res.err().unwrap();
75    world.this_process().send(&x);
76    loop {
77        match future.r#try() {
78            Ok((msg, _)) => {
79                assert_eq!(x, msg);
80                break;
81            }
82            Err(f) => {
83                future = f;
84            }
85        }
86    }
87
88    mpi::request::scope(|scope| {
89        let sreq = world.this_process().immediate_send(scope, &x);
90        sreq.cancel();
91        sreq.wait();
92
93        let _sreq = CancelGuard::from(world.this_process().immediate_receive_into(scope, &mut y));
94    });
95}
examples/immediate_multiple_requests.rs (line 17)
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 x: i32 = 100;
14    let mut y: i32 = 0;
15
16    mpi::request::scope(|scope| {
17        let sreq = world.this_process().immediate_send(scope, &x);
18        let rreq = world.this_process().immediate_receive_into(scope, &mut y);
19        let result = rreq.wait_for_data();
20        assert_eq!(*result, x);
21        sreq.wait();
22    });
23
24    // Test wait_any()
25    let mut result: Vec<i32> = vec![0; COUNT];
26    let prev_proc = (rank - 1 + size) % size;
27    let next_proc = (rank + 1) % size;
28    mpi::request::multiple_scope(2 * COUNT, |scope, coll| {
29        for _ in 0..result.len() {
30            let sreq = world
31                .process_at_rank(next_proc)
32                .immediate_send(scope, &rank);
33            coll.add(sreq);
34        }
35        for val in result.iter_mut() {
36            let rreq = world
37                .process_at_rank(prev_proc)
38                .immediate_receive_into(scope, val);
39            coll.add(rreq);
40        }
41        let mut send_count = 0;
42        let mut recv_count = 0;
43        while coll.incomplete() > 0 {
44            let (_, _, result) = coll.wait_any().unwrap();
45            if *result == rank {
46                send_count += 1;
47            } else {
48                recv_count += 1;
49            }
50        }
51        assert_eq!(send_count, COUNT);
52        assert_eq!(recv_count, COUNT);
53    });
54
55    let mut result: Vec<i32> = vec![0; COUNT];
56    // Test wait_some()
57    mpi::request::multiple_scope(2 * COUNT, |scope, coll| {
58        for _ in 0..result.len() {
59            let sreq = world
60                .process_at_rank(next_proc)
61                .immediate_send(scope, &rank);
62            coll.add(sreq);
63        }
64        for val in result.iter_mut() {
65            let rreq = world
66                .process_at_rank(prev_proc)
67                .immediate_receive_into(scope, val);
68            coll.add(rreq);
69        }
70        let mut send_count = 0;
71        let mut recv_count = 0;
72        let mut some_buf = vec![];
73        let mut finished = 0;
74        while coll.incomplete() > 0 {
75            coll.wait_some(&mut some_buf);
76            println!("wait_some(): {} request(s) completed", some_buf.len());
77            finished += some_buf.len();
78            assert_eq!(coll.incomplete(), 2 * COUNT - finished);
79            for &(_, _, result) in some_buf.iter() {
80                if *result == rank {
81                    send_count += 1;
82                } else {
83                    recv_count += 1;
84                }
85            }
86        }
87        assert_eq!(send_count, COUNT);
88        assert_eq!(recv_count, COUNT);
89    });
90
91    let mut result: Vec<i32> = vec![0; COUNT];
92    // Test wait_all()
93    mpi::request::multiple_scope(2 * COUNT, |scope, coll| {
94        for _ in 0..result.len() {
95            let sreq = world
96                .process_at_rank(next_proc)
97                .immediate_send(scope, &rank);
98            coll.add(sreq);
99        }
100        for val in result.iter_mut() {
101            let rreq = world
102                .process_at_rank(prev_proc)
103                .immediate_receive_into(scope, val);
104            coll.add(rreq);
105        }
106
107        let mut out = vec![];
108        coll.wait_all(&mut out);
109        assert_eq!(out.len(), 2 * COUNT);
110        let mut send_count = 0;
111        let mut recv_count = 0;
112        for (_, _, result) in out {
113            if *result == rank {
114                send_count += 1;
115            } else {
116                recv_count += 1;
117            }
118        }
119        assert_eq!(send_count, COUNT);
120        assert_eq!(recv_count, COUNT);
121    });
122
123    // Check wait_*() with a buffer of increasing values
124    let x: Vec<i32> = (0..COUNT as i32).collect();
125    let mut result: Vec<i32> = vec![0; COUNT];
126    mpi::request::multiple_scope(2 * COUNT, |scope, coll| {
127        for elm in &x {
128            let sreq = world.process_at_rank(next_proc).immediate_send(scope, elm);
129            coll.add(sreq);
130        }
131        for val in result.iter_mut() {
132            let rreq = world
133                .process_at_rank(prev_proc)
134                .immediate_receive_into(scope, val);
135            coll.add(rreq);
136        }
137        let mut out: Vec<(usize, Status, &i32)> = vec![];
138        coll.wait_all(&mut out);
139        assert_eq!(out.len(), 2 * COUNT);
140    });
141    // Ensure the result and x are an incrementing array of integers
142    result.sort();
143    assert_eq!(result, x);
144}
Source

fn compare(&self, other: &dyn Communicator) -> CommunicatorRelation

Compare two communicators.

See enum CommunicatorRelation.

§Standard section(s)

6.4.1

Examples found in repository?
examples/duplicate.rs (line 14)
6fn main() {
7    let universe = mpi::initialize().unwrap();
8    let world = universe.world();
9    let moon = world.duplicate();
10
11    world.barrier();
12    moon.barrier();
13
14    assert_eq!(CommunicatorRelation::Congruent, world.compare(&moon));
15}
Source

fn duplicate(&self) -> SimpleCommunicator

Duplicate a communicator.

§Examples

See examples/duplicate.rs

§Standard section(s)

6.4.2

Examples found in repository?
examples/duplicate.rs (line 9)
6fn main() {
7    let universe = mpi::initialize().unwrap();
8    let world = universe.world();
9    let moon = world.duplicate();
10
11    world.barrier();
12    moon.barrier();
13
14    assert_eq!(CommunicatorRelation::Congruent, world.compare(&moon));
15}
More examples
Hide additional examples
examples/attributes.rs (line 59)
48fn main() {
49    let universe = mpi::initialize().unwrap();
50    println!("Universe: {:?}", universe.size());
51    let mut world = universe.world();
52    println!("World   : {}", world.size());
53    world.set_attr(MyData1(10));
54    world.set_attr(MyData2(20));
55    assert_eq!(world.get_attr::<MyData1>(), Some(MyData1(10)).as_ref());
56    println!("Got from world: {:?}", world.get_attr::<MyData1>());
57    assert_eq!(world.get_attr::<MyData2>(), Some(MyData2(20)).as_ref());
58    println!("Got from world: {:?}", world.get_attr::<MyData2>());
59    let comm = world.duplicate();
60    assert_eq!(comm.get_attr::<MyData1>(), Some(MyData1(11)).as_ref());
61    println!("Got from comm: {:?}", comm.get_attr::<MyData1>());
62    assert_eq!(comm.get_attr::<MyData2>(), None);
63    println!("Got from comm: {:?}", comm.get_attr::<MyData2>());
64    let mut comm2 = comm.duplicate();
65    with_trait_object(&mut comm2);
66}
Source

fn split_by_color(&self, color: Color) -> Option<SimpleCommunicator>

Split a communicator by color.

Creates as many new communicators as distinct values of color are given. All processes with the same value of color join the same communicator. A process that passes the special undefined color will not join a new communicator and None is returned.

§Examples

See examples/split.rs

§Standard section(s)

6.4.2

Examples found in repository?
examples/split.rs (line 64)
6fn main() {
7    let universe = mpi::initialize().unwrap();
8    let world = universe.world();
9
10    let odd = (0..world.size()).filter(|x| x % 2 != 0).collect::<Vec<_>>();
11    let odd_group = world.group().include(&odd[..]);
12    let even_group = world.group().difference(&odd_group);
13    assert!(
14        (world.rank() % 2 == 0 && even_group.rank().is_some() && odd_group.rank().is_none())
15            || (even_group.rank().is_none() && odd_group.rank().is_some())
16    );
17    let my_group = if odd_group.rank().is_some() {
18        &odd_group
19    } else {
20        &even_group
21    };
22    let empty_group = SystemGroup::empty();
23
24    let oddness_comm = world.split_by_subgroup_collective(my_group);
25    assert!(oddness_comm.is_some());
26    let oddness_comm = oddness_comm.unwrap();
27    assert_eq!(
28        GroupRelation::Identical,
29        oddness_comm.group().compare(my_group)
30    );
31
32    let odd_comm = if odd_group.rank().is_some() {
33        world.split_by_subgroup_collective(&odd_group)
34    } else {
35        world.split_by_subgroup_collective(&empty_group)
36    };
37    if odd_group.rank().is_some() {
38        assert!(odd_comm.is_some());
39        let odd_comm = odd_comm.unwrap();
40        assert_eq!(
41            GroupRelation::Identical,
42            odd_comm.group().compare(&odd_group)
43        );
44    } else {
45        assert!(odd_comm.is_none());
46    }
47
48    #[cfg(not(msmpi))]
49    {
50        if even_group.rank().is_some() {
51            let even_comm = world.split_by_subgroup(&even_group);
52            assert!(even_comm.is_some());
53            let even_comm = even_comm.unwrap();
54            assert_eq!(
55                GroupRelation::Identical,
56                even_comm.group().compare(&even_group)
57            );
58
59            let no_comm = world.split_by_subgroup(&odd_group);
60            assert!(no_comm.is_none());
61        }
62    }
63
64    let oddness_comm = world.split_by_color(Color::with_value(world.rank() % 2));
65    assert!(oddness_comm.is_some());
66    let oddness_comm = oddness_comm.unwrap();
67    assert_eq!(
68        GroupRelation::Identical,
69        oddness_comm.group().compare(my_group)
70    );
71
72    let odd_comm = world.split_by_color(if world.rank() % 2 != 0 {
73        Color::with_value(0)
74    } else {
75        Color::undefined()
76    });
77    if world.rank() % 2 != 0 {
78        assert!(odd_comm.is_some());
79        let odd_comm = odd_comm.unwrap();
80        assert_eq!(
81            GroupRelation::Identical,
82            odd_comm.group().compare(&odd_group)
83        );
84    } else {
85        assert!(odd_comm.is_none());
86    }
87}
Source

fn split_by_color_with_key( &self, color: Color, key: Key, ) -> Option<SimpleCommunicator>

Split a communicator by color.

Like split() but orders processes according to the value of key in the new communicators.

§Standard section(s)

6.4.2

Source

fn split_shared(&self, key: c_int) -> SimpleCommunicator

Split the communicator into subcommunicators, each of which can create a shared memory region.

Within each subgroup, the processes are ranked in the order defined by the value of the argument key, with ties broken according to their rank in the old group.

§Standard section(s)

6.4.2 (See: MPI_Comm_split_type)

Source

fn split_by_subgroup_collective( &self, group: &dyn Group, ) -> Option<SimpleCommunicator>

Split a communicator collectively by subgroup.

Proceses pass in a group that is a subgroup of the group associated with the old communicator. Different processes may pass in different groups, but if two groups are different, they have to be disjunct. One new communicator is created for each distinct group. The new communicator is returned if a process is a member of the group he passed in, otherwise None.

This call is a collective operation on the old communicator so all processes have to partake.

§Examples

See examples/split.rs

§Standard section(s)

6.4.2

Examples found in repository?
examples/dyn_communicator.rs (line 20)
7fn main() {
8    let universe = mpi::initialize().unwrap();
9    let world = universe.world();
10
11    prefix_sum(&world, "World: ");
12
13    let g1 = world
14        .group()
15        .include(&(0..world.size()).filter(|x| x % 2 != 0).collect::<Vec<_>>());
16    let g2 = world
17        .group()
18        .include(&(0..world.size()).filter(|x| x % 2 == 0).collect::<Vec<_>>());
19    world
20        .split_by_subgroup_collective(&g1)
21        .map(|c| prefix_sum(&c, "Group 1: "));
22    world
23        .split_by_subgroup_collective(&g2)
24        .map(|c| prefix_sum(&c, "Group 2: "));
25}
More examples
Hide additional examples
examples/split.rs (line 24)
6fn main() {
7    let universe = mpi::initialize().unwrap();
8    let world = universe.world();
9
10    let odd = (0..world.size()).filter(|x| x % 2 != 0).collect::<Vec<_>>();
11    let odd_group = world.group().include(&odd[..]);
12    let even_group = world.group().difference(&odd_group);
13    assert!(
14        (world.rank() % 2 == 0 && even_group.rank().is_some() && odd_group.rank().is_none())
15            || (even_group.rank().is_none() && odd_group.rank().is_some())
16    );
17    let my_group = if odd_group.rank().is_some() {
18        &odd_group
19    } else {
20        &even_group
21    };
22    let empty_group = SystemGroup::empty();
23
24    let oddness_comm = world.split_by_subgroup_collective(my_group);
25    assert!(oddness_comm.is_some());
26    let oddness_comm = oddness_comm.unwrap();
27    assert_eq!(
28        GroupRelation::Identical,
29        oddness_comm.group().compare(my_group)
30    );
31
32    let odd_comm = if odd_group.rank().is_some() {
33        world.split_by_subgroup_collective(&odd_group)
34    } else {
35        world.split_by_subgroup_collective(&empty_group)
36    };
37    if odd_group.rank().is_some() {
38        assert!(odd_comm.is_some());
39        let odd_comm = odd_comm.unwrap();
40        assert_eq!(
41            GroupRelation::Identical,
42            odd_comm.group().compare(&odd_group)
43        );
44    } else {
45        assert!(odd_comm.is_none());
46    }
47
48    #[cfg(not(msmpi))]
49    {
50        if even_group.rank().is_some() {
51            let even_comm = world.split_by_subgroup(&even_group);
52            assert!(even_comm.is_some());
53            let even_comm = even_comm.unwrap();
54            assert_eq!(
55                GroupRelation::Identical,
56                even_comm.group().compare(&even_group)
57            );
58
59            let no_comm = world.split_by_subgroup(&odd_group);
60            assert!(no_comm.is_none());
61        }
62    }
63
64    let oddness_comm = world.split_by_color(Color::with_value(world.rank() % 2));
65    assert!(oddness_comm.is_some());
66    let oddness_comm = oddness_comm.unwrap();
67    assert_eq!(
68        GroupRelation::Identical,
69        oddness_comm.group().compare(my_group)
70    );
71
72    let odd_comm = world.split_by_color(if world.rank() % 2 != 0 {
73        Color::with_value(0)
74    } else {
75        Color::undefined()
76    });
77    if world.rank() % 2 != 0 {
78        assert!(odd_comm.is_some());
79        let odd_comm = odd_comm.unwrap();
80        assert_eq!(
81            GroupRelation::Identical,
82            odd_comm.group().compare(&odd_group)
83        );
84    } else {
85        assert!(odd_comm.is_none());
86    }
87}
Source

fn split_by_subgroup(&self, group: &dyn Group) -> Option<SimpleCommunicator>

Split a communicator by subgroup.

Like split_by_subgroup_collective() but not a collective operation.

§Examples

See examples/split.rs

§Standard section(s)

6.4.2

Examples found in repository?
examples/split.rs (line 51)
6fn main() {
7    let universe = mpi::initialize().unwrap();
8    let world = universe.world();
9
10    let odd = (0..world.size()).filter(|x| x % 2 != 0).collect::<Vec<_>>();
11    let odd_group = world.group().include(&odd[..]);
12    let even_group = world.group().difference(&odd_group);
13    assert!(
14        (world.rank() % 2 == 0 && even_group.rank().is_some() && odd_group.rank().is_none())
15            || (even_group.rank().is_none() && odd_group.rank().is_some())
16    );
17    let my_group = if odd_group.rank().is_some() {
18        &odd_group
19    } else {
20        &even_group
21    };
22    let empty_group = SystemGroup::empty();
23
24    let oddness_comm = world.split_by_subgroup_collective(my_group);
25    assert!(oddness_comm.is_some());
26    let oddness_comm = oddness_comm.unwrap();
27    assert_eq!(
28        GroupRelation::Identical,
29        oddness_comm.group().compare(my_group)
30    );
31
32    let odd_comm = if odd_group.rank().is_some() {
33        world.split_by_subgroup_collective(&odd_group)
34    } else {
35        world.split_by_subgroup_collective(&empty_group)
36    };
37    if odd_group.rank().is_some() {
38        assert!(odd_comm.is_some());
39        let odd_comm = odd_comm.unwrap();
40        assert_eq!(
41            GroupRelation::Identical,
42            odd_comm.group().compare(&odd_group)
43        );
44    } else {
45        assert!(odd_comm.is_none());
46    }
47
48    #[cfg(not(msmpi))]
49    {
50        if even_group.rank().is_some() {
51            let even_comm = world.split_by_subgroup(&even_group);
52            assert!(even_comm.is_some());
53            let even_comm = even_comm.unwrap();
54            assert_eq!(
55                GroupRelation::Identical,
56                even_comm.group().compare(&even_group)
57            );
58
59            let no_comm = world.split_by_subgroup(&odd_group);
60            assert!(no_comm.is_none());
61        }
62    }
63
64    let oddness_comm = world.split_by_color(Color::with_value(world.rank() % 2));
65    assert!(oddness_comm.is_some());
66    let oddness_comm = oddness_comm.unwrap();
67    assert_eq!(
68        GroupRelation::Identical,
69        oddness_comm.group().compare(my_group)
70    );
71
72    let odd_comm = world.split_by_color(if world.rank() % 2 != 0 {
73        Color::with_value(0)
74    } else {
75        Color::undefined()
76    });
77    if world.rank() % 2 != 0 {
78        assert!(odd_comm.is_some());
79        let odd_comm = odd_comm.unwrap();
80        assert_eq!(
81            GroupRelation::Identical,
82            odd_comm.group().compare(&odd_group)
83        );
84    } else {
85        assert!(odd_comm.is_none());
86    }
87}
Source

fn split_by_subgroup_with_tag( &self, group: &dyn Group, tag: Tag, ) -> Option<SimpleCommunicator>

Split a communicator by subgroup

Like split_by_subgroup() but can avoid collision of concurrent calls (i.e. multithreaded) by passing in distinct tags.

§Standard section(s)

6.4.2

Source

fn group(&self) -> UserGroup

The group associated with this communicator

§Standard section(s)

6.3.2

Examples found in repository?
examples/dyn_communicator.rs (line 14)
7fn main() {
8    let universe = mpi::initialize().unwrap();
9    let world = universe.world();
10
11    prefix_sum(&world, "World: ");
12
13    let g1 = world
14        .group()
15        .include(&(0..world.size()).filter(|x| x % 2 != 0).collect::<Vec<_>>());
16    let g2 = world
17        .group()
18        .include(&(0..world.size()).filter(|x| x % 2 == 0).collect::<Vec<_>>());
19    world
20        .split_by_subgroup_collective(&g1)
21        .map(|c| prefix_sum(&c, "Group 1: "));
22    world
23        .split_by_subgroup_collective(&g2)
24        .map(|c| prefix_sum(&c, "Group 2: "));
25}
More examples
Hide additional examples
examples/group.rs (line 11)
7fn main() {
8    let universe = mpi::initialize().unwrap();
9    let world = universe.world();
10
11    let g = world.group();
12    // Group accessors and Communicator accessors agree
13    assert_eq!(world.size(), g.size());
14    assert_eq!(world.rank(), g.rank().unwrap());
15
16    // g == g
17    assert_eq!(GroupRelation::Identical, g.compare(&g));
18
19    let h = world.group();
20    // h == g
21    assert_eq!(GroupRelation::Identical, g.compare(&h));
22
23    let i = g.union(&h);
24    // g union h == g union g == g
25    assert_eq!(GroupRelation::Identical, g.compare(&i));
26
27    let empty = g.difference(&h);
28    // g difference h == g difference g = empty Group
29    assert_eq!(
30        GroupRelation::Identical,
31        SystemGroup::empty().compare(&empty)
32    );
33    assert_eq!(0, empty.size());
34
35    // g intersection empty == empty Group
36    assert_eq!(0, g.intersection(&empty).size());
37
38    let first_half: Vec<Rank> = (0..g.size() / 2).collect();
39
40    // f and s are first and second half of g
41    let f = g.include(&first_half[..]);
42    let s = g.exclude(&first_half[..]);
43    // f != s
44    assert_eq!(GroupRelation::Unequal, f.compare(&s));
45
46    // g intersection f == f
47    let f_ = g.intersection(&f);
48    assert_eq!(GroupRelation::Identical, f.compare(&f_));
49    // g intersection s == s
50    let s_ = g.intersection(&s);
51    assert_eq!(GroupRelation::Identical, s.compare(&s_));
52
53    // g difference s == f
54    let f__ = g.difference(&s);
55    assert_eq!(GroupRelation::Identical, f.compare(&f__));
56    // g difference f == s
57    let s__ = g.difference(&f);
58    assert_eq!(GroupRelation::Identical, s.compare(&s__));
59
60    // f union s == g
61    let fs = f.union(&s);
62    assert_eq!(GroupRelation::Identical, g.compare(&fs));
63
64    // f intersection s == empty Group
65    let fs = f.intersection(&s);
66    assert_eq!(GroupRelation::Identical, empty.compare(&fs));
67
68    // rank is either in f or in s
69    assert!(
70        (f.rank().is_some() && s.rank().is_none()) ^ (f.rank().is_none() && s.rank().is_some())
71    );
72
73    // inverting rank mappings
74    let rev: Vec<Rank> = (0..g.size()).rev().collect();
75    let r = g.include(&rev[..]);
76    assert_eq!(
77        Some(rev[g.rank().unwrap() as usize]),
78        r.translate_rank(g.rank().unwrap(), &g)
79    );
80}
examples/split.rs (line 11)
6fn main() {
7    let universe = mpi::initialize().unwrap();
8    let world = universe.world();
9
10    let odd = (0..world.size()).filter(|x| x % 2 != 0).collect::<Vec<_>>();
11    let odd_group = world.group().include(&odd[..]);
12    let even_group = world.group().difference(&odd_group);
13    assert!(
14        (world.rank() % 2 == 0 && even_group.rank().is_some() && odd_group.rank().is_none())
15            || (even_group.rank().is_none() && odd_group.rank().is_some())
16    );
17    let my_group = if odd_group.rank().is_some() {
18        &odd_group
19    } else {
20        &even_group
21    };
22    let empty_group = SystemGroup::empty();
23
24    let oddness_comm = world.split_by_subgroup_collective(my_group);
25    assert!(oddness_comm.is_some());
26    let oddness_comm = oddness_comm.unwrap();
27    assert_eq!(
28        GroupRelation::Identical,
29        oddness_comm.group().compare(my_group)
30    );
31
32    let odd_comm = if odd_group.rank().is_some() {
33        world.split_by_subgroup_collective(&odd_group)
34    } else {
35        world.split_by_subgroup_collective(&empty_group)
36    };
37    if odd_group.rank().is_some() {
38        assert!(odd_comm.is_some());
39        let odd_comm = odd_comm.unwrap();
40        assert_eq!(
41            GroupRelation::Identical,
42            odd_comm.group().compare(&odd_group)
43        );
44    } else {
45        assert!(odd_comm.is_none());
46    }
47
48    #[cfg(not(msmpi))]
49    {
50        if even_group.rank().is_some() {
51            let even_comm = world.split_by_subgroup(&even_group);
52            assert!(even_comm.is_some());
53            let even_comm = even_comm.unwrap();
54            assert_eq!(
55                GroupRelation::Identical,
56                even_comm.group().compare(&even_group)
57            );
58
59            let no_comm = world.split_by_subgroup(&odd_group);
60            assert!(no_comm.is_none());
61        }
62    }
63
64    let oddness_comm = world.split_by_color(Color::with_value(world.rank() % 2));
65    assert!(oddness_comm.is_some());
66    let oddness_comm = oddness_comm.unwrap();
67    assert_eq!(
68        GroupRelation::Identical,
69        oddness_comm.group().compare(my_group)
70    );
71
72    let odd_comm = world.split_by_color(if world.rank() % 2 != 0 {
73        Color::with_value(0)
74    } else {
75        Color::undefined()
76    });
77    if world.rank() % 2 != 0 {
78        assert!(odd_comm.is_some());
79        let odd_comm = odd_comm.unwrap();
80        assert_eq!(
81            GroupRelation::Identical,
82            odd_comm.group().compare(&odd_group)
83        );
84    } else {
85        assert!(odd_comm.is_none());
86    }
87}
Source

fn abort(&self, errorcode: c_int) -> !

Abort program execution

§Standard section(s)

8.7

Source

fn test_inter(&self) -> bool

Tests if the communicator is an inter-communicator.

§Standard sections(s)

6.6.1, See MPI_Comm_test_inter

Source

fn set_name(&self, name: &str)

Set the communicator name

§Standard section(s)

6.8, see the MPI_Comm_set_name function

Examples found in repository?
examples/comm_name.rs (line 11)
7fn main() {
8    let universe = mpi::initialize().unwrap();
9    let world = universe.world();
10    assert_eq!("MPI_COMM_WORLD", world.get_name());
11    world.set_name(CNAME);
12    assert_eq!(CNAME, world.get_name());
13}
Source

fn get_name(&self) -> String

Get the communicator name

§Standard section(s)

6.8, see the MPI_Comm_get_name function

Examples found in repository?
examples/comm_name.rs (line 10)
7fn main() {
8    let universe = mpi::initialize().unwrap();
9    let world = universe.world();
10    assert_eq!("MPI_COMM_WORLD", world.get_name());
11    world.set_name(CNAME);
12    assert_eq!(CNAME, world.get_name());
13}
Source

fn create_cartesian_communicator( &self, dims: &[Count], periods: &[bool], reorder: bool, ) -> Option<CartesianCommunicator>

Creates a communicator with ranks laid out in a multi-dimensional space, allowing for easy neighbor-to-neighbor communication, while providing MPI with information to allow it to better optimize the physical locality of ranks that are logically close.

  • dims - array of spatial extents for the cartesian space
  • periods - Must match length of dims. For i in 0 to dims.len(), periods[i] indicates if axis i is periodic. i.e. if true, the element at dims[i] - 1 in axis i is a neighbor of element 0 in axis i
  • reorder - If true, MPI may re-order ranks in the new communicator.
§Standard section(s)

7.5.1 (MPI_Cart_create)

Examples found in repository?
examples/cartesian.rs (line 19)
6fn main() {
7    let universe = mpi::initialize().unwrap();
8
9    let comm = universe.world();
10
11    if comm.size() < 4 {
12        return;
13    }
14
15    let cart_comm = {
16        let dims = [2, 2];
17        let periodic = [false, true];
18        let reorder = true;
19        if let Some(cart_comm) = comm.create_cartesian_communicator(&dims, &periodic, reorder) {
20            cart_comm
21        } else {
22            assert!(comm.rank() >= 4);
23            return;
24        }
25    };
26
27    assert_eq!(2, cart_comm.num_dimensions());
28
29    let mpi::topology::CartesianLayout {
30        dims,
31        periods,
32        coords,
33    } = cart_comm.get_layout();
34
35    assert_eq!([2 as mpi::Count, 2], &dims[..]);
36    assert_eq!([false, true], &periods[..]);
37
38    let xrank = coords[0];
39    let yrank = coords[1];
40
41    assert!(0 <= xrank && xrank < 2);
42    assert!(0 <= yrank && yrank < 2);
43
44    let xcomm = cart_comm.subgroup(&[true, false]);
45    let ycomm = cart_comm.subgroup(&[false, true]);
46
47    assert_eq!(2, xcomm.size());
48    assert_eq!(xrank, xcomm.rank());
49
50    assert_eq!(2, ycomm.size());
51    assert_eq!(yrank, ycomm.rank());
52
53    // the first dimension is non-periodic
54    let (x_src, x_dest) = cart_comm.shift(0, 1);
55    if xrank == 0 {
56        assert!(x_src.is_none());
57        assert!(x_dest.is_some());
58
59        let coords = cart_comm.rank_to_coordinates(x_dest.unwrap());
60        assert_eq!(1, coords[0]);
61    } else {
62        assert_eq!(1, xrank);
63
64        assert!(x_src.is_some());
65        assert!(x_dest.is_none());
66
67        let coords = cart_comm.rank_to_coordinates(x_src.unwrap());
68        assert_eq!(0, coords[0]);
69    }
70
71    // the second dimension is periodic
72    {
73        let (y_src, y_dest) = cart_comm.shift(1, 1);
74        assert!(y_src.is_some());
75        assert!(y_dest.is_some());
76
77        let y_src_coords = cart_comm.rank_to_coordinates(y_src.unwrap());
78        assert_eq!((yrank - 1) & 0b1, y_src_coords[1]);
79
80        let y_dest_coords = cart_comm.rank_to_coordinates(y_dest.unwrap());
81        assert_eq!((yrank + 1) & 0b1, y_dest_coords[1]);
82    }
83
84    // second dimension shift by 2 should be identity
85    {
86        let (y_src, y_dest) = cart_comm.shift(1, 2);
87        assert_eq!(comm.rank(), y_src.unwrap());
88        assert_eq!(comm.rank(), y_dest.unwrap());
89    }
90}
Source

fn cartesian_map(&self, dims: &[Count], periods: &[bool]) -> Option<Rank>

Gets the target rank of this rank as-if create_cartesian_communicator had been called with dims, periods, and reorder = true.

Returns None if the local process would not particate in the new CartesianCommunciator.

  • dims - array of spatial extents for the cartesian space
  • periods - Must match length of dims. For i in 0 to dims.len(), periods[i] indicates if axis i is periodic. i.e. if true, the element at dims[i] - 1 in axis i is a neighbor of element 0 in axis i
§Standard section

7.5.8 (MPI_Cart_map)

Examples found in repository?
examples/cartesian_map.rs (line 10)
5fn main() {
6    let universe = mpi::initialize().unwrap();
7
8    let comm = universe.world();
9
10    let new_rank = comm.cartesian_map(&[2, comm.size() / 4], &[false, false]);
11
12    println!("{} -> {:?}", comm.rank(), new_rank);
13}
Source

fn pack_size<Dt>(&self, incount: Count, datatype: &Dt) -> Count
where Dt: Datatype, Self: Sized,

Gets the implementation-defined buffer size required to pack ‘incount’ elements of type ‘datatype’.

§Standard section(s)

4.2, see MPI_Pack_size

Source

fn pack<Buf>(&self, inbuf: &Buf) -> Vec<u8>
where Buf: ?Sized + Buffer, Self: Sized,

Packs inbuf into a byte array with an implementation-defined format. Often paired with unpack to convert back into a specific datatype.

§Standard Sections

4.2, see MPI_Pack

Examples found in repository?
examples/pack.rs (line 10)
5fn main() {
6    let universe = mpi::initialize().unwrap();
7    let world = universe.world();
8
9    let ints = [3i32, 2, 1];
10    let packed = world.pack(&ints[..]);
11
12    let mut new_ints = [0, 0, 0];
13    unsafe {
14        world.unpack_into(&packed, &mut new_ints[..], 0);
15    }
16
17    assert_eq!([3, 2, 1], new_ints);
18}
Source

fn pack_into<Buf>( &self, inbuf: &Buf, outbuf: &mut [u8], position: Count, ) -> Count
where Buf: ?Sized + Buffer, Self: Sized,

Packs inbuf into a byte array with an implementation-defined format. Often paired with unpack to convert back into a specific datatype.

§Standard Sections

4.2, see MPI_Pack

Source

unsafe fn unpack_into<Buf>( &self, inbuf: &[u8], outbuf: &mut Buf, position: Count, ) -> Count
where Buf: ?Sized + BufferMut, Self: Sized,

Unpacks an implementation-specific byte array from pack or pack_into into a buffer of a specific datatype.

§Standard Sections

4.2, see MPI_Unpack

Examples found in repository?
examples/pack.rs (line 14)
5fn main() {
6    let universe = mpi::initialize().unwrap();
7    let world = universe.world();
8
9    let ints = [3i32, 2, 1];
10    let packed = world.pack(&ints[..]);
11
12    let mut new_ints = [0, 0, 0];
13    unsafe {
14        world.unpack_into(&packed, &mut new_ints[..], 0);
15    }
16
17    assert_eq!([3, 2, 1], new_ints);
18}
Source

fn parent(&self) -> Option<InterCommunicator>

Returns the parent Communicator, if any

§Standard Sections

10.3.2, see MPI_Comm_get_parent

Examples found in repository?
examples/spawn_multiple.rs (line 11)
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}
More examples
Hide additional examples
examples/spawn.rs (line 12)
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}

Implementors§