SWATGenXSWATGenX
Watershed ExplorerPricing
ServicesWatershed ExplorerExample modelsCloud calibrationDocsPricing

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 went upstream as independent pull requests: #220 was merged on 2026-08-20 and #219 was closed without merging; both ship in the SWATGenX production engine.

Where the CPU goes — stock vs two fixesVTune · 94k HRUs
0s20s40s60s80sString name-matchingoverhead75s → 7sArray zeroingoverhead28s → 2sStartup / input readoverhead21s → 0sHRU hydrologyreal work25sChannel routingreal work17sObject/command loopoverhead8s
stock baseline+ two fixes3-month run: 462s → 292s (1.58×)
  • Top cost: name-matching 75s, not hydrology
  • 462s → 292s (1.58×) on our server
  • Byte-identical results
  • Upstream: #220 merged, #219 closed

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 went upstream as independent pull requests (upstream merged #220 on 2026-08-20 and closed #219 without merging), and both 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

Build a model of your watershed
SWAT+ parallel engine (multi-core OpenMP)
Hydrology calibration methods

Last updated 2026-07-13.