Skip to main content

GraphCommunicator

Struct GraphCommunicator 

Source
pub struct GraphCommunicator { /* private fields */ }
Expand description

A communicator carrying a general graph topology (MPI_Graph_create).

Implementations§

Source§

impl GraphCommunicator

Source

pub fn num_nodes(&self) -> Count

Total number of nodes in the graph.

Source

pub fn num_edges(&self) -> Count

Total number of (directed) edges in the graph.

Source

pub fn neighbor_count(&self, rank: Rank) -> Count

The number of neighbours of rank (MPI_Graph_neighbors_count).

Examples found in repository?
examples/topo_inter.rs (line 25)
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    // ---- graph topology: a ring, node i adjacent to i-1 and i+1 ----
12    if size >= 2 {
13        let mut index = Vec::new();
14        let mut edges = Vec::new();
15        for i in 0..size {
16            edges.push((i - 1 + size) % size);
17            edges.push((i + 1) % size);
18            index.push(2 * (i + 1));
19        }
20        let g = world
21            .create_graph_communicator(&index, &edges)
22            .expect("graph create returned None");
23        let expected = vec![(rank - 1 + size) % size, (rank + 1) % size];
24        assert_eq!(g.my_neighbors(), expected, "graph neighbours mismatch");
25        assert_eq!(g.neighbor_count(rank), 2);
26        // Neighbourhood all-gather: each neighbour contributes its own rank.
27        let mut ng = vec![-1i32; 2];
28        g.neighbor_all_gather_into(&rank, &mut ng[..]);
29        assert_eq!(ng, expected, "neighbor_all_gather mismatch");
30        g.barrier();
31    }
32
33    // ---- distributed-graph adjacent: directed ring (recv prev, send next) ----
34    if size >= 2 {
35        let prev = (rank - 1 + size) % size;
36        let next = (rank + 1) % size;
37        let dg = world.create_dist_graph_adjacent(&[prev], &[next]);
38        assert_eq!(dg.in_degree(), 1, "dist-graph in-degree");
39        assert_eq!(dg.out_degree(), 1, "dist-graph out-degree");
40        let mut r = vec![-1i32; 1];
41        dg.neighbor_all_gather_into(&rank, &mut r[..]);
42        assert_eq!(r, vec![prev], "dist-graph neighbor mismatch");
43        dg.barrier();
44    }
45
46    // ---- inter-communicator: split world into two halves ----
47    if size >= 2 {
48        let half = size / 2;
49        let in_a = rank < half;
50        let inter = world.split_intercommunicator(in_a);
51        assert_eq!(
52            inter.local_size() + inter.remote_size(),
53            size,
54            "intercomm size mismatch"
55        );
56
57        // Leaders of the two groups exchange their world ranks across the
58        // inter-communicator.
59        if inter.rank() == 0 {
60            if in_a {
61                inter.process_at_rank(0).send(&rank);
62                let (peer, _): (i32, _) = inter.process_at_rank(0).receive();
63                assert_eq!(peer, half, "intercomm exchange mismatch (A)");
64            } else {
65                let (peer, _): (i32, _) = inter.process_at_rank(0).receive();
66                assert_eq!(peer, 0, "intercomm exchange mismatch (B)");
67                inter.process_at_rank(0).send(&rank);
68            }
69        }
70
71        // Merge back into one intra-communicator spanning everyone.
72        let merged = inter.merge();
73        assert_eq!(merged.size(), size, "merge size mismatch");
74        merged.barrier();
75    }
76
77    world.barrier();
78    if rank == 0 {
79        println!("TOPO/INTER PASS: graph + inter-communicator verified on {size} ranks.");
80    }
81}
Source

pub fn neighbors(&self, rank: Rank) -> Vec<Rank>

The neighbours of rank (MPI_Graph_neighbors).

Source

pub fn my_neighbors(&self) -> Vec<Rank>

This process’s neighbours.

