Uh oh!
There was an error while loading.Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork8.1k
Micro optimization of plotting#26303
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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.
Already on GitHub?Sign in to your account
Uh oh!
There was an error while loading.Please reload this page.
Conversation
tacaswell commentedJul 13, 2023
importmatplotlib# print(matplotlib)importpyperfsetup="""import matplotlib.figure as mfigurex=[1,2,3,4,5]y=[5,6,3,3,4]n=6def go(): for ii in range(n): fig = mfigure.Figure() ax = fig.subplots() ax.plot(x,y)"""runner=pyperf.Runner()runner.timeit(name="mpl",stmt="go()",setup=setup) This may be a better bench mark script. I have concerns that the speed up is less than the std.... |
tacaswell commentedJul 13, 2023
well, did you mean to plot many times to the same figure or do a plot per figure? |
tacaswell commentedJul 13, 2023
new (this branch)mpl: Mean +- std dev: 796 us +- 7 us old (3.7.2 from wheels)mpl: Mean +- std dev: 845 us +- 13 us using importmatplotlib# print(matplotlib)importpyperfsetup="""import matplotlib.figure as mfigurex=[1,2,3,4,5]y=[5,6,3,3,4]n=6fig = mfigure.Figure()ax = fig.subplots()def go(): for ii in range(n): ax.plot(x,y)"""runner=pyperf.Runner()runner.timeit(name="mpl",stmt="go()",setup=setup) so I think there is a real speed up here, even if it is realitvely small against the cost of making a new |
oscargus left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Most things make sense for sure. Some things I simply trust are faster.
A few minor comments though.
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
lib/matplotlib/cbook.py Outdated
| defsafe_isfinite(val): | ||
| ifvalisNone: | ||
| returnFalse | ||
| ifisinstance(val,int): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
I'm not sure special-casing ints here make sense -- certainly that'll make a microbenchmark based on plotting ints faster, but at the cost of introducing a branch for all other cases (plotting floats is likely much more common, and even np.int is perhaps a more common case than python ints in real code).
If one really wants to workaround the fact that np.isfinite is relatively slow, one can instead use math.isfinite (which on a quick microbenchmark is extremely fast), taking into account the fact that it won't handle certain cases like datetimes (but will handle numpy floats and ints), so something like
try:ifmath.isfinite(val):returnTrueexceptTypeError:pass# continue with the np.isfinite check
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
This is an excellent suggestion. On my systemnp.isfinite(val) if np.isscalar(val) else True is about 900 ns, andmath.isfinite(val) (including the try-except) is 80 ns. Theisinstance(val, int) is 50 ns, but does not handle the important float case.
PR summary
In this PR some micro optimizations are applied to the matplotlib plotting. Optimizations selected are in methods that show in the profiling (cProfile).
Benchmark
on script
PR checklist