Update
This commit is contained in:
1 parent
589d22aa5e
commit
7a5c77c1c8
31 files changed
+1196
-44
No files matched your search
@@ -0,0 +1,109 @@
|
||||
# Solver optimization audit
|
||||
|
||||
Measured on an Intel Core i5-12600K, Linux, GCC 16.2.1, Release (`-O3`,
|
||||
no fast-math). Reference is commit `589d22a`. Performance results are specific
|
||||
to this machine; Windows/MSVC runtime measurements remain pending. The retained
|
||||
changes use portable C++ and compiler vectorization, with no new CPU requirement.
|
||||
|
||||
## Retained changes
|
||||
|
||||
* Boundary solves start from the previous converged face pressure when it is
|
||||
inside the new physical bracket. Otherwise they start at the bracket midpoint.
|
||||
The safeguarded Newton solver, residual tolerance, iteration cap, choking,
|
||||
reverse flow, donor budgets and inertance calculation remain unchanged.
|
||||
* Pipe preparation computes primitive states and wave speeds in an independent
|
||||
loop, then validates states and reduces the CFL timestep. GCC confirms 128-bit
|
||||
vectorization of the arithmetic loop. Invalid states still throw before flux
|
||||
updates. No approximate reciprocal/square root or relaxed arithmetic is used.
|
||||
* Pipe fresh-air tracer fractions smaller than the smallest **normal** float
|
||||
(approximately 1.175e-38) are rounded to zero. Previously, purged intake/exhaust
|
||||
tracer tails persisted as subnormals, causing severe sustained-load slowdown.
|
||||
This affects species attribution below that precision, not total density,
|
||||
momentum or energy. The regression suite checks bulk conservation and retention
|
||||
of normal tracer concentrations. Global flush-to-zero modes are not enabled.
|
||||
|
||||
Starting guesses change numerical trajectories within the existing convergence
|
||||
tolerance; long engine/audio traces need not be bit-identical to the reference.
|
||||
|
||||
## Profiling and experiments
|
||||
|
||||
A `-pg` build running every scenario for two simulated seconds attributed about
|
||||
39% of sampled executable time to pipe advancement, 38% to orifice boundary
|
||||
solves, and 13% to Solver::step (including inlined preparation). Turbo mechanics
|
||||
were under 1% and outdoor emitter rendering about 1%. These are sampled gprof
|
||||
results, not precise attribution of time inside dynamically linked math functions.
|
||||
|
||||
`fluidsim_thread_benchmark` now uses each scenario's actual pipe geometry and
|
||||
compares persistent 1/2/4-worker execution with barriers per substep. This isolates
|
||||
the parallelizable pipe work; boundary/component work would remain serial. Every
|
||||
current scenario loses with workers, so production remains serial. The synthetic
|
||||
64-pipe, 256-cells-per-pipe case benefits from workers, confirming that this
|
||||
strategy has a useful scale threshold. It does not justify adding its scheduling
|
||||
and synchronization cost to the current small graphs.
|
||||
|
||||
SIMD-disabled and `-march=native` builds are comparison experiments. Native
|
||||
compilation is not enabled in the project defaults, since the executable could
|
||||
then require instructions missing on another machine.
|
||||
|
||||
## Results
|
||||
|
||||
Mean wall seconds per simulated second, six-second sustained-load runs:
|
||||
|
||||
| Scenario | Reference | Optimized | Time reduction | SIMD disabled |
|
||||
|---|---:|---:|---:|---:|
|
||||
| Twin | .528 | .405 | 23% | .423 |
|
||||
| Turbo twin | 1.368 | .649 | 53% | .684 |
|
||||
| B205 | .884 | .689 | 22% | .737 |
|
||||
| Two-stroke racing | .561 | .470 | 16% | .535 |
|
||||
| Two-stroke straight | .539 | .464 | 14% | .525 |
|
||||
| Helmholtz | .167 | .141 | 16% | .160 |
|
||||
| Pulse | .256 | .238 | 7% | .315 |
|
||||
|
||||
Idle/transient optimized means (seconds per simulated second): twin .394/.399,
|
||||
turbo .627/.651, B205 .666/.683, racing two-stroke .450/.459, straight two-stroke
|
||||
.452/.453, Helmholtz .141/.140, and pulse .238/.238.
|
||||
|
||||
The pulse scenario has no orifice, so its improvement isolates the SIMD-friendly
|
||||
preparation change. Disabling SIMD increases time in every scenario. An optional
|
||||
native-instruction build improves some timings further, but is not shipped as
|
||||
the default: FMA also changes rounding and the binary is CPU-specific.
|
||||
|
||||
Initial isolated changes measured approximately .40 seconds for the twin after
|
||||
boundary warm starts alone (previously .53). The sustained turbo still took
|
||||
about 1.2 seconds after that change; eliminating subnormal tracer tails brought
|
||||
it to about .65. The diagnostic found 22 subnormal pipe fields before truncation
|
||||
and zero afterwards. This is distinct from reducing CFL substeps or geometry;
|
||||
neither was changed. Six-second idle and throttle/release runs also complete
|
||||
for every scenario. These are finite test windows, not a guarantee of real-time
|
||||
performance for every user configuration or arbitrarily long simulation.
|
||||
|
||||
## Reproduction
|
||||
|
||||
Final validation: all nine CTest suites passed both with SIMD enabled (28.50 s)
|
||||
and disabled (30.86 s). The fluid validation executable includes 30 checks,
|
||||
including tracer underflow conservation. The Release SFML desktop target also
|
||||
rebuilt successfully. This audit verifies desktop compilation and headless audio
|
||||
rendering; interactive playback underrun testing remains a separate user check.
|
||||
|
||||
```sh
|
||||
cmake -S . -B build-opt -DCMAKE_BUILD_TYPE=Release -DFLUIDSIM_BUILD_DESKTOP=OFF
|
||||
cmake --build build-opt -j
|
||||
ctest --test-dir build-opt --output-on-failure
|
||||
./build-opt/fluidsim_scenario_benchmark 6 loaded
|
||||
./build-opt/fluidsim_scenario_benchmark 6 idle
|
||||
./build-opt/fluidsim_scenario_benchmark 6 transient
|
||||
./build-opt/fluidsim_thread_benchmark
|
||||
```
|
||||
|
||||
The scenario benchmark runs twin, turbo twin, B205, racing and straight-pipe
|
||||
two-strokes, Helmholtz and pulse scenarios, including their normal audio path.
|
||||
`loaded` holds four-strokes at 7,000 RPM and two-strokes at 10,000 RPM using an
|
||||
ideal speed-holding dyno; engine throttle is 70%. `idle` releases the pedal;
|
||||
`transient` starts released, applies 70%, then releases for the last two seconds.
|
||||
The optional final argument selects one scenario, e.g. `6 loaded turbo`.
|
||||
CSV timing/checksum goes to stdout; subnormal and iteration diagnostics go to
|
||||
stderr. Inspection happens outside the timed sample-processing loop.
|
||||
|
||||
Use `-DFLUIDSIM_ENABLE_SIMD=OFF` in a separate build for scalar comparisons.
|
||||
Run timed experiments sequentially, without concurrent builds or simulations.
|
||||
The raw final measurements are retained in `verification/optimization/`.
|
||||
Reference in new issue
Block a user