Numba Generator Argument

Watch this question: function types in numba .

I am writing a function that should take a generator as one of its arguments. This is too complicated to insert here, so consider this toy example:

def take_and_sum(gen):
    @numba.jit(nopython=False)
    def inner(n):
        s = 0
        for _ in range(n):
            s += next(gen)
        return s
    return inner

It returns the sum of the first elements of the ngenerator. Usage example:

@numba.njit()
def odd_numbers():
    n = 1
    while True:
        yield n
        n += 2

take_and_sum(odd_numbers())(3) # prints 9

This value is because I would like to compile with nopython=True, and then I cannot pass gen(a pyobject) as an argument. Unfortunately, with nopython=TrueI get the error message:

TypingError: Failed at nopython (nopython frontend)
Untyped global name 'gen'

although I nopythoncompiled the generator.

What really gets confused about this is that hard coding works:

def take_and_sum():
    @numba.njit()
    def inner(n):
        gen = odd_numbers()
        s = 0.0
        for _ in range(n):
            s += next(gen)
        return s
    return inner

take_and_sum()(3)

I also tried turning my generator into a class:

@numba.jitclass({'n': numba.uint})
class Odd:
    def __init__(self):
        self.n = 1
    def next(self):
        n = self.n
        self.n += 2
        return n

, , nopython unsearchable:

LoweringError: Failed at nopython (nopython mode backend)
Internal error:
NotImplementedError: instance.jitclass.Odd#4aa9758<n:uint64> as constant unsupported
+4
1

, , , . ( numba 0.30):

numba- jitclass:

import numba

@numba.jitclass({'n': numba.uint})
class Odd:
    def __init__(self):
        self.n = 1

    def __iter__(self):
        return self

    def __next__(self):
        n = self.n
        self.n += 2
        return n

:

>>> next(Odd())
TypeError: 'Odd' object is not an iterator

numba.jitclass, :

>>> next(Odd())
1

. -, numba . , .

>>> t = odd_numbers()
>>> take_and_sum(t)(3)
9
>>> next(t)   # State has been updated, unfortunatly that requires nopython=False!
7

numba ().

, , , , :

>>> take_and_sum()(3) # using your hardcoded version
9.0
>>> take_and_sum()(3) # no updated state so this returns the same:
9.0

, , , :

@numba.jitclass({'n': numba.uint})
class Odd:
    def __init__(self):
        self.n = 1

    def calculate(self, n):
        s = 0.0
        for _ in range(n):
            s += self.n
            self.n += 2
        return s

>>> x = Odd()
>>> x.calculate(3)
9.0
>>> x.calculate(3)
27.0

, , , , , : -)

+2

Source: https://habr.com/ru/post/1667812/


All Articles