#[cfg(target_arch = "wasm32")]
use jsmpi as mpi;
#[cfg(not(target_arch = "wasm32"))]
use mpi::traits::*;
#[cfg(target_arch = "wasm32")]
use std::time::Duration;
#[cfg(target_arch = "wasm32")]
use wasm_bindgen::prelude::*;
#[cfg(target_arch = "wasm32")]
use wasm_bindgen_futures::spawn_local;
#[cfg(not(target_arch = "wasm32"))]
fn run() {
let universe = mpi::initialize().expect("failed to initialize MPI runtime");
let world = universe.world();
let rank = world.rank();
let size = world.size();
assert!(size >= 2, "ping_pong requires at least 2 ranks");
if rank == 0 {
log::info!("[ping_pong] starting demo, requires rank 0 and rank 1");
}
if rank == 0 {
let payload = 42_i32;
log::info!("[ping_pong] rank 0 sending payload={payload} to rank 1");
world.process_at_rank(1).send(&payload);
let (reply, _status) = world.process_at_rank(1).receive::<i32>();
log::info!("[ping_pong] rank 0 received reply={reply} from rank 1");
} else if rank == 1 {
log::info!("[ping_pong] rank 1 waiting payload from rank 0");
let (value, _status) = world.any_process().receive::<i32>();
let reply = value + 1;
log::info!("[ping_pong] rank 1 got payload={value}, sending reply={reply}");
world.process_at_rank(0).send(&reply);
}
log::info!("[ping_pong] rank {rank} entering barrier");
world.barrier();
log::info!("[ping_pong] rank {rank} left barrier");
}
#[cfg(target_arch = "wasm32")]
async fn run_async() {
let runtime = mpi::runtime::Runtime::detect().expect("failed to initialize MPI runtime");
let rank = runtime.rank();
let size = runtime.size();
assert!(size >= 2, "ping_pong requires at least 2 ranks");
if rank == 0 {
log::info!("[ping_pong] starting demo, requires rank 0 and rank 1");
let payload = 42_i32;
log::info!("[ping_pong] rank 0 sending payload={payload} to rank 1");
runtime
.send(rank, 1, 0, &payload)
.expect("rank 0 send failed");
let (reply, _status) = runtime
.receive_with_timeout_async::<i32>(Some(1), Some(0), Duration::from_secs(15))
.await
.expect("timed out waiting for rank 1 reply");
log::info!("[ping_pong] rank 0 received reply={reply} from rank 1");
} else if rank == 1 {
log::info!("[ping_pong] rank 1 waiting payload from rank 0");
let (value, _status) = runtime
.receive_with_timeout_async::<i32>(Some(0), Some(0), Duration::from_secs(15))
.await
.expect("timed out waiting for rank 0 payload");
let reply = value + 1;
log::info!("[ping_pong] rank 1 got payload={value}, sending reply={reply}");
runtime
.send(rank, 0, 0, &reply)
.expect("rank 1 send failed");
}
log::info!("[ping_pong] rank {rank} entering barrier");
runtime.barrier_async().await.expect("barrier failed");
log::info!("[ping_pong] rank {rank} left barrier");
}
fn main() {
#[cfg(not(target_arch = "wasm32"))]
env_logger::init();
#[cfg(not(target_arch = "wasm32"))]
run();
}
#[cfg(target_arch = "wasm32")]
#[wasm_bindgen]
pub fn jsmpi_main() {
let _ = console_log::init();
spawn_local(async {
run_async().await;
mpi::runtime::mark_finished().expect("failed to mark worker as finished");
});
}