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

Optimize circumsphere and triangulation.py #245

Closed
wants to merge 14 commits into from

Conversation

philippeitis
Copy link
Contributor

@philippeitis philippeitis commented Dec 15, 2019

To speed up circumsphere, I directly called numpy's determinant function, as fast_det defaults to this case for >= 4 dimensions, which is always the case for circumsphere. I also directly took the norm, as this again defaults to sqrt(np.dot(vec * vec)) in fast_det for 4 dimensions. I also removed np.delete in favour of masked indices, which means that numpy doesn't need to allocate new arrays for each determinant.

For circumsphere, the speedup is about 33% on a four dimensional sphere (1.35x faster):

(50000 runs on arbitrary coordinates)

opt  circumsphere: 8.907416s
nopt circumsphere: 13.325046s
opt  circumsphere: 7.633841s
nopt circumsphere: 12.151468s

For a five dimensional sphere, the difference is more obvious, at around 50% (2x faster):
(50000 runs on arbitrary coordinates)

opt  circumsphere: 11.039010s
nopt circumsphere: 19.448841s
opt  circumsphere: 10.594215s
nopt circumsphere: 18.614510s

I also added general optimizations by directly importing all numpy functions - for hot loops, this means that Python doesn't have to look up the function repeatedly, which can save a fair amount of time.

To speed up circumsphere, I directly imported the relevant functions, and I also removed the fast_det calls, as these end up defaulting to numpy's linalg.det anyways. I also avoid array allocations by getting rid of np.delete() calls. I made a few more tweaks, particularly in dealing with applying the (-1) multiplier and the constant factor a.
I also added general optimizations by directly importing all numpy functions - for hot loops, this means that Python doesn't have to look up the function repeatedly.
It appears that for vectors with large values, it is possible to induce an integer overflow in dot(x, x).
Add unit test for test_circumsphere.
Add black formatted code.
Update with black formatted code.
@basnijholt
Copy link
Member

Thanks a lot for doing these optimizations!

You can easily fix all the style issues by running pre-commit run --all (first install using pip install pre-commit).

I've made #246 to make this more obvious in the future.

I don't see any usages of numpy's sqrt for vectors, so I just switched the import over to the math library.
@akhmerov
Copy link
Contributor

Should we use @ instead of dot? I might be wrong, but it seems either faster or same speed, and more readable.

Forgot to run pre-commit.
@akhmerov
Copy link
Contributor

While most of the names that we import have no collision with built-ins, abs does override the built-in one. Would it be a good idea to import abs as np_abs?

Is making all names available in the module namespace an important optimization?

@philippeitis
Copy link
Contributor Author

philippeitis commented Dec 16, 2019

While most of the names that we import have no collision with built-ins, abs does override the built-in one. Would it be a good idea to import abs as np_abs?

Is making all names available in the module namespace an important optimization?

As a quick demo:

>python -m timeit -s"from math import sqrt" "sqrt(5.6)"
5000000 loops, best of 5: 69.4 nsec per loop

>python -m timeit -s"import math" "math.sqrt(5.6)"
5000000 loops, best of 5: 94.8 nsec per loop

A 20-30% performance boost from direct imports is pretty nice to have, though this may vary for specific functions and their overhead.

Use numpy's abs only for vectors.
@philippeitis
Copy link
Contributor Author

philippeitis commented Dec 16, 2019

Should we use @ instead of dot? I might be wrong, but it seems either faster or same speed, and more readable.

The issue with @ is that it doesn't work if the argument is a regular list (I think a lot of calls to fast norm aren't numpy arrays). Also, it seems to be slower, at least from my testing:

>python -m timeit -s"from numpy import array;vect = array([1,2,3,4])" "vect @ vect"
500000 loops, best of 5: 879 nsec per loop

>python -m timeit -s"from numpy import dot, array; vect = array([1,2,3,4])" "dot(vect, vect)"
500000 loops, best of 5: 603 nsec per loop

@philippeitis
Copy link
Contributor Author

Azure seems to be throwing this error which is causing the linting tests to fail:

Traceback (most recent call last):
  File "/home/vsts/.cache/pre-commit/repom1wn1zn2/py_env-python3.7/bin/black", line 5, in <module>
    from black import patched_main
  File "/home/vsts/.cache/pre-commit/repom1wn1zn2/py_env-python3.7/lib/python3.7/site-packages/black.py", line 15, in <module>
    import regex as re
  File "/home/vsts/.cache/pre-commit/repom1wn1zn2/py_env-python3.7/lib/python3.7/site-packages/regex.py", line 402, in <module>
    import _regex_core
  File "/home/vsts/.cache/pre-commit/repom1wn1zn2/py_env-python3.7/lib/python3.7/site-packages/_regex_core.py", line 21, in <module>
    import regex._regex as _regex
ModuleNotFoundError: No module named 'regex._regex'; 'regex' is not a package

@basnijholt
Copy link
Member

That failure is because of psf/black#1207.

I imagine that will be fixed soon.

@jbweston jbweston self-requested a review May 5, 2020 16:10
Copy link
Contributor

@jbweston jbweston left a comment

Choose a reason for hiding this comment

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

LGTM, and thank you for adding an extra test!

jbweston pushed a commit that referenced this pull request May 5, 2020
Optimize cirumsphere and triangulation.py
@jbweston
Copy link
Contributor

jbweston commented May 5, 2020

I merged this manually (so that we could get a rebase but also an explicit merge commit, which GitHub does not allow, for some reason), but it seems that GitHub did not register this as closing this PR.

@philippeitis your changes are merged in, but I will have to "close" this PR.

@jbweston jbweston closed this May 5, 2020
@jbweston
Copy link
Contributor

jbweston commented May 5, 2020

@philippeitis Let me know how you'd like me to credit you in the AUTHORS file (your GH profile does not have your real name).

@philippeitis
Copy link
Contributor Author

philippeitis commented May 8, 2020

@jbweston Happy to see these changes merged in. If you'd like to credit me in the AUTHORS file, my name is Philippe Solodov.

@basnijholt basnijholt mentioned this pull request May 19, 2020
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