Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Speed-up +proj=cart +inv #4087

Merged
merged 4 commits into from
Mar 24, 2024
Merged

Speed-up +proj=cart +inv #4087

merged 4 commits into from
Mar 24, 2024

Conversation

rouault
Copy link
Member

@rouault rouault commented Mar 14, 2024

Alternative implementation to #4067

@rouault
Copy link
Member Author

rouault commented Mar 14, 2024

@wblangdon Assuming this PR pass the tests, can you give it a try on your side to measure the performance?

@rouault rouault force-pushed the faster_geodetic branch 4 times, most recently from 4d72380 to 923f6f8 Compare March 14, 2024 19:16
@rouault
Copy link
Member Author

rouault commented Mar 14, 2024

On my system, with a RelWithDebInfo build (-O2), hyperfine --warmup 5 './bin/bench_proj_trans -p "+proj=pipeline +step +inv +proj=cart" 4189946.586317880544811 146316.158923541981494 4790634.218430089764297' runs in 441 ms, vs 497 ms with master, so a 13% improvement

@rouault rouault mentioned this pull request Mar 14, 2024
@wblangdon
Copy link

wblangdon commented Mar 14, 2024

Passes (64 bit) tests here. Speed up on geodetic 37% (GCC 10.2.1 -O3, i7-4790 CPU @ 3.60GHz)

#else
return a *
sqrt(cosphi * cosphi +
(b_div_a * b_div_a) * (b_div_a * b_div_a) * (sinphi * sinphi)) /
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Those parenthesis are not needed. Are for readability or helping the compiler?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That might help the compiler. Otherwise if we do "a * a * a * a", I suspect he's supposed to evaluate it as "((a * a) * a) * a" given the left-to-right evaluation order mandated by C/C++. Grouping by pair will save one multiplication (since the optimizer should be smart enough to evaluate once b_div_a * b_div_a

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

actually I've just added a commit to further optimize things

@@ -112,7 +112,7 @@ static double normal_radius_of_curvature(double a, double es, double sinphi) {
}

/*********************************************************************/
static double geocentric_radius(double a, double b, double cosphi,
static double geocentric_radius(double a, double b_div_a, double cosphi,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice trick using b/a, that is always <1, to avoid overflows and improve performance.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that b/a is also called the aspect ratio of the ellipsoid, which may be more descriptive than b_div_a. I have noted another pair of identities here. There's no reference to literature, but I remember adding the name and the referred ellipsoid method right after having seen it mentioned in an absolutely reliable source (perhaps Rapp, OSU)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks. Do you know if there is a conventional short name/letter for the aspect ratio?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks. Do you know if there is a conventional short name/letter for the aspect ratio?

I do not remember one, and as I was too stupid to write down the reference in the Rust Geodesy Bibliography it will be hard to find again - but this paper uses alpha (and swaps the meaning of a and b!), while Rapp uses alpha for the angular eccentricity, and hence b/a = arccos(alpha). So it does not look like there is any firmly established convention.

Also, I see from this Wikipedia page, that it is also common to define the aspect ratio as the larger parameter divided by the smaller, so even in that aspect (!) there does not seem to be any clear convention.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

after all, isn't b_div_a quite explicit ;-) ?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

after all, isn't b_div_a quite explicit ;-) ?

It can probably harder get any more explicit :-) so given the lack of common nomenclature, it is obviously the better choice!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice trick using b/a, that is always <1, to avoid overflows and improve performance.

... although I think a few of Jupiter's moons are actually prolate, so this will not hold if we at some time accidentally blindly import IAU ellipsoids

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The algorithm is still stable. If it were thaaat eccentric, then using an ellipsoid model wouldn't be a good idea ;)
I'm curious what is the physics behind a spinning prolate moon.

Copy link
Member

@busstoptaktik busstoptaktik Mar 17, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The algorithm is still stable.

Ah, yes, I now see that it is, since we may safely assume that b never equals the imaginary unit times a :-)

I'm curious what is the physics behind a spinning prolate moon.

Physically, I believe it's as stable as an oblate, as long as the spin axis and the principal axes of inertia are reasonably aligned. Apparently it just happens to spin around the longest axis, for whichever reason $DEITY came up with during the creation of the solar system (and, in the case of Saturn, whichever perturbations the poor moon suffers from the debris of the ring it shepherds)

double c, s;
if (norm != 0) {
const double inv_norm = 1.0 / norm;
c = p_div_a_b_div_a * inv_norm;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had to write it down in paper to check that they are equivalent.

@wblangdon
Copy link

:-) I am out of the office next week, but do not hesitate to let me know if I can help when I get back, eg timings

@rouault
Copy link
Member Author

rouault commented Mar 16, 2024

:-) I am out of the office next week, but do not hesitate to let me know if I can help when I get back, eg timings

yes, you're feedback on timings would be helpful since my own measurements show only a modest 13% improvement

@wblangdon
Copy link

sure:-) Please do not delay waiting for me, as I say I will be out-of-action for a while...

@wblangdon
Copy link

geodetic() speed up cart.cpp_2d22cf6 relative PROJ-master 37% (GCC 10.2.1 -O3 i7-4790 3.60GHz)

@rouault rouault added this to the 9.5.0 milestone Mar 24, 2024
@rouault rouault merged commit 31ffa2b into OSGeo:master Mar 24, 2024
23 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants