MPI ingest and export#

Build with --features mpi against one MPI implementation (MPICC=mpicc.mpich or mpicc.openmpi). The library never calls MPI_Init and only uses the communicator you pass.

Ingest#

let counts = readcon_db::mpi_ingest::append_trajectory_paths(&world, "corpus", &files, 4096)?;
let counts = readcon_db::mpi_ingest::append_trajectory_paths_sharded(&world, "root", 64, &files, 4096)?;

The frames of all files, in order, are split into contiguous blocks. Each rank parses, hashes and derives index keys for its block. Ranks exchange only the 16-byte hashes first, so a repeated frame sends no blob. Records go to the env owner with MPI_Alltoallv (rank 0 for one corpus, rank shard % P for shards), which inserts them in global frame order.

From C, C++ or Fortran use rkrdb_mpi_ingest_paths (an MPI_Comm) or rkrdb_mpi_ingest_paths_f (an MPI_Fint) from readcon-db-mpi.h.

Read and export#

mpi_read::scatter_packed_frames sends each rank its block of a selection as one RCSO batch. mpi_read::export_extxyz_collective writes extended XYZ from every rank with MPI_File_write_at_all, or through rank 0 with WriteMode::Gather.

LMDB map size#

Each writer rank grows its LMDB map to three times the CON bytes routed to it before the first batch, so large ingests do not stop with MDB_MAP_FULL. A serial write that hits MDB_MAP_FULL aborts that transaction, grows the map to the larger of twice its size and the bytes already used plus the input, and retries. Serial callers can set READCON_DB_MAP_SIZE (for example 8G) or call ConCorpus::open_with_map_size and ConCorpus::reserve_map. The default is 2 GiB, and reopening an existing corpus always maps at least twice its data.mdb. The map is address space, so a large value costs no disk until pages are written.

Determinism#

LMDB page layout can differ between equal corpora, so the check is ConCorpus::canonical_dump (every table in key order). Its sha256 after an MPI ingest equals the serial ingest of the same files in the same order, for every rank count. Exported XYZ bytes equal the serial export.

Benchmark#

bench/mpi_bench.sh FRAMES ATOMS "1 2 4 8" writes a synthetic trajectory with bench/gen_con.py and prints the ingest wall time and the sha256 match for every rank count and mode.