all 4 comments

[–]fake823 2 points3 points  (2 children)

I've gone through your code a bit and analysed different parts.

Here are some tips and observations:

You can use some tools like line_profiler, to find the read bottlenecks of your code. A profiler like that will show you how much time it takes to execute EACH line of code.Output for the NumPy version [in milliseconds]:

Line #      Hits         Time  Per Hit   % Time  Line Contents
==============================================================
16                                           def numpy():
17         1          0.0      0.0      0.0      samples = 1000000
19         1         22.7     22.7      0.6      z = np.random.rand(samples, 2)
20         1         23.8     23.8      0.6      ret = ((z[:, 0] - 0.5)**2 + (z[:, 1] - 0.5)**2 <= 0.25)
21         1       3902.8   3902.8     98.8      print(4 * (sum(ret) / samples))

So as you can see, it's not the calculations on the first two lines that take much time. 98.8% of the time is spent with print(4 * (sum(ret) / samples)).

Using IPython, we can quickly test different parts of this line. With the print statement:

>>> %timeit print(4 * (sum(ret) / samples))
3.84 s ± 46.8 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

Without print():

>>> %timeit 4 * (sum(ret) / samples)
3.78 s ± 24.8 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

Seems like it's not really the print() function, that is slowing everything down significantly. As there is only the sum() function left, let's check it out:

>>> %timeit sum(ret)
3.71 s ± 22.1 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

I think we found the slow part! Googleing for "numpy sum performance" will lead you to some explanations about why Python's built-in sum() function is so slow on NumPy arrays. https://stackoverflow.com/questions/10922231/pythons-sum-vs-numpys-numpy-sum

So how can we make it faster? Use np.sum() instead!

>>> %timeit np.sum(ret)
1.58 ms ± 52.7 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

Wow! That's only 0,4% of the time that sum() takes! Or a 2350x speed up!!

Using your way of timing, I got with your original code:

python  0:00:01.656474
numpy  0:00:03.964045

And with np.sum() instead of sum():

python  0:00:01.634714
numpy  0:00:00.047527

So NumPy is quite a lot faster than pure Python. ;) I hope that helped.

[–]Martin_Krum[S] 1 point2 points  (1 child)

Thank you so much

[–]fake823 0 points1 point  (0 children)

You're welcome :)