Understanding Function Argument Type Specification in @jit of numba

Asked 2 years ago, Updated 2 years ago, 47 views

We introduced numba to speed up pyhon.
Among them, only one function cannot be typed in @jit and the program cannot be run.
The function pulls other functions as arguments, but I don't know the type specification when the function is an argument.
Does anyone know the solution?
Or do you mean that @jit cannot use a function that treats a function as an argument?

12/25 postscript
The code has been rewritten as follows.
I suspect that the type is being treated as NoneType because it is not recognized correctly.

source code

 from numba import jit, int32, float64
from number import types

@jit(int32(int32))
defa(x):
  return2+x

@jit(int32(int32))
defb(x):
  return2*x

@jit(float64(int32))
defc(x):
  return 2/x

@jit([print(((f._type.get_call_signatures()))) for fin globals().values() if hasattr(f, '_type') and isinstance(f._type, types.Dispatcher))]) 
def(x,g):
  return(x)

if__name__=='__main__':
  print(f'Signature of function a: {a._type.get_call_signatures()[0]}')
  print(f'Signature of function b: {b._type.get_call_signatures()[0]}')
  print(f'Signature of function c: {c._type.get_call_signatures()[0]}')
  print(f'Signature of function f:\n{f._type.get_call_signatures()[0]}')
  print(f'f(1,a)={f(1,a)}')
  print(f'f(1,b)={f(1,b)}')
  print(f'f(3,c)={f(3,c)}')

error message

runfile('C:/Users/Nakada/Desktop/DIC/python/code/Untitled 4.py', wdir='C:/Users/Nakada/Desktop/DIC/python/code')
<generator object<genexpr>at 0x00000257391877C8>
Traceback (most recent call last):

  File "<ipython-input-134-e1e163fb48a4>", line 1, in <module>
    runfile('C:/Users/nakada/Desktop/DIC/python/code/Untitled 4.py', wdir='C:/Users/nakada/Desktop/DIC/python/code')

  File "C:\ProgramData\Anaconda3\lib\site-packages\spyder_kernel\customize\spydercustomize.py", line 827, in runfile
    execfile(filename,namespace)

  File "C:\ProgramData\Anaconda3\lib\site-packages\spyder_kernel\customize\spydercustomize.py", line 110, in execfile
    exec(compile(f.read(), filename, 'exec', namespace)

  File "C:/Users/nakada/Desktop/DIC/python/code/Untitled 4.py", line 23, in <module>
    @jit([print(((f._type.get_call_signatures()))) for fin globals().values() if hasattr(f, '_type') and isinstance(f._type, types.Dispatcher))])

  File "C:\ProgramData\Anaconda3\lib\site-packages\numba\decorators.py", line 186, in wrapper
    disp.compile(sig)

  File "C:\ProgramData\Anaconda3\lib\site-packages\numba\compiler_lock.py", line 32, in_acquire_compile_lock
    return func (*args, **kwargs)

  File "C:\ProgramData\Anaconda3\lib\site-packages\numba\dispatcher.py", line 676, incompile
    args,return_type=sigutils.normalize_signature(sig)

  File "C:\ProgramData\Anaconda3\lib\site-packages\numba\sigutils.py", line 37, normalize_signature
    parsed.__class__.__name__

TypeError: invalid signature: None (type: 'NoneType') values to 'NoneType' installed of table or signature

1/6 Add
When I first executed the code you gave me, I received the following error:

source code

 from numba import jit, int32, float64
from number import types

@jit(int32(int32))
defa(x):
  return2+x

@jit(int32(int32))
defb(x):
  return2*x

@jit(float64(int32))
defc(x):
  return 2/x

@jit([
  (f._type.get_call_signatures()[0][0].return_type) (int32, f._type)
  for inglobals().values()
  if hasattr(f, '_type') and
     isinstance(f._type, types.Dispatcher) and
     f._type.get_call_signatures()[0][0]in
       (int32(int32), float64(int32))
])
def(x,g):
  return(x)

if__name__=='__main__':
  print(f'Signature of function a: {a._type.get_call_signatures()[0]}')
  print(f'Signature of function b: {b._type.get_call_signatures()[0]}')
  print(f'Signature of function c: {c._type.get_call_signatures()[0]}')
  print(f'Signature of function f:\n{f._type.get_call_signatures()[0]}')
  print(f'f(1,a)={f(1,a)}')
  print(f'f(1,b)={f(1,b)}')
  print(f'f(3,c)={f(3,c)}')

error code

