Skip to content
Pedro Braiti
← All projects

Quantitative research

pgsr-fast

Thirteen targeted patches that make surface reconstruction training faster without changing a comma of the final result.

Dot chart: 1.115 it/s on stock PGSR against 1.222 it/s on pgsr-fast, two runs per side, axis cropped at 1.07
Measured

≈10%

more iterations per second in the training loop — +9.5% measured, with identical geometry

Conditions
+9.5% across two runs per side, interleaved on the same RTX 4090 · real scene of 469 photos at 12 MP · loss at parity within the measurement noise
Role
Author, open source contribution
Context
Optimization on top of an academic 3D reconstruction project
Period
2026
Status
Public, with a reproducible benchmark

The problem

Surface reconstruction with Gaussian Splatting is expensive: hours of GPU time per scene. Looking at PGSR’s training loop, you could see wasted work — data going back and forth between GPU and CPU on every iteration, synchronizations stalling the queue for nothing.

Speeding that up is easy. Speeding it up without changing the result is the actual work.

The decision that changed the project

A speed gain in model training is easy to fake. You cut a synchronization, the number drops, and the geometry degrades in a way that only shows up three scenes later.

So the rule was: every patch has to prove it didn’t change the math. There are thirteen numbered patches, each anchored to an exact passage of the original source code, each idempotent, and each with a numerical equivalence proof run on CPU — where the result is deterministic and comparable bit for bit.

For the benchmark, I measured with interleaved A/B instead of running one side all the way through and then the other: that way a thermal swing on the GPU in the middle of the test doesn’t turn into a “performance gain”.

The result

+9.5% iterations per second in the training loop, with loss at parity within the measurement noise — validated afterwards on a full 23,000-iteration training run, not just a short segment.

And that has a price attached. On the clock, the benchmark measures 1.090× — the same 23,000 iterations finish in about 8.3% less time. (The loop rate gives 1.095×; wall time trails it slightly because it includes the one-off checkpoint load and save, which the patches never touch.) Rented GPU is billed by the hour, and the hour you don’t run is the hour you don’t pay for — the gain never shows up on screen and always shows up on the bill.

Along the way, two defects in the original project turned up: an operator precedence error in the moving-average logging, and a crash. Both fixed.