Examples found in repository?
examples/topo_inter.rs (line 24)
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    // ---- graph topology: a ring, node i adjacent to i-1 and i+1 ----
12    if size >= 2 {
13        let mut index = Vec::new();
14        let mut edges = Vec::new();
15        for i in 0..size {
16            edges.push((i - 1 + size) % size);
17            edges.push((i + 1) % size);
18            index.push(2 * (i + 1));
19        }
20        let g = world
21            .create_graph_communicator(&index, &edges)
22            .expect("graph create returned None");
23        let expected = vec![(rank - 1 + size) % size, (rank + 1) % size];
24        assert_eq!(g.my_neighbors(), expected, "graph neighbours mismatch");
25        assert_eq!(g.neighbor_count(rank), 2);
26        // Neighbourhood all-gather: each neighbour contributes its own rank.
27        let mut ng = vec![-1i32; 2];
28        g.neighbor_all_gather_into(&rank, &mut ng[..]);
29        assert_eq!(ng, expected, "neighbor_all_gather mismatch");
30        g.barrier();
31    }
32
33    // ---- distributed-graph adjacent: directed ring (recv prev, send next) ----
34    if size >= 2 {
35        let prev = (rank - 1 + size) % size;
36        let next = (rank + 1) % size;
37        let dg = world.create_dist_graph_adjacent(&[prev], &[next]);
38        assert_eq!(dg.in_degree(), 1, "dist-graph in-degree");
39        assert_eq!(dg.out_degree(), 1, "dist-graph out-degree");
40        let mut r = vec![-1i32; 1];
41        dg.neighbor_all_gather_into(&rank, &mut r[..]);
42        assert_eq!(r, vec![prev], "dist-graph neighbor mismatch");
43        dg.barrier();
44    }
45
46    // ---- inter-communicator: split world into two halves ----
47    if size >= 2 {
48        let half = size / 2;
49        let in_a = rank < half;
50        let inter = world.split_intercommunicator(in_a);
51        assert_eq!(
52            inter.local_size() + inter.remote_size(),
53            size,
54            "intercomm size mismatch"
55        );
56
57        // Leaders of the two groups exchange their world ranks across the
58        // inter-communicator.
59        if inter.rank() == 0 {
60            if in_a {
61                inter.process_at_rank(0).send(&rank);
62                let (peer, _): (i32, _) = inter.process_at_rank(0).receive();
63                assert_eq!(peer, half, "intercomm exchange mismatch (A)");
64            } else {
65                let (peer, _): (i32, _) = inter.process_at_rank(0).receive();
66                assert_eq!(peer, 0, "intercomm exchange mismatch (B)");
67                inter.process_at_rank(0).send(&rank);
68            }
69        }
70
71        // Merge back into one intra-communicator spanning everyone.
72        let merged = inter.merge();
73        assert_eq!(merged.size(), size, "merge size mismatch");
74        merged.barrier();
75    }
76
77    world.barrier();
78    if rank == 0 {
79        println!("TOPO/INTER PASS: graph + inter-communicator verified on {size} ranks.");
80    }
81}
Source

pub fn neighbor_all_gather_into<S, R>(&self, sendbuf: &S, recvbuf: &mut R)
where S: Buffer + ?Sized, R: BufferMut + ?Sized,

Gather each rank’s sendbuf from all of its neighbours (MPI_Neighbor_allgather). recvbuf holds one block per neighbour, in neighbour order.

