Hataori

Hataori (機織り, “weaving on a loom”) is a Rust engine for simple serial, Rayon, MPI, and hybrid data-parallel execution. It is inspired by Distributed.jl’s dynamically scheduled pmap while keeping Rust’s scoped execution and MPI’s SPMD model: every entry point is a synchronous function call, results always come back in input order, and the first callback error is reported with its input index.

The crate has no default dependencies. You choose an execution model by enabling Cargo features and calling the matching function:

Model Feature(s) Entry point What runs where
Serial none hataori::map one thread, one process
Rayon rayon hataori::map_in a rank-local thread pool (Domain)
MPI mpi or rsmpi-rt hataori::pmap one sequential worker per MPI rank
Hybrid mpi/rsmpi-rt + rayon hataori::pmap a Rayon pool on every MPI rank

The MPI backends also provide broadcast, scatter, and gather placement collectives for owned values.

Where to start

Workflow Start with
Install the crate and pick features Getting Started
Understand the four execution models and LocalMode Parallel Execution Models
See every model as runnable code Tutorials
Link-time vs runtime-loaded MPI Choosing Features and Backends
Function-level documentation API Reference
Why the engine is shaped this way P0 design, P1 bounded prefetch
Feed the whole site to a coding agent llms.txt — conventions plus every page with a one-line description

Thirty-second example

Serial execution needs no features and no trait bounds beyond Display on the error type. Every tutorial renders the same Mandelbrot image, one column per item; this is the serial version:

/// Render every column in input order on the calling thread.
///
/// `map` takes a `Vec<T>` and a fallible callback and returns a `Vec<U>` in
/// the same order, or the first error together with the failing index. The
/// callback borrows `param`, `x`, and `y` from the caller's stack.
fn render(param: &Param) -> Result<Vec<Vec<i64>>, MapError> {
    let (x, y) = param.make_axes();
    let columns: Vec<usize> = (0..param.width).collect();
    map(columns, |col_idx| {
        Ok::<_, String>(mandelbrot_common::compute_column(param, x[col_idx], &y))
    })
}

Every other model keeps the same shape — a Vec<T> in, a Result<Vec<U>, _> out, in input order — and adds only the coordination that the model needs: a Domain for Rayon, an MPI communicator plus PmapOptions for MPI and hybrid runs.

All tutorial snippets are quoted from examples/ and are compiled and run by scripts/check-tutorial-examples.sh; see Tutorials.