umop apisdn
umop apisdn

Reputation: 683

Using NumPy array operations with Numba's @guvectorize

I've been experimenting with Numba lately, and here's something that I still cannot understand:

In a normal Python function with NumPy arrays you can do something like this:

# Subtracts two NumPy arrays and returns an array as the result
def sub(a, b):
    res = a - b
    return res

But, when you use Numba's @guvectorize decorator like so:

# Subtracts two NumPy arrays and returns an array as the result
@guvectorize(['void(float32[:], float32[:], float32[:])'],'(n),(n)->(n)')
def subT(a, b, res):
    res = a - b

The result is not even correct. Worse still, there are instances where it complains about "Invalid usage of [math operator] with [parameters]"

I am baffled. Even if I try this:

# Subtracts two NumPy arrays and returns an array as the result
@guvectorize(['void(float32[:], float32[:], float32[:])'],'(n),(n)->(n)')
def subTt(a, b, res):
    res = np.subtract(a,b)

The result is still incorrect. Considering that this is supposed to be a supported Math operation, I don't see why it doesn't work.

I know the standard way is like this:

# Subtracts two NumPy arrays and returns an array as the result
@guvectorize(['void(float32[:], float32[:], float32[:])'],'(n),(n)->(n)')
def subTtt(a, b, res):
    for i in range(a.shape[0]):
        res[i] = a[i] - b[i]

and this does work as per expected.

But what is wrong with my way?

P/S This is just a trivial example to explain my problem, I don't actually plan to use @guvectorize just to subtract arrays :P P/P/S I suspect it has something to do with how the arrays are copied to gpu memory, but I am not sure... P/P/P/S This looked relevant but the function here operates only on a single thread right...

Upvotes: 4

Views: 1081

Answers (1)

chrisb
chrisb

Reputation: 52266

The correct way to write this is:

@guvectorize(['void(float32[:], float32[:], float32[:])'],'(n),(n)->(n)')
def subT(a, b, res):
    res[:] = a - b

The reason what you tried didn't work is a limitation of python syntax not particular to numba.

name = expr rebinds the value of name to expr, it can never mutate the original value of name, as you could with, e.g. c++ references.

name[] = expr calls (in essence), name.__setitem__ which can be used to modify name, as numpy arrays do, the empty slice [:] refers to the whole array.

Upvotes: 2

Related Questions