mpi/lib.rs
1//! # mpi-rs — a pure-Rust Message Passing Interface
2//!
3//! This crate (published as **`mpi-rs`**, imported as **`mpi`**) is a
4//! from-scratch, **pure-Rust** implementation of MPI whose public API mirrors
5//! [`rsmpi`](https://github.com/rsmpi/rsmpi) (the `mpi` crate) so that existing
6//! rsmpi programs compile and run against it with little or no change. Unlike
7//! rsmpi, it does **not** link against a C MPI library (Open MPI / MPICH): the
8//! runtime — process bootstrap, the byte transport, and every collective
9//! algorithm — is implemented here in safe Rust on top of the standard library
10//! only (the default build has zero external dependencies).
11//!
12//! ## Quick start
13//!
14//! ```no_run
15//! use mpi::traits::*;
16//!
17//! let universe = mpi::initialize().unwrap();
18//! let world = universe.world();
19//! let size = world.size();
20//! let rank = world.rank();
21//!
22//! if rank == 0 {
23//! let msg = [1.0f64, 2.0, 3.0];
24//! world.process_at_rank(1).send(&msg[..]);
25//! } else if rank == 1 {
26//! let (msg, status) = world.process_at_rank(0).receive_vec::<f64>();
27//! println!("rank 1 received {:?} (status {:?})", msg, status);
28//! }
29//! ```
30//!
31//! Run it with the bundled launcher:
32//!
33//! ```text
34//! mpiexec -n 4 ./target/debug/examples/hello
35//! ```
36//!
37//! A program that is *not* launched under `mpiexec` runs as a singleton job
38//! (world size 1, rank 0), exactly like a C MPI singleton `MPI_Init`.
39
40#![deny(unsafe_op_in_unsafe_fn)]
41#![warn(missing_docs)]
42
43use std::fmt;
44
45// Internal runtime (networking + bootstrap). Not part of the public API.
46mod transport;
47
48// Optional POSIX shared-memory fast-path for same-host ranks.
49#[cfg(feature = "shm")]
50mod shm;
51
52// The process launcher, shared by the `mpiexec` / `mpirun` binaries.
53pub mod launcher;
54
55// Dynamic process management (MPI_Comm_spawn). Internal helpers.
56mod dpm;
57
58// Public API modules, mirroring rsmpi's module layout.
59pub mod attribute;
60pub mod collective;
61pub mod datatype;
62pub mod environment;
63pub mod error;
64pub mod io;
65pub mod point_to_point;
66pub mod raw;
67pub mod request;
68pub mod topology;
69pub mod traits;
70pub mod window;
71
72/// The integer type used to identify a process within a communicator
73/// (`MPI_Comm_rank`).
74pub type Rank = i32;
75
76/// The integer type used to tag point-to-point messages.
77pub type Tag = i32;
78
79/// The integer type counting elements in a buffer (`int` in the C API).
80pub type Count = i32;
81
82/// A byte displacement / absolute address (`MPI_Aint`).
83pub type Address = i64;
84
85/// Errors that can occur while managing the MPI environment.
86#[derive(Debug, Clone)]
87pub enum MpiError {
88 /// `initialize` was called more than once in the same process.
89 AlreadyInitialized,
90 /// The job could not be bootstrapped (launcher handshake failed).
91 Bootstrap(String),
92 /// A generic runtime error carrying a human-readable message.
93 Other(String),
94}
95
96impl fmt::Display for MpiError {
97 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
98 match self {
99 MpiError::AlreadyInitialized => {
100 write!(f, "MPI has already been initialized")
101 }
102 MpiError::Bootstrap(m) => write!(f, "MPI bootstrap failed: {m}"),
103 MpiError::Other(m) => write!(f, "MPI error: {m}"),
104 }
105 }
106}
107
108impl std::error::Error for MpiError {}
109
110pub use environment::{
111 initialize, initialize_with_threading, library_version, processor_name, threading_support,
112 time, time_resolution, version, Threading, Universe,
113};
114
115/// Derive macro for [`datatype::Equivalence`] (enabled by the `derive` feature).
116///
117/// ```ignore
118/// use mpi::Equivalence;
119///
120/// #[derive(Clone, Copy, Equivalence)]
121/// #[repr(C)]
122/// struct Particle { x: f64, y: f64, id: u64 }
123/// ```
124#[cfg(feature = "derive")]
125pub use mpi_derive::Equivalence;
126
127/// A convenience re-export of the wildcard constants.
128pub use transport::{ANY_SOURCE, ANY_TAG};