Monday, 26 November 2018

numba ahead of time compilation of recursive function

I am trying to compile a recursive function ahead of time. As a MCVE, let's take the following function:

#import numba as nb
from numba.pycc import CC
cc = CC('precompiled')

#@nb.njit
@cc.export('gsum', 'int64(int64)')
def gsum(n):
    if n>1:
        return n+gsum(n-1)
    else:
        return 1

if __name__== '__main__':
##    print(gsum(5))
    cc.compile()

If I run this code, I get the following error trace:

Traceback (most recent call last):
  File "numba_ahead.py", line 17, in <module>
    cc.compile()
  File "/opt/local/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/numba/compiler_lock.py", line 32, in _acquire_compile_lock
    return func(*args, **kwargs)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/numba/pycc/cc.py", line 212, in compile
    objects, dll_exports = self._compile_object_files(build_dir)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/numba/compiler_lock.py", line 32, in _acquire_compile_lock
    return func(*args, **kwargs)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/numba/pycc/cc.py", line 200, in _compile_object_files
    compiler.write_native_object(temp_obj, wrap=True)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/numba/pycc/compiler.py", line 198, in write_native_object
    library = self._cull_exports()
  File "/opt/local/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/numba/compiler_lock.py", line 32, in _acquire_compile_lock
    return func(*args, **kwargs)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/numba/pycc/compiler.py", line 157, in _cull_exports
    locals={}, library=library)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/numba/compiler.py", line 904, in compile_extra
    return pipeline.compile_extra(func)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/numba/compiler.py", line 367, in compile_extra
    return self._compile_bytecode()
  File "/opt/local/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/numba/compiler.py", line 835, in _compile_bytecode
    return self._compile_core()
  File "/opt/local/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/numba/compiler.py", line 822, in _compile_core
    res = pm.run(self.status)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/numba/compiler_lock.py", line 32, in _acquire_compile_lock
    return func(*args, **kwargs)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/numba/compiler.py", line 253, in run
    raise patched_exception
  File "/opt/local/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/numba/compiler.py", line 244, in run
    stage()
  File "/opt/local/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/numba/compiler.py", line 477, in stage_nopython_frontend
    self.locals)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/numba/compiler.py", line 1005, in type_inference_stage
    infer.build_constraint()
  File "/opt/local/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/numba/typeinfer.py", line 816, in build_constraint
    self.constrain_statement(inst)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/numba/typeinfer.py", line 1016, in constrain_statement
    self.typeof_assign(inst)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/numba/typeinfer.py", line 1079, in typeof_assign
    self.typeof_global(inst, inst.target, value)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/numba/typeinfer.py", line 1177, in typeof_global
    typ = self.resolve_value_type(inst, gvar.value)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/numba/typeinfer.py", line 1100, in resolve_value_type
    raise TypingError(msg, loc=inst.loc)
numba.errors.TypingError: Failed in nopython mode pipeline (step: nopython frontend)
Untyped global name 'gsum': cannot determine Numba type of <class 'function'>

File "numba_ahead.py", line 9:
def gsum(n):
    <source elided>
    if n>1:
        return n+gsum(n-1)
        ^

So apparently cc.export doesn't know the type of the function it is compiling, if that function calls itself. Is there any way to fix the problem? When I compile the same code just in time with njit (commented-out lines) the code compiles just fine.



from numba ahead of time compilation of recursive function

No comments:

Post a Comment