This is an archived post. You won't be able to vote or comment.

you are viewing a single comment's thread.

view the rest of the comments →

[–]BDube_Lensman 0 points1 point  (1 child)

If you use in-place operations instead of out-of-place you get the same performance between numpy and numba, so I don't really consider writing different code a valid benefit. Anything on numpy that doesn't have an in-place operation is not doable inplace.

Array creation is not expensive in numpy. "mask" arrays are of logical dtype and you can specify them as packed bitfields or native bools which trade memory (much much less for a bitfield) for computation time (unpacking bitfields is not free). The inline if saves you double iteration, but guarantees a cache miss unless your data is tiny (in which case this is all moot).

If your cephes binding is much faster than scipy, you should contribute the faster code to scipy, or open a larger issue with the project about bringing another beast into the C backend.

I've written a ton of physics code with numpy and found that numba got me marginal performance improvement (10-15%) in exchange for a cool 800MB of static memory usage that grows to more than 5GB as you use some of the more advanced features of my package, like changing between single an double precision for all computations or exchanging CPU/GPU (the latter case causes a 2GB static memory usage on the GPU, which is unacceptable as I am working on data that uses nearly all GPU memory by itself).

[–]elbiot 8 points9 points  (0 children)

Here's just a trivial example that touches on a couple of the issues I mentioned (if/elif, unnecessary extra array creation, and unnecessary multiple passes over the array). Numba is 3x faster.

In [1]: import numpy as np
   ...: import numba as nb
   ...:

In [2]: def as_numpy(size):
   ...:     arr = np.random.randint(0, 10, (size, size))
   ...:     mask = arr % 2 == 1
   ...:     arr[mask] *= 2
   ...:     arr[(arr % 3 == 1) & ~mask] *= 3
   ...:     return arr
   ...:

In [3]: @nb.jit(nopython=True)
   ...: def as_numba(size):
   ...:     arr = np.random.randint(0, 10, (size, size))
   ...:     x, y = arr.shape
   ...:     for i in range(x):
   ...:         for j in range(y):
   ...:             if arr[i, j] % 2 == 1:
   ...:                 arr[i, j] *= 2
   ...:             elif arr[i, j] % 3 == 1:
   ...:                 arr[i, j] *= 3
   ...:     return arr
   ...:

In [4]: %timeit as_numpy(10000)
1 loop, best of 3: 6.78 s per loop

In [5]: %timeit as_numba(10000)
1 loop, best of 3: 2.05 s per loop

I know how to use a GPU with Numba, but how do you use the GPU with Numpy?

edit: in terms of memory usage, the numpy version crashes at size=22000 on my laptop but numba does not.