Examples found in repository?
examples/topo_inter.rs (line 28)
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    // ---- graph topology: a ring, node i adjacent to i-1 and i+1 ----
12    if size >= 2 {
13        let mut index = Vec::new();
14        let mut edges = Vec::new();
15        for i in 0..size {
16            edges.push((i - 1 + size) % size);
17            edges.push((i + 1) % size);
18            index.push(2 * (i + 1));
19        }
20        let g = world
21            .create_graph_communicator(&index, &edges)
22            .expect("graph create returned None");
23        let expected = vec![(rank - 1 + size) % size, (rank + 1) % size];
24        assert_eq!(g.my_neighbors(), expected, "graph neighbours mismatch");
25        assert_eq!(g.neighbor_count(rank), 2);
26        // Neighbourhood all-gather: each neighbour contributes its own rank.
27        let mut ng = vec![-1i32; 2];
28        g.neighbor_all_gather_into(&rank, &mut ng[..]);
29        assert_eq!(ng, expected, "neighbor_all_gather mismatch");
30        g.barrier();
31    }
32
33    // ---- distributed-graph adjacent: directed ring (recv prev, send next) ----
34    if size >= 2 {
35        let prev = (rank - 1 + size) % size;
36        let next = (rank + 1) % size;
37        let dg = world.create_dist_graph_adjacent(&[prev], &[next]);
38        assert_eq!(dg.in_degree(), 1, "dist-graph in-degree");
39        assert_eq!(dg.out_degree(), 1, "dist-graph out-degree");
40        let mut r = vec![-1i32; 1];
41        dg.neighbor_all_gather_into(&rank, &mut r[..]);
42        assert_eq!(r, vec![prev], "dist-graph neighbor mismatch");
43        dg.barrier();
44    }
45
46    // ---- inter-communicator: split world into two halves ----
47    if size >= 2 {
48        let half = size / 2;
49        let in_a = rank < half;
50        let inter = world.split_intercommunicator(in_a);
51        assert_eq!(
52            inter.local_size() + inter.remote_size(),
53            size,
54            "intercomm size mismatch"
55        );
56
57        // Leaders of the two groups exchange their world ranks across the
58        // inter-communicator.
59        if inter.rank() == 0 {
60            if in_a {
61                inter.process_at_rank(0).send(&rank);
62                let (peer, _): (i32, _) = inter.process_at_rank(0).receive();
63                assert_eq!(peer, half, "intercomm exchange mismatch (A)");
64            } else {
65                let (peer, _): (i32, _) = inter.process_at_rank(0).receive();
66                assert_eq!(peer, 0, "intercomm exchange mismatch (B)");
67                inter.process_at_rank(0).send(&rank);
68            }
69        }
70
71        // Merge back into one intra-communicator spanning everyone.
72        let merged = inter.merge();
73        assert_eq!(merged.size(), size, "merge size mismatch");
74        merged.barrier();
75    }
76
77    world.barrier();
78    if rank == 0 {
79        println!("TOPO/INTER PASS: graph + inter-communicator verified on {size} ranks.");
80    }
81}
Source

pub fn neighbor_all_to_all_into<S, R>(&self, sendbuf: &S, recvbuf: &mut R)
where S: Buffer + ?Sized, R: BufferMut + ?Sized,

Exchange a distinct block with each neighbour (MPI_Neighbor_alltoall). sendbuf and recvbuf hold one block per neighbour, in neighbour order.

Trait Implementations§

Source§

impl Clone for GraphCommunicator

Source§

fn clone(&self) -> GraphCommunicator

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Communicator for GraphCommunicator

Source§

fn size(&self) -> Rank

Number of processes in the communicator (MPI_Comm_size).
Source§

fn rank(&self) -> Rank

This process’s rank in the communicator (MPI_Comm_rank).
Source§

fn target_size(&self) -> Rank

Number of processes on the remote side (equals Communicator::size for an intra-communicator).
Source§

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

A handle to the process with the given rank.
Source§

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

A handle to this process.
Source§

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

A handle matching any source (MPI_ANY_SOURCE), for receives.
Source§

fn group(&self) -> Group

The group underlying this communicator (MPI_Comm_group).
Source§

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

Compare this communicator to other (MPI_Comm_compare).
Source§

fn duplicate(&self) -> SimpleCommunicator

Duplicate the communicator with a fresh context (MPI_Comm_dup). Collective over all members.
Source§

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

Split the communicator by colour (MPI_Comm_split). Collective.
Source§

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

Split by colour, ordering new ranks by key then old rank (MPI_Comm_split). Collective.
Source§

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

Split by an explicit subgroup (MPI_Comm_create style). Collective; returns None for processes not in group.
Source§

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

Abort the whole job with an exit code (MPI_Abort). Notifies every peer so the entire job exits rather than leaving ranks blocked.
Source§

fn set_name(&self, name: &str)

