-
Notifications
You must be signed in to change notification settings - Fork 109
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
feat: add a page about compiling + parallel and GPU computing #252
Conversation
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.
Very amazing job! I don't think we need to remove or add much to it. I think it can be merged after solved the few comments I left.
# %% | ||
_ = jit_f(data) | ||
|
||
# %% | ||
# %%timeit | ||
jit_f(data) | ||
|
||
# %% [markdown] | ||
# Surprisingly, the JITted function was slower than plain Python and NumPy | ||
# implementation! Why did this happen? Numba does not provide valuable performance | ||
# gains over pure Python or NumPy code for simple operations and small dataset. | ||
# The JITted function turned out to be slower than the non-JIT implementation | ||
# because of the compilation overhead. Let's try increasing the size of our | ||
# data and perform a non-NumPy list comprehension on the data. | ||
# |
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 confused, why do you run it first on line 94, and then again? Wouldn't the first one on line 94 generates the compilation code, and therefore, the timed line (98) it just the running time?
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.
Yes, I was just trying to time the running time and not the compile time. Should I not compile the function before timing it?
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 think, in that case, it doesn't produce any difference, because as you said, the optimisation is not going to be much better than what numpy already does. We could leave it as it is and explain that for measuring JIT performance is normally done in that way. Though ideally, we should also measure the compilation to show that overhead.
So, I'd say, in all the jit examples, run it once with:
%timeit -n 1 -r 1
jit_function(data) # compilation and run
and then
%timeit
jit_function(data) # just run
This way we ensure that the compilation timing is calculated separately and don't affect the average (though in these examples is probably spread out). We need to note, however, that the result from the compilation run could be very noisy and could give a higher than real value (I think we mention that in the previous lesson when introducing timeit
).
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.
Thank you! Working on this right now 🚀
# That does not work. The error might be solvable or it might just be out of Numba's | ||
# scope. Numba does not distinguish between plain Python |
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.
It feels that we should give some insight into the error. But I don't know exactly where it is...
[Edit]: After playing with it, I think I've managed to so by flatting the arrays (and taking only the real part on the comparison)
@njit
def mandel_numpy(position,limit=50):
value = position.flatten()
diverged_at_count = np.zeros(position.shape).flatten()
while limit > 0:
limit -= 1
value = value**2+position.flatten()
diverging = (value * np.conj(value)).real > 4
if limit == 49: print(diverging.shape, diverged_at_count.shape)
first_diverged_this_time = (np.logical_and(diverging, diverged_at_count == 0))
diverging_at_count[first_diverged_this_time] = limit
value[diverging] = 2
return diverged_at_count.reshape(position.shape)
ymatrix, xmatrix = np.mgrid[ymin:ymax:ystep, xmin:xmax:xstep]
values = xmatrix + 1j * ymatrix
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.
Thank you for looking into this! 😄
# %% | ||
df | ||
# The computation gave us a dask object and not the actual answer. Why is that? | ||
# We can visualise the dask task graph using - |
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.
using ... is that a -
?
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.
Ah I think I misplaced something here. Will fix it!
Co-authored-by: David Pérez-Suárez <[email protected]>
ad6d3bf
to
6edb6da
Compare
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.
Awesome!!!!
Closes #239
I will need some help here to filter what content is underexplained and what is overexplained 🙂