jsmpi 0.1.0

A browser-oriented MPI compatibility layer for Rust/WASM using Web Workers
Documentation
#[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(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();

    let local = rank + 1;

    if rank == 0 {
        let mut total = local;
        for src in 1..size {
            let (value, _status) = world.process_at_rank(src).receive::<i32>();
            total += value;
        }

        for dst in 1..size {
            world.process_at_rank(dst).send(&total);
        }

        log::info!("[sum_reduction] global sum={total} over {size} ranks");
    } else {
        world.process_at_rank(0).send(&local);
        let (total, _status) = world.process_at_rank(0).receive::<i32>();
        log::info!("[sum_reduction] rank {rank} local={local}, global={total}");
    }

    world.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();

    let local = rank + 1;
    let send_tag = 31;
    let recv_tag = 32;

    if rank == 0 {
        let mut total = local;
        for src in 1..size {
            let (value, _status) = runtime
                .receive_with_timeout_async::<i32>(Some(src), Some(send_tag), Duration::from_secs(15))
                .await
                .expect("sum_reduction receive failed");
            total += value;
        }

        for dst in 1..size {
            runtime
                .send(rank, dst, recv_tag, &total)
                .expect("sum_reduction send failed");
        }

        log::info!("[sum_reduction] global sum={total} over {size} ranks");
    } else {
        runtime
            .send(rank, 0, send_tag, &local)
            .expect("sum_reduction send failed");
        let (total, _status) = runtime
            .receive_with_timeout_async::<i32>(Some(0), Some(recv_tag), Duration::from_secs(15))
            .await
            .expect("sum_reduction receive failed");
        log::info!("[sum_reduction] rank {rank} local={local}, global={total}");
    }

    runtime.barrier_async().await.expect("barrier failed");
}

fn main() {
    #[cfg(not(target_arch = "wasm32"))]
    {
        env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("info")).init();
        run();
    }
}

#[cfg(target_arch = "wasm32")]
#[wasm_bindgen]
pub async fn jsmpi_main() {
    console_error_panic_hook::set_once();
    let _ = console_log::init_with_level(log::Level::Info);
    run_async().await;
    let _ = mpi::runtime::mark_finished();
}