7 releases (4 breaking)
0.5.0 | Apr 30, 2024 |
---|---|
0.4.0 | Jan 18, 2024 |
0.3.0 | Jan 17, 2024 |
0.2.2 | Jan 15, 2024 |
0.1.0 | Jan 14, 2024 |
#117 in Science
426 downloads per month
97KB
2K
SLoC
Thin wrapper to a Message Passing Interface (MPI)
Contents
Introduction
MsgPass (Message Passing) is a thin Rust wrapper to MPI. We consider a small subset of MPI functions. This subset will grow as our projects require more functionality. We implement (by hand) C functions that Rust can easily call using the FFI (in the c_code
directory).
We try to test all functions as much as possible, but test coverage could be better. The tests must be called with mpiexec
, thus it is easy to use the run-tests.bash
script.
Note: We can communicate strings by converting them to an array of bytes. For instance:
let mut bytes = vec![0_u8; MAX];
str_to_bytes(&mut bytes, "Hello World 😊");
comm.broadcast_bytes(0, &mut bytes)?;
Installation
Debian/Ubuntu Linux
First, install OpenMPI, MPICH, or Intel MPI. For instance,
sudo apt install libopenmpi-dev
or
sudo apt install libmpich-dev
or
bash ./zscripts/install-intel-mpi-debian.bash
The use the corresponding feature
:
intel
: use Intel MPImpich
: use MPICH- (default): use OpenMPI
For Intel MPI, remember to call setvars.sh
first:
source /opt/intel/oneapi/setvars.sh
macOS
On macOS, install the following packages:
brew install llvm open-mpi
Also, export the following environment variable:
export echo TMPDIR=/tmp
Setting Cargo.toml
👆 Check the crate version and update your Cargo.toml accordingly:
[dependencies]
msgpass = "*"
Or, considering the optional features:
[dependencies]
msgpass = { version = "*", features = ["intel"] }
Examples
See also:
The example below (available in the examples
directory) will send an array from ROOT to all the other processors.
use msgpass::*;
fn main() -> Result<(), StrError> {
mpi_init()?;
let mut comm = Communicator::new()?;
let rank = comm.rank()?;
let size = comm.size()?;
const ROOT: i32 = 0;
const TAG: i32 = 70;
if rank == ROOT as usize {
let x = vec![1.0, 2.0, 3.0];
for to in 1..size {
comm.send_f64(&x, to, TAG)?;
}
println!("{}: x = {:?}", rank, x);
} else {
let mut y = vec![0.0, 0.0, 0.0];
comm.receive_f64(&mut y, ROOT, TAG)?;
println!("{}: y = {:?}", rank, y);
}
mpi_finalize()
}
Running the code above with mpiexec -np 4 ex_send_receive
(see run-examples.bash
), we get an output similar to the one below:
### ex_send_receive ######################################################
2: y = [1.0, 2.0, 3.0]
0: x = [1.0, 2.0, 3.0]
3: y = [1.0, 2.0, 3.0]
1: y = [1.0, 2.0, 3.0]
Roadmap
- Implement basic functionality
- Initialize and finalize
- Abort and barrier
- Wrap more MPI functions
- Implement send/receive
- Implement reduce/allreduce
- Implement scatter/gather/allgather
- Handle complex numbers
Dependencies
~205–550KB
~12K SLoC