In the past, I have rewritten several scipy functions so I can call them from Numba. This is becoming easier with each Numba release due to the growing support for numpy and python functions.
But I am still facing a bottleneck when deep inside the scipy function a function written in fortran is called. In particular, I am trying to rewrite scipy.optimize.root which calls _root_hybr which calls minpack._hybrd
.
The signature of minpack._hybrd
is available as it is a compiled function? Is there an automatic way to use it from a numba njitted
function? If not, how can I do it manually?
1 Like
Hi @hgrecco,
I think the issue here is that the scipy.optimize._minpack
module is a C extension module which unfortunately doesn’t export the symbols you need. i.e.:
$ nm lib/python3.7/site-packages/scipy/optimize/_minpack.cpython-37m-x86_64-linux-gnu.so|grep hybrd
00000000000211e0 d doc_hybrd
00000000000066a0 t hybrd_
0000000000002f80 t minpack_hybrd
the hybrd_
symbol is likely the one from minpack itself, but it’s local only so Numba cannot bind to it.
Normally, if there’s a global symbol, you can just bind to the library with ctypes.CDLL
and then get the address of the symbol and describe the argtypes
/restype
or create a ctypes.CFUNCTYPE
for it and off you go. Example:
import ctypes as ct
DSO = ct.CDLL('libm.so')
fptr_cos = DSO.cos
# describe the function pointer
fptr_cos.argtypes = (ct.c_double,)
fptr_cos.restype = ct.c_double
print(fptr_cos(1.2))
# or bind with a CFUNCTYPE description
fty = ct.CFUNCTYPE(ct.c_double, ct.c_double)
bind = fty(fptr_cos)
print(bind(1.2))
from numba import njit
@njit
def foo(x):
return bind(x), fptr_cos(x)
print(foo(1.2))
If you can get minpack
as a library then the above ctypes
binding could work.
Hope this helps?
Thanks a lot for the reply! It helps.
Would this
serve your needs?
The bindings are through cffi, which numba can handle well.