1

I'm having this problem where the numba implementation of np.diff does not work on a slice of a matrix. Is this a bug or am I doing something wrong?

import numpy as np
from numba import njit
v = np.ones((2,2))
np.diff(v[:,0])
array([0.])
@njit
def numbadiff(x):
    return np.diff(x)

numbadiff(v[:,0])

This last call returns in an error, but I'm not sure why.

2 Answers2

6

The problem is that np.diff in Numba does an internal reshape, which is only supported for contiguous arrays. The slice that you are making, v[:, 0], is not contiguous, hence the error. You can get it to work using np.ascontiguousarray, which returns a contiguous copy of the given array if it is not already contiguous:

numbadiff(np.ascontiguousarray(v[:, 0]))

Note you can also just avoid np.diff and redefine numbadiff as:

@njit
def numbadiff(x):
    return x[1:] - x[:-1]
jdehesa
  • 58,456
  • 7
  • 77
  • 121
  • Thank you. My problem is actually more complex, as the matrix i'm trying to diff is already inside a numba function. The above was just a simple replication. However, your response was very helpful, as I didn't know about contiguous arrays. I was able to fix it by using `np.copy(v[:,0])`, which is discussed in this [link](https://github.com/numba/numba/issues/1418). – alanlujan91 Nov 11 '19 at 18:55
  • 1
    Thanks, this solved it. I do think your alternative for diff should be x[1:] - x[:-1] (the other way around). I ended up using the alternative as it turned out the be faster than using np.ascontiguousarray – L. IJspeert Aug 27 '20 at 17:59
3

When you encounter an error, the polite thing is to show the error. Sometimes the full error with traceback is appropriate. For numba that may be too much, but you should try to post a summary. It makes it easier for us, especially if we aren't in a position to run your code and see the error ourselves. You might even learn something.

I ran your example and got (in part):

In [428]: numbadiff(np.ones((2,2))[:,0])                                        
---------------------------------------------------------------------------
TypingError    
...
TypeError: reshape() supports contiguous array only
...
    def diff_impl(a, n=1):
        <source elided>
        # To make things easier, normalize input and output into 2d arrays
        a2 = a.reshape((-1, size))
...
TypeError: reshape() supports contiguous array only
....
This is not usually a problem with Numba itself but instead often caused by
the use of unsupported features or an issue in resolving types.

This supports the diagnosis and fix that @jdehesa provides. It's not a bug in numba; it's a problem with your input.

One disadvantage with using numba is that the errors are harder to understand. Another apparently is that it isn't quite as flexible about inputs such as this array view. If you seriously want the speed advantages, you need to be willing to dig into the error messages yourself.

hpaulj
  • 221,503
  • 14
  • 230
  • 353
  • 1
    The editor would not let me provide the error (too much code, not enough text?), but thank you for your suggestions. – alanlujan91 Nov 11 '19 at 18:43