Running at scale (HPC)¶
Workflow
At a glance
Infomap trials are independent work units: run many in parallel on a
single node with parallel_trials, 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. It starts from a random initial state and greedily minimises the map equation, so different random seeds can find different local optima. The standard way to get a reliable partition is to run many independent trials and keep the one with the lowest codelength. On small networks, tens of trials on a laptop is enough. On real-world networks with millions of nodes and links, each trial can take minutes, and you may want hundreds of trials to trust the result.
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
parallel_trials=True.num_threadscontrols the thread budget and reads scheduler-set variables (SLURM_CPUS_PER_TASK,OMP_NUM_THREADS, cpuset) automatically when set to"auto".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 either a positive integer or the string
"auto". With "auto", 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
Using num_threads="auto" means your job script does not need to 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()is the main entry point; it acceptsnum_trials,seed,num_threads,parallel_trials,trial_offset, andtrial_resultsas engine options.result.codelengthis the codelength of the best solution found.result.modules()returns a{node_id: module_id}mapping for the top-level partition.infomap.merge.merge_trial_results()is the programmatic equivalent ofpython -m infomap.merge.Running Infomap covers the search and flow-model options (
seed,num_trials,converge,directed, …); the parallelism options used here (parallel_trials,inner_parallelization,num_threads,trial_offset) are documented on this page and in 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.