Parallelize + hoist invariants in QuadSurface resample/rotate warps (bit-identical)#1080
Open
robert-kofler42 wants to merge 1 commit into
Open
Conversation
The two linear point-warp helpers were fully serial and recomputed loop-invariant work per pixel. Both are now parallelized over output rows and have their invariants hoisted, with bit-identical output: - resamplePointsLinearPreservingInvalids: the source-x sample (x0/x1/fx) depends only on dstX, so precompute it once per column instead of per pixel (same technique as the gen() warp helpers), then run the row loop under OpenMP. - warpAffinePointsLinearPreservingInvalids (rotate path): the affine is not x-separable, so only lift the six dstToSrc.at<double>() coefficients into locals (the compiler reloaded them every pixel because it can't prove the Mat doesn't alias the store) and parallelize the row loop. The explicit m*dstX + m*dstY + m form is kept to preserve float rounding. No numeric change: output is bit-for-bit identical to the serial code (verified with an FNV-1a checksum over all output floats across a sweep of resample factors and rotation angles, identical before/after; existing quadsurface/render tests pass). End-to-end timing of resample()/rotate() on a 1500x1500 surface (8 threads, includes the fixed surface-rebuild overhead, so the warp-only speedup is larger): resample 38.8 -> 31.6 ms (-19%), rotate 95.6 -> 63.8 ms (-33%).
|
Someone is attempting to deploy a commit to the scroll Team on Vercel. A member of the Team first needs to authorize it. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
The two linear point-warp helpers in
QuadSurface.cppwere fully serial and recomputed loop-invariant work per pixel. Both are now parallelized over output rows with their invariants hoisted, bit-identically:resamplePointsLinearPreservingInvalids— the source-x sample (x0/x1/fx) depends only ondstX, so precompute it once per column instead of per pixel (same separable-axis technique as thegen()warp helpers in Speed up QuadSurface::gen() warps by hoisting the separable x axis #1076), then run the row loop under OpenMP.warpAffinePointsLinearPreservingInvalids(rotate path) — the affine is not x-separable (srcXdepends on bothdstXanddstY), so only the sixdstToSrc.at<double>()coefficients are lifted into locals (the compiler reloaded them every pixel because it can't prove thecv::Matdoesn't alias the store) and the row loop is parallelized. The explicitm*dstX + m*dstY + mform is kept to preserve float rounding.Correctness — bit-identical
Same float ops in the same order, only memoized / CSE'd; rows are independent so OpenMP doesn't reorder any accumulation. Verified with an FNV-1a checksum over all output floats across a sweep of resample factors {0.5, 0.37, 2.0} and rotation angles {30, 90, 12.5, −47}° — identical before/after (
9b62b8c86523bfb0). Existing quadsurface/render tests (10) pass.Performance
End-to-end timing of
resample()/rotate()on a 1500×1500 surface (8 threads,RelWithDebInfo). These include the fixed surface-rebuild/clone overhead, so the warp-only speedup is larger:resample()rotate()These are user-triggered (resample/rotate/ABF-regrid), off the per-frame
gen()hot path, so the absolute wins are modest — but free given they're bit-identical. Independent of #1075/#1076; applies cleanly onmain.