numba icon indicating copy to clipboard operation
numba copied to clipboard

@guvectorize not accepting new size variable (i.e. () -> (n)) in output argument

Open Rik-de-Kort opened this issue 6 years ago • 7 comments

MnWE:

from numba import guvectorize


@guvectorize("int64, int64[:]", "() -> (n)")
def result(x, res):
    for i in range(3):
        res[i] = x


if __name__ == "__main__":
    print(result(3))

Yields the following error:

Traceback (most recent call last):
  File "C:/Users/User/Documents/numba_playground/guvectorize_test.py", line 4, in <module>
    @guvectorize("int64, int64[:]", "() -> (n)")
  File "C:\Users\User\Anaconda3\lib\site-packages\numba\npyufunc\decorators.py", line 177, in wrap
    guvec = GUVectorize(func, signature, **kws)
  File "C:\Users\User\Anaconda3\lib\site-packages\numba\npyufunc\decorators.py", line 50, in __new__
    targetoptions=kws)
  File "C:\Users\User\Anaconda3\lib\site-packages\numba\npyufunc\ufuncbuilder.py", line 278, in __init__
    self.sin, self.sout = parse_signature(signature)
  File "C:\Users\User\Anaconda3\lib\site-packages\numba\npyufunc\sigparse.py", line 63, in parse_signature
    raise NameError('undefined output symbols: %s' % ','.join(sorted(diff)))
NameError: undefined output symbols: n

Related to this discussion from 2016: https://groups.google.com/a/continuum.io/forum/#!topic/numba-users/tjkxRHj4x4k

Workaround there is to pass a dummy output array, like so:

@guvectorize("int64, int64[:], int64[:]", "(), (n) -> (n)")
def result2(x, dum, res):
    for i in range(dum.shape[0]):
        res[i] = x

Do mind the argument type for dum here, you'll likely have to explicitly declare it with dtype int64.

Rik-de-Kort avatar Mar 08 '18 09:03 Rik-de-Kort

I just hit this issue. I would like to write a guvectorize'd function that returns an output of different size from the input. Is this possible?

rabernat avatar Oct 28 '18 19:10 rabernat

The dummy output array approach really helps, thanks! But if I don't know the length of the output array originally, how can I solve this?

MAbdelatti avatar Dec 22 '18 18:12 MAbdelatti

I also have this problem. Has anyone looked at a fix?

ChristopherMayes avatar Oct 24 '21 00:10 ChristopherMayes

I also have this problem. Has anyone looked at a fix?

I would imagine not - any further updates would be likely to have been posted to this issue.

gmarkall avatar Oct 25 '21 09:10 gmarkall

Joining the club, just hit this issue - (still) present in all pipelines, i.e. targets cpu, parallel, cuda.

s-m-e avatar Jan 01 '24 14:01 s-m-e

Does NumPy allow new size variables in output arguments for Generalized UFuncs?

gmarkall avatar Jan 02 '24 12:01 gmarkall

Does NumPy allow new size variables in output arguments for Generalized UFuncs?

I think so?

Typically, the size of all core dimensions in an output will be determined by the size of a core dimension with the same label in an input array. This is not a requirement, and it is possible to define a signature where a label comes up for the first time in an output, although some precautions must be taken when calling such a function. An example would be the function euclidean_pdist(a), with signature (n,d)->(p), that given an array of n d-dimensional vectors, computes all unique pairwise Euclidean distances among them. The output dimension p must therefore be equal to n * (n - 1) / 2, but it is the caller’s responsibility to pass in an output array of the right size. If the size of a core dimension of an output cannot be determined from a passed in input or output array, an error will be raised.

https://numpy.org/doc/stable/reference/c-api/generalized-ufuncs.html

ricardoV94 avatar May 01 '24 13:05 ricardoV94