Running at scale (HPC)¶
Workflow
At a glance
Infomap trials are independent work units: run many in parallel on a
single node with options=Options(parallel_trials=True), or split them across a
scheduler job array with trial_offset and merge the best result afterwards with
python -m infomap.merge.
When one node isn’t enough¶
Infomap is a stochastic optimiser, so more independent trials give a more reliable partition (see Running Infomap for why). That is cheap on small networks — tens of trials on a laptop — but on real-world networks with millions of nodes and links each trial can take minutes, and the hundreds of trials you may want are more than one node can finish in reasonable wall-clock time.
Two strategies cover most HPC use cases:
Single-node parallelism. Your scheduler gives you a node with many cores. Run all trials on that node with
options=Options(parallel_trials=True).num_threads(also carried onOptions) controls the thread budget; left unset (its default, the same as"auto") it reads scheduler-set variables (SLURM_CPUS_PER_TASK,OMP_NUM_THREADS, cpuset) automatically.Job-array sharding. Your network is large, or you want more trials than one node can finish in time. Divide the total trial budget across array tasks with
trial_offset. Each task runs its slice of trials and writes a shard result file (trial_results). A lightweight post-processing step merges the shards and picks the global best without rerunning Infomap.
Both strategies produce the same result as a sequential run with the same seed, total trial count, and algorithm settings.
Trials as independent work units¶
Each task runs num_trials trials of its own (the per-shard count), and
trial_offset positions those trials within the global budget. If you want
100 trials in total and split them across four array tasks, each task gets
num_trials=25:
task 0: trials 0–24, offset 0
task 1: trials 25–49, offset 25
task 2: trials 50–74, offset 50
task 3: trials 75–99, offset 75
Each task uses seed base_seed + (offset + i) for its i-th local
trial. The ranges never overlap, so no two tasks duplicate work. After all
tasks finish, infomap.merge reads the four result JSON files, checks
that they came from the same network and algorithm configuration, and
writes the tree from the lowest-codelength trial.
The merge is an offline post-processing step. It reads JSON, copies one tree file, and exits. It does not need the network, does not rerun Infomap, and takes negligible time compared with the runs themselves.
Threading and scheduler awareness¶
The num_threads option accepts a positive integer or the string "auto", and
defaults to "auto" when left unset. In "auto" mode Infomap resolves the
thread budget from the first source that provides a value in this priority order:
--num-threads/num_threadsexplicit integerEnvironment variable
INFOMAP_NUM_THREADSSLURM_CPUS_PER_TASK(set automatically by SLURM when you use--cpus-per-task)OMP_NUM_THREADSThe process cpuset (cgroup limit)
Hardware thread count
Because "auto" is the default, your job script does not need to set
num_threads or forward scheduler environment variables manually: if the
scheduler sets SLURM_CPUS_PER_TASK=8, Infomap will use 8 threads. This prevents
the common mistake of allocating 8 cores but Infomap running with 64 threads
and fighting every other job on the node.
parallel_trials=True runs independent trials concurrently using OpenMP.
The number of concurrent workers is clamped to min(num_trials, OpenMP thread count), which num_threads sets. Peak memory scales with the worker
count, so check your memory allocation if you raise thread counts significantly. (The
benchmark-performance
notebook has run-time and memory scaling curves to help plan allocations.)
inner_parallelization=True is an experimental alternative that
parallelises the node-move loop inside a single trial. It can improve
wall-clock time on very large graphs but may produce a slightly different
partition. If you set both, parallel_trials takes precedence and inner
parallelisation is disabled inside the trial workers.
Using infomap.merge¶
After all shard jobs finish, merge their result files into a final
tree/clu pair. You can do this from the shell:
python -m infomap.merge results_*.json \
--out-name final \
--output tree,clu \
--require-complete-trials
Or programmatically from Python:
from infomap.merge import merge_trial_results
summary = merge_trial_results(
["results_*.json"],
out_name="final",
formats=("tree", "clu"),
require_complete=True,
)
print("winner trial:", summary["trial"])
print("codelength: ", summary["codelength"])
print("outputs: ", summary["outputs"])
merge_trial_results verifies that all shard files share the same
network and configuration fingerprint (so you cannot accidentally mix
results from different runs), selects the trial with the lowest
codelength, and writes the corresponding tree. Ties are broken by the
lowest global trial index to make the result independent of how you
partitioned the trials across shards.
--require-complete-trials / require_complete=True causes the merge to
fail if any global trial index in [0, max] is missing. Use this when
reproducibility matters; leave it off if one shard failed and you are
happy with the subset that completed.
SLURM array-job recipe¶
The following SLURM batch script distributes 100 trials across four array tasks (25 per task). Each task writes a shard result JSON. A small post-processing step merges the shards.
#!/usr/bin/env bash
#SBATCH --job-name=infomap-shards
#SBATCH --array=0-3
#SBATCH --cpus-per-task=8
#SBATCH --mem=32G
#SBATCH --time=02:00:00
#SBATCH --output=logs/infomap_%A_%a.out
#SBATCH --error=logs/infomap_%A_%a.err
set -euo pipefail
INFOMAP=/path/to/Infomap # native binary, built with OpenMP
NETWORK=/path/to/graph.net
OUT=/path/to/out
TRIALS_PER_SHARD=25
OFFSET=$((SLURM_ARRAY_TASK_ID * TRIALS_PER_SHARD))
mkdir -p "$OUT/shards/$SLURM_ARRAY_TASK_ID"
srun "$INFOMAP" "$NETWORK" "$OUT/shards/$SLURM_ARRAY_TASK_ID" \
--num-trials "$TRIALS_PER_SHARD" \
--trial-offset "$OFFSET" \
--seed 123 \
--num-threads auto \
--parallel-trials \
--trial-results "$OUT/results_${SLURM_ARRAY_TASK_ID}.json" \
--no-final-output \
--silent
Key points about this script:
--num-threads autopicks upSLURM_CPUS_PER_TASK, so the Infomap process uses exactly the cores the scheduler allocated.--parallel-trialsruns the 25 per-shard trials concurrently across those cores.--trial-resultswrites the shard JSON along with a per-shard best-result tree;--no-final-outputskips the aggregate default output (the merge produces the final result).All shards use the same
--seed 123. Trialiin shardkuses seed123 + offset_k + i, which guarantees globally unique seeds.
After the array completes, submit a short post-processing job:
python -m infomap.merge "$OUT"/results_*.json \
--out-name "$OUT/final" \
--output tree,clu \
--require-complete-trials
Monitor the array while it runs:
squeue -j <job-id>
tail -f logs/infomap_<job-id>_<task-id>.out
sacct -j <job-id> --format=JobID,State,ExitCode,Elapsed,MaxRSS
Before you scale: a checklist¶
Use
--num-threads autoso the process respects scheduler core allocation without manual forwarding of environment variables.Use the same
--seed, network file, and algorithm flags for all shards. Shard files with different network or config fingerprints will be rejected by the merge.Make
--num-trialsthe per-shard count. Choose non-overlapping--trial-offsetranges.Run a short reference job (a single shard without
--no-final-output) to confirm your build, options, and file paths work before submitting a large array.Check exit codes in your batch script (
set -euo pipefail). A failed Infomap run that exits 0 would produce a missing shard file and silently pollute the merge result.infomap.mergecan write onlytreeandcluoutput; link-bearing formats (ftree) require a full Infomap run with the original network.Use
--require-complete-trialswhen reproducibility matters; the merge warns about gaps without it.
API pointers¶
infomap.run() takes num_trials and seed directly; the parallelism
options num_threads, parallel_trials, trial_offset, and trial_results are
carried via Options (they leave the bare signature in 3.0, see
Deprecation policy). infomap.merge.merge_trial_results() is the
programmatic equivalent of python -m infomap.merge. Read run metrics
(codelength, modules(), …) off the
Result — see
Reading the result; the search and flow-model
options are in Running Infomap and the
Options reference.
Going deeper¶
Companion notebook
examples/notebooks/run-infomap-on-hpc.ipynbis a complete end-to-end HPC walkthrough using the native binary, with distributed trial verification and SLURM monitoring commands.Performance planning:
examples/notebooks/benchmark-performance.ipynbhas empirical run-time and memory scaling curves to help you choose trial counts, thread budgets, and memory allocations before submitting large jobs.Running Infomap is the options guide for the search and flow-model settings that shape each trial before you scale it out.