Set the communicator’s name (MPI_Comm_set_name).
Source§

fn get_name(&self) -> String

Get the communicator’s name (MPI_Comm_get_name).
Source§

fn pack_size(&self, incount: Count, dt: DatatypeRef) -> Count

Number of bytes needed to pack incount elements of datatype dt (MPI_Pack_size).
Source§

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

Pack a buffer into a freshly allocated byte vector (MPI_Pack). Since this implementation uses contiguous native layouts, packing is a copy.
Source§

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

Pack a buffer into outbuf starting at byte offset position, returning the new position (MPI_Pack).
Source§

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

Unpack from inbuf starting at byte offset position into outbuf, returning the new position (MPI_Unpack). Read more
Source§

fn create_graph_communicator( &self, index: &[Count], edges: &[Count], ) -> Option<GraphCommunicator>

Create a graph topology communicator (MPI_Graph_create). Read more
Source§

fn create_dist_graph_adjacent( &self, sources: &[Rank], destinations: &[Rank], ) -> DistGraphCommunicator

Create a distributed-graph topology where this rank receives from sources and sends to destinations (MPI_Dist_graph_create_adjacent). Collective; each rank supplies its own adjacency.
Source§

fn split_intercommunicator(&self, in_group_a: bool) -> InterCommunicator

Collectively split this communicator into an inter-communicator between two disjoint groups. Ranks passing true form one group (“A”); the rest form the other. Each rank’s InterCommunicator has the other group as its remote group (MPI_Intercomm_create-style, collective).
Source§

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

Create a Cartesian topology communicator (MPI_Cart_create). Read more
Source§

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

If this process was created by crate::collective::Root::spawn, return the inter-communicator to the parent group (MPI_Comm_get_parent). The local group is this world; the remote group is the spawner.

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<C> CommunicatorAttributes for C
where C: Communicator + ?Sized,

Source§

fn set_attr<T: Any + Send + Sync>(&self, key: &CommKeyval, value: T)

Cache value under key on this communicator (MPI_Comm_set_attr).
Source§

fn get_attr<T: Any + Clone>(&self, key: &CommKeyval) -> Option<T>

Retrieve a clone of the attribute cached under key (MPI_Comm_get_attr), if present and of type T.
Source§

fn has_attr(&self, key: &CommKeyval) -> bool

Whether an attribute is cached under key.
Source§

fn delete_attr(&self, key: &CommKeyval)

Remove the attribute cached under key (MPI_Comm_delete_attr).
Source§

impl<C> CommunicatorCollectives for C
where C: Communicator + ?Sized,

Source§

fn barrier(&self)

Barrier synchronization (MPI_Barrier).
Source§

fn try_barrier(&self) -> Result<(), MpiError>

Fallible barrier.
Source§

fn all_gather_into<S, R>(&self, sendbuf: &S, recvbuf: &mut R)
where S: Buffer + ?Sized, R: BufferMut + ?Sized,

Gather equal-sized contributions from all ranks to all ranks (MPI_Allgather).
Source§

fn try_all_gather_into<S, R>( &self, sendbuf: &S, recvbuf: &mut R, ) -> Result<(), MpiError>
where S: Buffer + ?Sized, R: BufferMut + ?Sized,

Fallible all_gather_into.
Source§

fn all_to_all_into<S, R>(&self, sendbuf: &S, recvbuf: &mut R)
where S: Buffer + ?Sized, R: BufferMut + ?Sized,

All-to-all scatter/gather with equal block sizes (MPI_Alltoall).
Source§

fn try_all_to_all_into<S, R>( &self, sendbuf: &S, recvbuf: &mut R, ) -> Result<(), MpiError>
where S: Buffer + ?Sized, R: BufferMut + ?Sized,

Fallible all_to_all_into.
Source§

fn all_reduce_into<S, R, O>(&self, sendbuf: &S, recvbuf: &mut R, op: O)
where S: Buffer + ?Sized, R: BufferMut + ?Sized, O: Operation,

Reduce contributions from all ranks and make the result available on all ranks (MPI_Allreduce).
Source§

