SWAT+ performance research
SWAT+ performance profiling: two upstream fixes, before and after
We profiled the stock SWAT+ engine on a 94,303-HRU basin with Intel VTune: the two largest CPU costs are not hydrology but string name-matching and array zeroing — two small, results-identical fixes remove them and cut a 3-month run 1.58×.
Commit-pinned binaries that differ by nothing but the two fixes. Both are proposed upstream as independent pull requests (#219, #220); both already ship in the SWATGenX production engine.
- Top cost: name-matching 75s, not hydrology
- 462s → 292s (1.58×) on our server
- Byte-identical results
- Upstream PRs #219 + #220 (proposed)
Inside a single SWAT+ simulation, where does the CPU actually go? We profiled the stock distribution (swat-model/swatplus 5ccf6f0) on Peace River HUC-8 — 94,303 HRUs — with Intel VTune, and the answer is not what runtime advice usually assumes.
The two biggest costs are overhead, not science: string name-matching in the input reader and array zeroing in the daily reset. We trace each to a specific source pattern, fix it, and show the before/after on commit-pinned binaries that differ by nothing but the two fixes. Both are proposed upstream as independent pull requests, and both already ship in the SWATGenX production engine.
These two fixes are serial-CPU wins — they change no results and need no threads. On the engine-acceleration study’s full-year AWS benchmarks the same overhead-removal work, combined with the rest of the serial ladder, makes the shipped engine’s one-thread run 1.26× faster than our original engine on the c8a reference node, after paying 1.23–1.24× for being compiled with OpenMP, so the ladder is a claim about the engineering rather than about a one-core run. On top of it, an opt-in multi-core wavefront scales a single run further. This page isolates the two fixes on our server; the full serial ladder and multi-core scaling are on the SWAT+ parallel-engine page.
FAQ
Where does stock SWAT+ spend its CPU on a large basin?
On a 94,303-HRU model profiled with Intel VTune, the three biggest CPU costs are overhead, not science: string name-matching in the input reader (~75 s), array zeroing in the daily reset (~28 s), and startup input handling (~21 s) — together larger than the HRU hydrology (~25 s) and channel routing (~17 s) that do the actual work.
What are the two fixes?
One replaces an O(N_HRU x N_database) linear name scan in hru_read with an O(1) name-to-index hash (upstream PR #219). The other zeros only the active HRU’s working row in the daily reset instead of the whole all-HRU array (upstream PR #220). Each is a small, self-contained change with no dependency on any other feature.
Do the fixes change model results?
No. Results are numerically identical — the data rows are bit-for-bit the same. NetCDF output is byte-identical; text output differs only in the SWAT+ revision string embedded in the file header, which reflects the build commit.
How much faster, and on what?
On a 3-month Peace River run (94,303 HRUs), wall time dropped from 462 s to 292 s (1.58x, 37%) with identical output. By VTune the overhead collapsed: name-matching 75 s to 7 s, array zeroing 28 s to 2 s, startup 21 s to 0.2 s; the hydrology and routing functions were unchanged.
Next steps
Last updated 2026-07-13.
