Quantum ESPRESSO exposes several nested levels of parallelism, and choosing them well is the difference between near-linear scaling and wasting most of your cores. The defaults rarely give the best performance on more than a handful of processes. This guide explains each level — pools, band groups, task groups, and the diagonalization group — how they interact, and how to pick the flags for your system.
The Hierarchy of Parallelism
Quantum ESPRESSO distributes work across a hierarchy of MPI communicator groups. Each level splits a different part of the problem, and they nest inside one another. The total number of MPI processes is partitioned across these levels, so they multiply together rather than add.
flowchart TD A[Total MPI ranks N] --> B["Images (-nimage)"] B --> C["Pools (-npool)"] C --> D["Band groups (-nband)"] D --> E["Task groups (-ntg)"] E --> F["Linear algebra (-ndiag)"] F --> G[Plane-wave / G-vector distribution]
From outermost to innermost, the levels are:
- Images (
-nimage) — independent calculations, used by NEB and some phonon runs. - Pools (
-npool) — split the set of k-points. - Band groups (
-nband) — split the electronic bands (Kohn-Sham states). - Task groups (
-ntg) — split the FFT work to help scale plane-wave distribution. - Linear-algebra / diagonalization group (
-ndiag) — distributes the dense subspace diagonalization.
Below all of these sits the default plane-wave (PW) parallelization, which distributes G-vectors and real-space FFT planes across the processes inside a pool. Understanding how these divide your process count is the key to good scaling.
MPI vs OpenMP: Two Kinds of Parallel
Quantum ESPRESSO supports hybrid MPI + OpenMP parallelism. The distinction matters:
- MPI distributes memory: each rank owns a slice of the data and communicates via messages. This is the primary scaling mechanism and drives all the group levels above.
- OpenMP shares memory: threads inside one MPI rank cooperate on loops, notably inside FFTs and BLAS calls.
A common effective layout is one MPI rank per NUMA domain or per few cores, with OpenMP threads filling the rest of the socket. You set threads with the environment before launching:
export OMP_NUM_THREADS=4
mpirun -np 32 pw.x -npool 4 -inp scf.in > scf.out
Pure-MPI (one thread per rank) is simplest and often fastest for medium systems. Hybrid helps when pure MPI causes excessive communication or memory duplication at high core counts. Always benchmark both for your workload.
Pool Parallelization (-npool)
Pools split the k-points into independent groups that require almost no communication between them, making this the most efficient level to scale first when you have k-points to distribute.
Choosing npool by k-point Count
The rule of thumb: -npool should divide evenly into the number of k-points, and the number of processes should divide evenly by -npool. If you have 8 irreducible k-points and 32 MPI ranks, -npool 8 gives each pool 4 ranks working on one k-point.
# 32 ranks, 8 k-points: one pool per k-point
mpirun -np 32 pw.x -npool 8 -inp scf.in > scf.out
Key considerations:
- More pools = less communication, since k-points are nearly independent. This is why pools scale so well.
- Each pool must hold the full data for its k-points, so pools do not reduce per-rank memory the way G-vector distribution does. Very large systems may be memory-limited before you can use many pools.
- Gamma-point calculations have only one k-point, so
-npool 1is the only sensible choice — pool parallelism does nothing here, and you must scale via bands and PW distribution instead.
Plane-Wave and Band Parallelization
Inside each pool, the default plane-wave parallelization distributes G-vectors and FFT real-space planes across ranks. This reduces per-rank memory and is essential for large systems, but it involves communication-heavy FFTs, so it scales less perfectly than pools.
Band-group parallelization (-nband) splits the Kohn-Sham states across groups of ranks. It helps when you have many bands (large metallic systems, big supercells) and when PW parallelization alone has stopped scaling. It is particularly useful for hybrid functionals and large gamma-point runs where there are no k-points to pool.
# Gamma-point supercell: no pools, use band groups
mpirun -np 64 pw.x -npool 1 -nband 4 -inp scf.in > scf.out
Task Groups (-ntg)
Task groups reorganize the FFT so that groups of ranks handle different orbitals’ transforms together, improving FFT scaling when the number of ranks approaches or exceeds the number of FFT planes along the distributed axis. The classic symptom that you need task groups is that PW parallelization stalls because there are more ranks than real-space planes to distribute.
mpirun -np 128 pw.x -npool 2 -ntg 2 -inp scf.in > scf.out
Task groups add communication overhead, so use them only when plain G-vector distribution has saturated. On GPU builds their role is reduced, since FFTs run on-device.
The Linear-Algebra Group (-ndiag)
The dense subspace diagonalization in the Davidson eigensolver is distributed by the linear-algebra group, set with -ndiag (sometimes documented as -northo). It uses a parallel dense solver (ScaLAPACK or the built-in distributed solver) over a square grid of processors, so the argument should be a perfect square: 1, 4, 9, 16, 25, and so on.
mpirun -np 64 pw.x -npool 2 -ndiag 16 -inp scf.in > scf.out
Guidance:
-ndiagmust not exceed the ranks available within a pool.- For small subspace matrices (few bands), a large
-ndiagadds communication overhead and hurts; keep it modest. - For large systems with many bands, distributing the diagonalization becomes worthwhile.
- If the parallel solver misbehaves,
-ndiag 1forces serial diagonalization on each pool as a safe fallback.
How the Levels Divide Your Cores
The levels multiply. With \(N\) total MPI ranks, the ranks per pool are \(N / n_{\mathrm{pool}}\), and within that the diagonalization grid and PW distribution operate. A worked example with 64 ranks and 4 k-points:
mpirun -np 64 pw.x -npool 4 -ndiag 4 -inp scf.in > scf.out
Here 64 ranks split into 4 pools of 16 ranks each; within each pool, 4 ranks form the diagonalization grid and the full 16 handle PW/FFT distribution. Getting the arithmetic to divide evenly is essential — leftover ranks are wasted.
Schematically:
$$ N = n_{\mathrm{image}} \times n_{\mathrm{pool}} \times n_{\mathrm{band}} \times n_{\mathrm{PW/diag}} $$Flag Reference
| Flag | Level | Splits | Best when | Notes |
|---|---|---|---|---|
-nimage | Images | Independent calcs | NEB, grouped phonon runs | Near-embarrassingly parallel |
-npool | Pools | k-points | Many k-points | Most efficient level; scale first |
-nband | Band groups | Kohn-Sham states | Many bands, gamma-point, hybrids | Helps when PW scaling stalls |
-ntg | Task groups | FFT work | More ranks than FFT planes | Adds communication; last resort |
-ndiag | Linear algebra | Subspace diagonalization | Many bands | Must be a perfect square |
A Practical Tuning Strategy
Work from the cheapest, best-scaling level inward:
- Start with pools. Set
-npoolto divide your k-point count evenly. This buys the most scaling for the least overhead. - Add PW parallelization by giving each pool multiple ranks. Watch for the point where FFT communication stops paying off.
- Introduce band groups for large or gamma-point systems where pools cannot help.
- Tune
-ndiagonly for many-band systems; keep it small or 1 otherwise. - Reach for
-ntgonly when you have more ranks than FFT planes and PW scaling has saturated.
Reading the Scaling
At the end of every run, the timing summary breaks down time in fft, cegterg (the eigensolver), h_psi, and communication. If wall time stops dropping as you add ranks, you have hit the scaling limit for that level — communication now dominates. Back off to the core count that gave the best time-to-solution, not the largest allocation. Over-parallelizing wastes both cores and budget.
For the underlying theory and the definitive flag documentation, consult the official user guide at quantum-espresso.org, and see our computational engines page for how these levels behave on GPU-accelerated hardware.
Image Parallelization for NEB and Phonons
The outermost level, image parallelization (-nimage), splits work that is naturally independent. It is used by nudged elastic band (NEB) calculations, where each image along a reaction path is a semi-independent SCF problem, and by phonon runs (ph.x), where different q-points or irreducible representations can be computed separately.
Because the images communicate rarely, this level scales almost perfectly — close to embarrassingly parallel. If an NEB run uses 7 images and you have 224 ranks, -nimage 7 gives each image 32 ranks, and those 32 then subdivide into pools, PW distribution, and diagonalization exactly as in a normal SCF.
mpirun -np 224 neb.x -nimage 7 -inp neb.in > neb.out
The lesson generalizes: whenever your problem contains independent sub-calculations, distribute them at the outermost level first, because independence means minimal communication and the best scaling.
Diagnosing Poor Scaling
When a run scales badly, the timing report at the end of the output is your primary diagnostic. A few common patterns and their fixes:
- Communication time grows with rank count. You are over-distributing at a communication-heavy level. Reduce
-ntg, lower-ndiag, or use more pools instead of more PW ranks. - Uneven pool load. Ranks finish at different times because k-points did not divide evenly across pools. Choose
-npoolso it divides the k-point count cleanly. - Diagonalization dominates. For many-band systems, increase
-ndiagto a larger perfect square; for small systems, decrease it or set it to 1. - FFT stalls at high rank counts. You have more ranks than real-space planes. This is the signal to enable task groups or fall back to fewer, better-utilized ranks.
The overarching principle is time-to-solution, not core count. Adding processes past the scaling limit slows the run through communication overhead while consuming more of your allocation. Benchmark a short SCF at a few rank counts and pick the sweet spot before launching long production jobs.
Run it on Simatra
Simatra runs Quantum ESPRESSO on GPU-accelerated clusters using our GPU-Opt-V2 instances, delivering up to 5x faster convergence and supporting supercells up to roughly 2,000 atoms — with parallelization presets tuned so you spend less time hand-optimizing -npool and -ndiag. You get both the Quantum ESPRESSO engine and our native KRONOS engine (a C++20, GPL-3.0 DFT code with CUDA, HIP, and Metal backends), detailed on our computational engines page. Start a free trial with $100 in credits at app.simatra.io.
