llc-tools
Decorators to make it easier to write SciPy LowLevelCallables
Decorators to make it easier to write SciPy LowLevelCallables
License: BSD 3-Clause "New" or "Revised" License
Decorators to make it easier to write SciPy LowLevelCallables
The functions in llc-tools are not even documented themselves. It would be good to change that. See the Guide to NumPy documentation:
The two blog posts that motivated this library contain some useful references for documentation:
https://ilovesymposia.com/2017/03/12/scipys-new-lowlevelcallable-is-a-game-changer/
https://ilovesymposia.com/2017/03/15/prettier-lowlevelcallables-with-numba-jit-and-decorators/
Currently, llc-tools doesn't have any documentation. It would be good to put some on ReadTheDocs or GitHub Pages.
Other useful references:
https://docs.scipy.org/doc/scipy/reference/generated/scipy.LowLevelCallable.from_cython.html
I followed your code on https://ilovesymposia.com/2017/03/15/prettier-lowlevelcallables-with-numba-jit-and-decorators/
import numba
from numba import cfunc, carray, jit
from numba.types import intc, CPointer, float64, intp, voidptr, uint8
from scipy import LowLevelCallable
def jit_filter_function(filter_function):
"""Decorator for use with scipy.ndimage.generic_filter."""
jitted_function = numba.jit(filter_function, nopython=True)
@cfunc(intc(CPointer(float64), intp, CPointer(float64), voidptr))
def wrapped(values_ptr, len_values, result, data):
values = carray(values_ptr, (len_values,), dtype=float64)
result[0] = jitted_function(values)
return 1
return LowLevelCallable(wrapped.ctypes)
@jit_filter_function
def fmin(values):
result = np.inf
for v in values:
if v < result:
result = v
Encountered the following error
LoweringError: Caused By:
Traceback (most recent call last):
File "/usr/local/lib/python2.7/site-packages/numba/compiler.py", line 238, in run
stage()
File "/usr/local/lib/python2.7/site-packages/numba/compiler.py", line 644, in stage_nopython_backend
self._backend(lowerfn, objectmode=False)
File "/usr/local/lib/python2.7/site-packages/numba/compiler.py", line 599, in _backend
lowered = lowerfn()
File "/usr/local/lib/python2.7/site-packages/numba/compiler.py", line 586, in backend_nopython_mode
self.flags)
File "/usr/local/lib/python2.7/site-packages/numba/compiler.py", line 882, in native_lowering_stage
lower.lower()
File "/usr/local/lib/python2.7/site-packages/numba/lowering.py", line 135, in lower
self.lower_normal_function(self.fndesc)
File "/usr/local/lib/python2.7/site-packages/numba/lowering.py", line 176, in lower_normal_function
entry_block_tail = self.lower_function_body()
File "/usr/local/lib/python2.7/site-packages/numba/lowering.py", line 201, in lower_function_body
self.lower_block(block)
File "/usr/local/lib/python2.7/site-packages/numba/lowering.py", line 216, in lower_block
self.lower_inst(inst)
File "/usr/local/Cellar/python/2.7.13_1/Frameworks/Python.framework/Versions/2.7/lib/python2.7/contextlib.py", line 35, in __exit__
self.gen.throw(type, value, traceback)
File "/usr/local/lib/python2.7/site-packages/numba/errors.py", line 265, in new_error_context
six.reraise(type(newerr), newerr, sys.exc_info()[2])
File "/usr/local/lib/python2.7/site-packages/numba/errors.py", line 259, in new_error_context
yield
File "/usr/local/lib/python2.7/site-packages/numba/lowering.py", line 216, in lower_block
self.lower_inst(inst)
File "/usr/local/lib/python2.7/site-packages/numba/lowering.py", line 305, in lower_inst
return self.lower_setitem(inst.target, inst.index_var, inst.value, signature)
File "/usr/local/lib/python2.7/site-packages/numba/lowering.py", line 390, in lower_setitem
signature.args[2])
File "/usr/local/lib/python2.7/site-packages/numba/targets/base.py", line 648, in cast
"Cannot cast %s to %s: %s" % (fromty, toty, val))
LoweringError: Cannot cast none to float64: %".117" = load i8*, i8** %"$0.10"
File "<ipython-input-52-1ddc111374d6>", line 13
[1] During: lowering "result[0] = $0.10" at <ipython-input-52-1ddc111374d6> (13)
Failed at nopython (nopython mode backend)
Cannot cast none to float64: %".117" = load i8*, i8** %"$0.10"
File "<ipython-input-52-1ddc111374d6>", line 13
[1] During: lowering "result[0] = $0.10" at <ipython-input-52-1ddc111374d6> (13)
LoweringErrorTraceback (most recent call last)
<ipython-input-52-1ddc111374d6> in <module>()
15 return LowLevelCallable(wrapped.ctypes)
16
---> 17 @jit_filter_function
18 def fmin(values):
19 result = np.inf
<ipython-input-52-1ddc111374d6> in jit_filter_function(filter_function)
8 jitted_function = numba.jit(filter_function, nopython=True)
9
---> 10 @cfunc(intc(CPointer(float64), intp, CPointer(float64), voidptr))
11 def wrapped(values_ptr, len_values, result, data):
12 values = carray(values_ptr, (len_values,), dtype=float64)
/usr/local/lib/python2.7/site-packages/numba/decorators.pyc in wrapper(func)
251 if cache:
252 res.enable_caching()
--> 253 res.compile()
254 return res
255
/usr/local/lib/python2.7/site-packages/numba/ccallback.pyc in compile(self)
65 cres = self._cache.load_overload(self._sig, self._targetdescr.target_context)
66 if cres is None:
---> 67 cres = self._compile_uncached()
68 self._cache.save_overload(self._sig, cres)
69 else:
/usr/local/lib/python2.7/site-packages/numba/ccallback.pyc in _compile_uncached(self)
78
79 # Compile native function
---> 80 cres = self._compiler.compile(sig.args, sig.return_type)
81 assert not cres.objectmode # disabled by compiler above
82 fndesc = cres.fndesc
/usr/local/lib/python2.7/site-packages/numba/dispatcher.pyc in compile(self, args, return_type)
78 impl,
79 args=args, return_type=return_type,
---> 80 flags=flags, locals=self.locals)
81 # Check typing error if object mode is used
82 if cres.typing_error is not None and not flags.enable_pyobject:
/usr/local/lib/python2.7/site-packages/numba/compiler.pyc in compile_extra(typingctx, targetctx, func, args, return_type, flags, locals, library)
761 pipeline = Pipeline(typingctx, targetctx, library,
762 args, return_type, flags, locals)
--> 763 return pipeline.compile_extra(func)
764
765
/usr/local/lib/python2.7/site-packages/numba/compiler.pyc in compile_extra(self, func)
358 self.lifted = ()
359 self.lifted_from = None
--> 360 return self._compile_bytecode()
361
362 def compile_ir(self, func_ir, lifted=(), lifted_from=None):
/usr/local/lib/python2.7/site-packages/numba/compiler.pyc in _compile_bytecode(self)
720 """
721 assert self.func_ir is None
--> 722 return self._compile_core()
723
724 def _compile_ir(self):
/usr/local/lib/python2.7/site-packages/numba/compiler.pyc in _compile_core(self)
707
708 pm.finalize()
--> 709 res = pm.run(self.status)
710 if res is not None:
711 # Early pipeline completion
/usr/local/lib/python2.7/site-packages/numba/compiler.pyc in run(self, status)
244 # No more fallback pipelines?
245 if is_final_pipeline:
--> 246 raise patched_exception
247 # Go to next fallback pipeline
248 else:
LoweringError: Caused By:
Traceback (most recent call last):
File "/usr/local/lib/python2.7/site-packages/numba/compiler.py", line 238, in run
stage()
File "/usr/local/lib/python2.7/site-packages/numba/compiler.py", line 644, in stage_nopython_backend
self._backend(lowerfn, objectmode=False)
File "/usr/local/lib/python2.7/site-packages/numba/compiler.py", line 599, in _backend
lowered = lowerfn()
File "/usr/local/lib/python2.7/site-packages/numba/compiler.py", line 586, in backend_nopython_mode
self.flags)
File "/usr/local/lib/python2.7/site-packages/numba/compiler.py", line 882, in native_lowering_stage
lower.lower()
File "/usr/local/lib/python2.7/site-packages/numba/lowering.py", line 135, in lower
self.lower_normal_function(self.fndesc)
File "/usr/local/lib/python2.7/site-packages/numba/lowering.py", line 176, in lower_normal_function
entry_block_tail = self.lower_function_body()
File "/usr/local/lib/python2.7/site-packages/numba/lowering.py", line 201, in lower_function_body
self.lower_block(block)
File "/usr/local/lib/python2.7/site-packages/numba/lowering.py", line 216, in lower_block
self.lower_inst(inst)
File "/usr/local/Cellar/python/2.7.13_1/Frameworks/Python.framework/Versions/2.7/lib/python2.7/contextlib.py", line 35, in __exit__
self.gen.throw(type, value, traceback)
File "/usr/local/lib/python2.7/site-packages/numba/errors.py", line 265, in new_error_context
six.reraise(type(newerr), newerr, sys.exc_info()[2])
File "/usr/local/lib/python2.7/site-packages/numba/errors.py", line 259, in new_error_context
yield
File "/usr/local/lib/python2.7/site-packages/numba/lowering.py", line 216, in lower_block
self.lower_inst(inst)
File "/usr/local/lib/python2.7/site-packages/numba/lowering.py", line 305, in lower_inst
return self.lower_setitem(inst.target, inst.index_var, inst.value, signature)
File "/usr/local/lib/python2.7/site-packages/numba/lowering.py", line 390, in lower_setitem
signature.args[2])
File "/usr/local/lib/python2.7/site-packages/numba/targets/base.py", line 648, in cast
"Cannot cast %s to %s: %s" % (fromty, toty, val))
LoweringError: Cannot cast none to float64: %".117" = load i8*, i8** %"$0.10"
File "<ipython-input-52-1ddc111374d6>", line 13
[1] During: lowering "result[0] = $0.10" at <ipython-input-52-1ddc111374d6> (13)
Failed at nopython (nopython mode backend)
Cannot cast none to float64: %".117" = load i8*, i8** %"$0.10"
File "<ipython-input-52-1ddc111374d6>", line 13
[1] During: lowering "result[0] = $0.10" at <ipython-input-52-1ddc111374d6> (13)
Thanks a lot for posting these recipes. I am trying to get your jit_filter_function
decorator to work, but I get the same error as in one of the comments on your blog post
:
ValueError: Invalid scipy.LowLevelCallable signature "long (double *, longlong, double *, void *)". Expected one of: ['int (double *, intptr_t, double *, void *)', 'int (double *, npy_intp, double *, void *)', 'int (double *, long long, double *, void *)']
This is with Python 3.6 on Windows and
>>> numba.__version__
'0.35.0+10.g143f70e'
>>> scipy.__version__
'0.19.1'
I have tried to modify this line
Line 11 in 576d70c
scipy.LowLevelCallable
likes. What am I missing?Hello! First I'd like to say this decorator has been great to work with, really appreciate jit_filter_function. I'm running into an error that pops up when adding the 'ddof' argument to np.nanstd within the filter function.
This code runs without flaw
@jit_filter_function
def fstd(values):
values[values == 0] = np.nan
result = np.nanstd(values)
return result
std = generic_filter(<2d_numpy_array>, fstd, footprint=np.ones((5, 5)))
However, adding the ddof argument like this
@jit_filter_function
def fstd(values):
values[values == 0] = np.nan
result = np.nanstd(values, ddof=1)
return result
std = generic_filter(<2d_numpy_array>, fstd, footprint=np.ones((5, 5)))
Throws this:
Traceback (most recent call last):
File "C:/Users/jbrown/AppData/Roaming/JetBrains/PyCharmCE2021.1/scratches/hr_class_master.py", line 301, in <module>
main()
File "C:\Users\jbrown\AppData\Local\Programs\Python\Python38\lib\site-packages\memory_profiler.py", line 1186, in wrapper
val = prof(func)(*args, **kwargs)
File "C:\Users\jbrown\AppData\Local\Programs\Python\Python38\lib\site-packages\memory_profiler.py", line 759, in f
return func(*args, **kwds)
File "C:/Users/jbrown/AppData/Roaming/JetBrains/PyCharmCE2021.1/scratches/hr_class_master.py", line 149, in main
def fstd(values):
File "C:\Users\jbrown\AppData\Local\Programs\Python\Python38\lib\site-packages\llc\ndimage.py", line 48, in jit_filter_function
def wrapped(values_ptr, len_values, result, data):
File "C:\Users\jbrown\AppData\Local\Programs\Python\Python38\lib\site-packages\numba\core\decorators.py", line 282, in wrapper
res.compile()
File "C:\Users\jbrown\AppData\Local\Programs\Python\Python38\lib\site-packages\numba\core\compiler_lock.py", line 35, in _acquire_compile_lock
return func(*args, **kwargs)
File "C:\Users\jbrown\AppData\Local\Programs\Python\Python38\lib\site-packages\numba\core\ccallback.py", line 67, in compile
cres = self._compile_uncached()
File "C:\Users\jbrown\AppData\Local\Programs\Python\Python38\lib\site-packages\numba\core\ccallback.py", line 81, in _compile_uncached
return self._compiler.compile(sig.args, sig.return_type)
File "C:\Users\jbrown\AppData\Local\Programs\Python\Python38\lib\site-packages\numba\core\dispatcher.py", line 129, in compile
raise retval
File "C:\Users\jbrown\AppData\Local\Programs\Python\Python38\lib\site-packages\numba\core\dispatcher.py", line 139, in _compile_cached
retval = self._compile_core(args, return_type)
File "C:\Users\jbrown\AppData\Local\Programs\Python\Python38\lib\site-packages\numba\core\dispatcher.py", line 152, in _compile_core
cres = compiler.compile_extra(self.targetdescr.typing_context,
File "C:\Users\jbrown\AppData\Local\Programs\Python\Python38\lib\site-packages\numba\core\compiler.py", line 716, in compile_extra
return pipeline.compile_extra(func)
File "C:\Users\jbrown\AppData\Local\Programs\Python\Python38\lib\site-packages\numba\core\compiler.py", line 452, in compile_extra
return self._compile_bytecode()
File "C:\Users\jbrown\AppData\Local\Programs\Python\Python38\lib\site-packages\numba\core\compiler.py", line 520, in _compile_bytecode
return self._compile_core()
File "C:\Users\jbrown\AppData\Local\Programs\Python\Python38\lib\site-packages\numba\core\compiler.py", line 499, in _compile_core
raise e
File "C:\Users\jbrown\AppData\Local\Programs\Python\Python38\lib\site-packages\numba\core\compiler.py", line 486, in _compile_core
pm.run(self.state)
File "C:\Users\jbrown\AppData\Local\Programs\Python\Python38\lib\site-packages\numba\core\compiler_machinery.py", line 368, in run
raise patched_exception
File "C:\Users\jbrown\AppData\Local\Programs\Python\Python38\lib\site-packages\numba\core\compiler_machinery.py", line 356, in run
self._runPass(idx, pass_inst, state)
File "C:\Users\jbrown\AppData\Local\Programs\Python\Python38\lib\site-packages\numba\core\compiler_lock.py", line 35, in _acquire_compile_lock
return func(*args, **kwargs)
File "C:\Users\jbrown\AppData\Local\Programs\Python\Python38\lib\site-packages\numba\core\compiler_machinery.py", line 311, in _runPass
mutated |= check(pss.run_pass, internal_state)
File "C:\Users\jbrown\AppData\Local\Programs\Python\Python38\lib\site-packages\numba\core\compiler_machinery.py", line 273, in check
mangled = func(compiler_state)
File "C:\Users\jbrown\AppData\Local\Programs\Python\Python38\lib\site-packages\numba\core\typed_passes.py", line 105, in run_pass
typemap, return_type, calltypes, errs = type_inference_stage(
File "C:\Users\jbrown\AppData\Local\Programs\Python\Python38\lib\site-packages\numba\core\typed_passes.py", line 83, in type_inference_stage
errs = infer.propagate(raise_errors=raise_errors)
File "C:\Users\jbrown\AppData\Local\Programs\Python\Python38\lib\site-packages\numba\core\typeinfer.py", line 1086, in propagate
raise errors[0]
numba.core.errors.TypingError: Failed in nopython mode pipeline (step: nopython frontend)
Failed in nopython mode pipeline (step: nopython frontend)
No implementation of function Function(<function nanstd at 0x000001BA5B414F70>) found for signature:
>>> nanstd(array(float64, 1d, C), ddof=Literal[int](1))
There are 2 candidate implementations:
- Of which 2 did not match due to:
Overload in function 'np_nanstd': File: numba\np\arraymath.py: Line 1231.
With argument(s): '(array(float64, 1d, C), ddof=int64)':
Rejected as the implementation raised a specific error:
TypingError: got an unexpected keyword argument 'ddof'
raised from C:\Users\jbrown\AppData\Local\Programs\Python\Python38\lib\site-packages\numba\core\typing\templates.py:791
During: resolving callee type: Function(<function nanstd at 0x000001BA5B414F70>)
During: typing of call at C:/Users/jbrown/AppData/Roaming/JetBrains/PyCharmCE2021.1/scratches/hr_class_master.py (151)
File "hr_class_master.py", line 151:
def fstd(values):
<source elided>
values[values == 0] = np.nan
result = np.nanstd(values, ddof=1)
^
During: resolving callee type: type(CPUDispatcher(<function main.<locals>.fstd at 0x000001BA0DBF04C0>))
During: typing of call at C:\Users\jbrown\AppData\Local\Programs\Python\Python38\lib\site-packages\llc\ndimage.py (50)
During: resolving callee type: type(CPUDispatcher(<function main.<locals>.fstd at 0x000001BA0DBF04C0>))
During: typing of call at C:\Users\jbrown\AppData\Local\Programs\Python\Python38\lib\site-packages\llc\ndimage.py (50)
File "..\..\..\..\Local\Programs\Python\Python38\lib\site-packages\llc\ndimage.py", line 50:
def wrapped(values_ptr, len_values, result, data):
<source elided>
values = carray(values_ptr, (len_values,), dtype=float64)
result[0] = jitted_function(values)
^
Is this functionality to be added, or error with the code itself? I'm using Python 3.8 on Windows
@cfunc(intc(CPointer(float64), intp, CPointer(float64), voidptr))
def function(values_ptr, len_values, result, data):
...
weights = carray(data, (1,), double)[0]
...
weights = [0.6, 0.8, 0.4]
seq = ctypes.c_double * len(weights)
arr = seq(*weights)
ptr = ctypes.cast(ctypes.pointer(arr), ctypes.c_void_p)
ndi.generic_filter(image, LowLevelCallable(function.ctypes, ptr), footprint=footprint)
Source:
scipy doc
Users of numerical integration don't have a nice lowlevelcallable interface with Numba right now. See:
See https://docs.scipy.org/doc/scipy/reference/ccallback.html
See https://github.com/napari/napari, https://github.com/napari/magicgui, and https://github.com/scikit-image/scikit-image for example configurations.
In #11, @trhallam added some basic tests (๐!). We can be more elaborate:
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.