unfile('C:/Users/Nakada/Desktop/DIC/python/code/Untitled 4.py', wdir='C:/Users/Nakada/Desktop/DIC/python/code')
Traceback (most recent call last):

  File "<ipython-input-135-e1e163fb48a4>", line 1, in <module>
    runfile('C:/Users/nakada/Desktop/DIC/python/code/Untitled 4.py', wdir='C:/Users/nakada/Desktop/DIC/python/code')

  File "C:\ProgramData\Anaconda3\lib\site-packages\spyder_kernel\customize\spydercustomize.py", line 827, in runfile
    execfile(filename,namespace)

  File "C:\ProgramData\Anaconda3\lib\site-packages\spyder_kernel\customize\spydercustomize.py", line 110, in execfile
    exec(compile(f.read(), filename, 'exec', namespace)

  File "C:/Users/nakada/Desktop/DIC/python/code/Untitled 4.py", line 18, in <module>
    for inglobals().values()

  File "C:/Users/nakada/Desktop/DIC/python/code/Untitled 4.py", line 21, in <listcomp>
    f._type.get_call_signatures()[0][0]in

IndexError:list index out of range

To resolve this error,
@jit([print(f._type.get_call_signatures()) for fin globals().values() if hasattr(f, '_type') and isinstance(f._type, types.Dispatcher)])
Are you going to use ?

1/6 Additional 2
I understand that the for statement in line 18 of the first code you gave me is necessary because the types of functions a, b and c are different, is that correct?
Also, if the function c is the same type as a and b, is it possible to omit or rewrite the for statement or less?
Sorry for asking so many questions, I look forward to hearing from you.

python python3

2022-09-30 21:45

2 Answers

This is not a direct answer, but I have found some relevant information, so I will summarize it as an answer.

  • Numba 0.39 and later, JIT compiled global functions can be passed as arguments.However, there is no type annotation.

    From the Numba document 1.18 Frequently Asked Questions:

    As of Numba 0.39, you can, so long as the function argument has been JIT-compiled:

    @jit(nopython=True)
    def(g,x):
        return(x)+g(-x)
    
    result=f(jitted_g_function,1)
    

    (abbreviated)

  • The treatment of functions and lambda defined inside the function is limited (as of Numba 0.47).

    From the Numba document 2.6.1.2.Functions:

    Numba now supports inner functions as long as they are non-recursive and only called locally, but not passed as argument or returned as result. The use of closure variables (variables defined in outside scopes) with an inner function is supported.

    Associated issue: Support for higher order functions and lambdas

  • If it is a JIT compiled function, you can use numba.typeof to get the type, which seems to be useful for type annotations.However, this function is not stable, and the document said, "If you don't need it, leave it to Numba's type inference."Also, even if you use numba.typeof to get the type of function, it's more like the ID of the function than the type of function, so you have to enumerate it as much as you want like metropolis's answer.

With Numba 0.39 and later, JIT compiled global functions can be passed as arguments.However, there is no type annotation.

From the Numba document 1.18 Frequently Asked Questions:

As of Numba 0.39, you can, so long as the function argument has been JIT-compiled:

@jit(nopython=True)
def(g,x):
    return(x)+g(-x)

result=f(jitted_g_function,1)

(abbreviated)

Functions and lambda defined inside a function are limited (as of Numba 0.47).

From the Numba document 2.6.1.2.Functions:

Numba now supports inner functions as long as they are non-recursive and only called locally, but not passed as argument or returned as result. The use of closure variables (variables defined in outside scopes) with an inner function is supported.

Associated issue: Support for higher order functions and lambdas

If it is a JIT compiled function, you can use numba.typeof to get the type, which seems to be useful for type annotations.However, this function is not stable, and the document said, "If you don't need it, leave it to Numba's type inference."Also, even if you use numba.typeof to get the type of function, it is more like the ID of the function than the type of function, so you will have to enumerate it as much as you want like metropolis's answer.


2022-09-30 21:45

How about using numba.types.functions.Dispatcher._type?The following is a simple example of execution:

 from numba import jit, int32, float64
from number import types

@jit(int32(int32))
defa(x):
  return2+x

@jit(int32(int32))
defb(x):
  return2*x

@jit(float64(int32))
defc(x):
  return 2/x

@jit([
  (f._type.get_call_signatures()[0][0].return_type) (int32, f._type)
  for inglobals().values()
  if hasattr(f, '_type') and
     isinstance(f._type, types.Dispatcher) and
     f._type.get_call_signatures()[0][0]in
       (int32(int32), float64(int32))
])
def(x,g):
  return(x)

if__name__=='__main__':
  print(f'Signature of function a: {a._type.get_call_signatures()[0]}')
  print(f'Signature of function b: {b._type.get_call_signatures()[0]}')
  print(f'Signature of function c: {c._type.get_call_signatures()[0]}')
  print(f'Signature of function f:\n{f._type.get_call_signatures()[0]}')
  print(f'f(1,a)={f(1,a)}')
  print(f'f(1,b)={f(1,b)}')
  print(f'f(3,c)={f(3,c)}')

=>
Signature of function a: [(int32,)->int32]
Signature of function b: [(int32,)->int32]
Signature of function c: [(int32,)->float64]
Signature of function f:
[( int32, type (CPUDispatcher(<function a at 0x7f4f86c82b00>)) - > int32,
 ( int32, type (CPUDispatcher(<function bat 0x7f4f5e4800e0>)) - > int32,
 ( int32, type (CPUDispatcher(<function cat0x7f4f5e429050>)) - >float64]
f(1,a) = 3
f(1,b) = 2
f(3,c) = 0.66666666666666666666666


2022-09-30 21:45

If you have any answers or tips


© 2024 OneMinuteCode. All rights reserved.