1

I have used Numba for speeding up my code. It works great and provides a 2-3x factor improvement. However the major time spent in my code (about 90%) is in the scipy quad integration and interpolation (linear and Cubic Spline). I do these integrations several hundred times so I figured this is something that Numba can boost. It does not look like Numba supports these? I heard of Numba-Scipy which is suppose to make Numba recognize Scipy, but this still does not seem to work. Is there a way to make Numba optimize my integrations/interpolations?

  • 1
    Can you provide what you've tried so far and the error you're getting? – Kyle Parsons Jul 22 '21 at 22:01
  • 1
    `scipy` is a set of unconnected packages. Last I looked the `numba-scipy` only 'knew' about the 'special-functons' module. `quad` is basically an iterative function, calling your function a number of times (something like 20 at a minumum). You can improve its speed by making your function as fast as possible, but otherwise there isn't much you can do. Some of the integrate/optimize functions have compiled components, but they are still limited by the time it takes to call your own function(s). No one compiles your code or turns the whole process into a compiled package. – hpaulj Jul 22 '21 at 22:13
  • Please provide a working example with realistic inputs (could be random numbers). Usually the way to go is to create a LowLevel callable, which provides a significant speedup. But Linear or Cubic Spline Classes are not supported out of the box. If it's only the evaluation of splines, this should be implementable in Numba. Alternatives are LowLevel Callables in C or Cython, but with the same isssues. eg. an example using np.interpolate and low-level callables. https://stackoverflow.com/a/58561573/4045774 – max9111 Jul 23 '21 at 07:27

1 Answers1

5

Just wrote a wrapper to cquadpack called NumbaQuadpack which should do what you want: https://github.com/Nicholaswogan/NumbaQuadpack . cquadpack is C version of Quadpack, which is what scipy.integrate.quad uses.

from NumbaQuadpack import quadpack_sig, dqags
import numpy as np
import numba as nb
import timeit

@nb.cfunc(quadpack_sig)
def f(x, data):
    return x**2 + 2 + np.log(x)
funcptr = f.address
a = 0
b = 1
sol, abserr, success = dqags(funcptr, a, b)
print(sol) # definite integral solution

# test speed
@nb.njit()
def timetest_nb():
    sol, abserr, success = dqags(funcptr, a, b)
timetest_nb()
n_time=10000
print(timeit.Timer(timetest_nb).timeit(number=n_time)/n_time) 

On my computer, this small integral takes 4.2 µs, and when I do the equivalent thing with scipy.integrate.quad, it takes 68.1 µs.

For interpolation, just use np.interp (1d interpolation). It can be used from within numba-jitted functions.

In general, any C/C++ or fortran code can be wrapped with ctypes, and called from within numba-jitted functions.

nicholaswogan
  • 631
  • 6
  • 13
  • Did you also find a way to pass multiple inputs (numpy.ndarrays, floats, int64) to your imlementation via double func(double x, void *user_data)? Something more elegant than doing this https://stackoverflow.com/a/58561573/4045774 – max9111 Jul 27 '21 at 13:38
  • @max9111 no I did not. I just hard-coded in a float64 array. Would be great if numba had a struct, which you could get a pointer to, then dereference from within a jitted function... Is this possible? – nicholaswogan Jul 27 '21 at 15:37
  • Oh I see that this is sort-of what you managed to do in that other SO post. Cool. It is a bit clumsy but it works I guess. – nicholaswogan Jul 27 '21 at 21:27
  • @nicholaswogan, would it be possible for you to write something similar for scipy's ``interpolate.RectBivariateSpline`` function, please? I am training such a ``RectBivariateSpline`` object, speed is alright for this step, however I query the trained interpolator for 10^7 times, and it takes 1 hour or so ... so querying a trained 2D interpolator is my problem. – velenos14 Nov 29 '21 at 16:01
  • 1
    @velenos14 , A faster wrapper for `interpolate.RectBivariateSpline` is possible. Its just a wrapper to the [Fitpack](https://github.com/scipy/scipy/tree/master/scipy/interpolate/fitpack) fortran library. You could make it. Follow the structure of one of the packages I have made. For example https://github.com/Nicholaswogan/NumbaMinpack – nicholaswogan Nov 29 '21 at 18:46
  • Ok, I will give it a try. I am not that experienced as you and never did something similar. – velenos14 Nov 29 '21 at 19:08