fn try_all_reduce_into<S, R, O>( &self, sendbuf: &S, recvbuf: &mut R, op: O, ) -> Result<(), MpiError>
where S: Buffer + ?Sized, R: BufferMut + ?Sized, O: Operation,

Fallible all_reduce_into.
Source§

fn all_reduce_into_in_place<R, O>(&self, buf: &mut R, op: O)
where R: BufferMut + ?Sized, O: Operation,

In-place all-reduce: buf is both the input and the output (MPI_Allreduce with MPI_IN_PLACE).
Source§

fn all_gather_into_in_place<R>(&self, buf: &mut R)
where R: BufferMut + ?Sized,

In-place all-gather: buf holds this rank’s block at slot rank on entry and every rank’s block on return (MPI_Allgather with MPI_IN_PLACE).
Source§

fn reduce_scatter_block_into<S, R, O>( &self, sendbuf: &S, recvbuf: &mut R, op: O, )
where S: Buffer + ?Sized, R: BufferMut + ?Sized, O: Operation,

Reduce, then scatter equal-sized blocks of the result (MPI_Reduce_scatter_block).
Source§

fn scan_into<S, R, O>(&self, sendbuf: &S, recvbuf: &mut R, op: O)
where S: Buffer + ?Sized, R: BufferMut + ?Sized, O: Operation,

Inclusive prefix reduction (MPI_Scan).
Source§

fn try_scan_into<S, R, O>( &self, sendbuf: &S, recvbuf: &mut R, op: O, ) -> Result<(), MpiError>
where S: Buffer + ?Sized, R: BufferMut + ?Sized, O: Operation,

Fallible scan_into.
Source§

fn exclusive_scan_into<S, R, O>(&self, sendbuf: &S, recvbuf: &mut R, op: O)
where S: Buffer + ?Sized, R: BufferMut + ?Sized, O: Operation,

Exclusive prefix reduction (MPI_Exscan).
Source§

fn all_gather_varcount_into<S, R>(&self, sendbuf: &S, recvbuf: &mut R)

Varying-count all-gather (MPI_Allgatherv).
Source§

fn all_to_all_varcount_into<S, R>(&self, sendbuf: &S, recvbuf: &mut R)

Varying-count all-to-all (MPI_Alltoallv): rank i sends its j-th block to rank j, with per-peer counts and displacements on both sides.
Source§

fn immediate_barrier(&self) -> Request<'static, ()>

Non-blocking barrier (MPI_Ibarrier). Progresses on a background thread using a fresh context, so it genuinely overlaps subsequent work; wait joins it.
Source§

fn immediate_all_gather_into<'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>,

Non-blocking all-gather (MPI_Iallgather).
Source§

fn immediate_all_to_all_into<'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>,

Non-blocking all-to-all (MPI_Ialltoall).
Source§

fn immediate_all_reduce_into<'a, S, R, O, Sc>( &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: Operation + Send + 'static, Sc: Scope<'a>,

Non-blocking all-reduce (MPI_Iallreduce). Progresses on a background thread using a fresh context so it overlaps computation; wait joins it.
Source§

fn immediate_scan_into<'a, S, R, O, Sc>( &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: Operation, Sc: Scope<'a>,

Non-blocking inclusive scan (MPI_Iscan).
Source§

fn immediate_exclusive_scan_into<'a, S, R, O, Sc>( &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: Operation, Sc: Scope<'a>,

Non-blocking exclusive scan (MPI_Iexscan).
Source§

fn immediate_reduce_scatter_block_into<'a, S, R, O, Sc>( &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: Operation, Sc: Scope<'a>,

Non-blocking reduce-scatter-block (MPI_Ireduce_scatter_block).
Source§

impl<C> CommunicatorErrorHandler for C
where C: Communicator + ?Sized,

Source§

fn set_error_handler(&self, handler: ErrorHandler)

Set this communicator’s error handler (MPI_Comm_set_errhandler).
Source§

fn error_handler(&self) -> ErrorHandler

Get this communicator’s error handler (MPI_Comm_get_errhandler). Defaults to ErrorHandler::Fatal.
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.