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

[WIP] Improve benchmarks #1142

Merged
merged 19 commits into from
Apr 12, 2020
Merged

[WIP] Improve benchmarks #1142

merged 19 commits into from
Apr 12, 2020

Conversation

nitishp25
Copy link
Contributor

@nitishp25 nitishp25 commented Apr 7, 2020

Description

Fixes #782 and builds on top of the work done in #1088.

I've moved the following functions to resolve cyclic imports that occured when histogram was imported for _fast_kde:

  • _fast_kde, _fast_kde_2d, get_bins and _sturges_formula --> numeric_utils
  • get_coords --> utils

I've also modified the benchmarks and will cover more functions soon.

cc @OriolAbril, @ahartikainen

Checklist

  • Follows official PR format
  • Includes new or updated tests to cover the new feature
  • Code style correct (follows pylint and black guidelines)
  • Changes are listed in changelog

@OriolAbril OriolAbril mentioned this pull request Apr 7, 2020
4 tasks
@nitishp25
Copy link
Contributor Author

nitishp25 commented Apr 8, 2020

Should the next step be adding more benchmarks?

@aloctavodia
Copy link
Contributor

get_bins and _sturges_formula are mainly helper functions to compute plots, not to compute statistics (inside stats). That's why they are inside plot_utils. Any reason to move them to stats_utils?

@OriolAbril
Copy link
Member

It has been moved to solve a cyclic import due to the following dependencies:

  • _fast_kde should import _histogram from stats_utils, it currently does not because of this cyclic import which means that _fast_kde does not use numba anymore -> imports stats_utils
  • calculate_point_estimate needs _fast_kde -> imports fast_kde (assuming it is moved to its own file) -> imports stats_utils
  • hpd (multimodal only) needs get_bins -> imports plot_utils

I proposed to move _sturges_formula too (even though it is not necessary) to have it in the same file as get_bins

@nitishp25
Copy link
Contributor Author

It looks complicated but it's done to make the whole stats module independent of plots so that plots can import functions from stats module easily

@codecov
Copy link

codecov bot commented Apr 8, 2020

Codecov Report

Merging #1142 into master will increase coverage by 0.00%.
The diff coverage is 96.47%.

Impacted file tree graph

@@           Coverage Diff           @@
##           master    #1142   +/-   ##
=======================================
  Coverage   92.81%   92.82%           
=======================================
  Files          93       94    +1     
  Lines        9181     9193   +12     
=======================================
+ Hits         8521     8533   +12     
  Misses        660      660           
Impacted Files Coverage Δ
arviz/numeric_utils.py 95.18% <95.18%> (ø)
arviz/utils.py 91.02% <95.45%> (+1.02%) ⬆️
arviz/plots/__init__.py 100.00% <100.00%> (ø)
arviz/plots/backends/bokeh/densityplot.py 94.28% <100.00%> (ø)
arviz/plots/backends/bokeh/distplot.py 85.18% <100.00%> (ø)
arviz/plots/backends/bokeh/forestplot.py 92.88% <100.00%> (ø)
arviz/plots/backends/bokeh/posteriorplot.py 98.09% <100.00%> (+0.01%) ⬆️
arviz/plots/backends/bokeh/ppcplot.py 99.12% <100.00%> (ø)
arviz/plots/backends/bokeh/violinplot.py 94.64% <100.00%> (-0.10%) ⬇️
arviz/plots/backends/matplotlib/densityplot.py 96.42% <100.00%> (+0.06%) ⬆️
... and 24 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 3352a8a...7e4e638. Read the comment docs.


class Hist:
params = (True, False)
param_names = "Numba"
Copy link
Member

Choose a reason for hiding this comment

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

This have to be a single element tuple, the string is interpreted as an iterable and only the first letter is used: https://dev.azure.com/ArviZ/ArviZ/_build/results?buildId=2274&view=logs&j=273a7ac9-cc40-5d2f-3776-d61d22a0ef9c&t=8fe29edb-6726-5e00-142e-7c337980bc77&l=60

See Atleast_Nd for an example

histogram(self.data, bins=100)


class Variance:
Copy link
Member

Choose a reason for hiding this comment

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

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I was trying to debug this so I ran the benchmarks with --show-stderr flag but it only showed

asv: benchmark timed out (timeout 60.0s)

And when I ran the benchmarks with both --quick --show-stderr flags, it worked but the function took 31s to run with Numba=False and when I used the function in a notebook with the same data and numba disabled it ran in milliseconds. I think it's some issue with the benchmarks configuration, I'll continue looking.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

My bad, the data was too large so the function was actually really slow without Numba speed-up (taking ~30s and not milliseconds after I rechecked) and it caused the benchmark to fail :(

I'll reduce the data.

@aloctavodia
Copy link
Contributor

What about having a numerics.py (or some other name), and put there histogram, _fast_kde, _fast_kde_2d, get_bins and _sturges_formula?

@nitishp25 nitishp25 requested a review from OriolAbril April 10, 2020 10:12
Copy link
Member

@OriolAbril OriolAbril left a comment

Choose a reason for hiding this comment

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

LGTM

I proposed some minor changes to try and make benchmarks more informative.

else:
az.Numba.disable_numba()

def time_variance(self, numba_flag):
Copy link
Member

Choose a reason for hiding this comment

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

we should probably name this one time_variance_2d

_fast_kde(self.x)

class Fast_KDE_2d:
params = [(True, False), (10**5, 10**6)]
Copy link
Member

Choose a reason for hiding this comment

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

I have realized that with these shapes, there is no speedup when using numba, I tried to look if the same issue as with fast_kde_1d happened where the speedup was lost in a future PR, and it looks like the speed-up is still there, but is only seen for larger sizes.

Could we try something like this and see how do dimensions affect performance?

class Fast_KDE_2d:
    params = [
        (True, False), 
        ((100, 10**4), (10**4, 100), (1000, 1000))
    ]
    param_names = ("Numba", "shape")

    def setup(self, numba_flag, shape):
        self.x = np.random.randn(*shape)
        self.y = np.random.randn(n//10, 10)
        if numba_flag:
        ...

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ooh, I'll implement this.

Also, in #1088 you mentioned that more functions need to be covered in benchmarks and later on memory benchmarks and line profiling also to be added, so should I start adding all this now in this PR or sometime later?

Copy link
Member

Choose a reason for hiding this comment

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

Maybe it's better to wait for another PR

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I have realized that with these shapes, there is no speedup when using numba, I tried to look if the same issue as with fast_kde_1d happened where the speedup was lost in a future PR, and it looks like the speed-up is still there, but is only seen for larger sizes.

Could we try something like this and see how do dimensions affect performance?

class Fast_KDE_2d:
    params = [
        (True, False), 
        ((100, 10**4), (10**4, 100), (1000, 1000))
    ]
    param_names = ("Numba", "shape")

    def setup(self, numba_flag, shape):
        self.x = np.random.randn(*shape)
        self.y = np.random.randn(n//10, 10)
        if numba_flag:
        ...

It gives the following error:

ValueError: all the input array dimensions for the concatenation axis must match exactly, but along dimension 1, the array at index 0 has size 1000000 and the array at index 1 has size 100

Do x and y have to be of the same size always?

Also, I did self.y = np.random.randn(shape[0]//10, 10) instead of self.y = np.random.randn(n//10, 10). This is what you meant?

Copy link
Member

Choose a reason for hiding this comment

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

I forgot to update y, it should be created like x, they must be the same shape. Also, there shoud be no n instances anymore

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yup, I had removed n. The only problem was the different sizes of x and y. You'll see after the tests finish that there's still no speed-up :(

@OriolAbril
Copy link
Member

I was thinking that benchmarks should also be formatted with black. I think 3 lines have to be changed

scripts/lint.sh Outdated
python -m black -l 100 --check ${SRC_DIR}/arviz/ ${SRC_DIR}/examples/
=======
python -m black -l 100 --check ${SRC_DIR}/arviz/ ${SRC_DIR}/examples/ ${SRC_DIR}/asv_benchmarks/
>>>>>>> update fast_kde_2d benchmark and changelog
Copy link
Member

Choose a reason for hiding this comment

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

there has been some merge issue

@ahartikainen ahartikainen merged commit 8d11040 into arviz-devs:master Apr 12, 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.

A better way to benchmark the speed tests
4 participants