New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
better jitted interface to multilinear interpolation #22
Comments
I think in the long term I like the idea of using |
That sounds fine, although there might be some confusion as to what Also, if you allow for the same interface for irregular grids, then I wonder if it's not better to just coordinate on users always supplying the actual grids. If the routine in question uses logic that expects a regular grid, then this can either be tested at run time or identified in the function name (e.g., |
My idea was that the grid could be either regular, or irregular, but that they would correspond to different numba types so the appropriate method could be compiled. For instance the two following calls would correspond to different implementations:
Actually, one could define
I am not a big fan of using irregular grids by default: the advantage of cartesian grid is that one doesn't need memory access to figure out the location of a point. The grid never needs to be constructed. In the same spirit detecting whether a grid is regular or not doesn't appeal to me. Two different names would indeed solve the problem. Here I think there is an obvious proposition that could work for you: let's just keep |
That all sounds great. I hear what you are saying about defaulting to regular grids. It makes sense. But I would be glad to have the option pass explicit grids in the lectures, even if they are regular, for simple low dimensional problems. Perhaps @spvdchachan, @chrishyland Let us know if you have thoughts. |
@jstac: with this proposal we'll have both types of grid with one single function call. It would be safe if users don't mix grid types unwillingly. Otherwise, I'm happy to use |
BTW, I started to implement the multilinear interpolation, mostly to try a new approach. So far it doesn't take many types of input, but it can accomodate for even or uneven grids or a mix of them. On 2d interpolation for a 10x10 matrix, interpolating K=1000 times on N=10000 points, I get the following timings:
This is of course not very scientific but seems to indicate that numba does optimize the code reasonaby well (and apparently inlines many functions). |
Hi Pablo,
Amazing work on getting it to run though! |
@chrishyland : thanks for looking at the code.
This is now a very simple function for the compiler. In particular, the exact amount of memory used by these calculations is known in advance and there is no need to allocate an array dynamically. I have not run this code, but I bet it should be faster than the naive implementation (it is this one the naive one?) if evaluated many times. Now there is another nice thing with tuple and numba: defining tuple has essentially zero cost, w.r.t. defining many variables. For instance: doing
or doing
are essentially equivalent for the compiler, hence performance-wise.
When this one is jitted, tmul and smul are replaced literally (inlined) and in a perfect world, the emitted code should have performances similar to the fastest
If you define a 2d array I hope my explanations are clear enough. Don't hesitate if they are not. The code is still a proof of concept. It is inspired by Julia's StaticArrays library which does essentially the same trick but with the ability to define actual arrays instead of tuples of tuples (and also with some help of julia macros). |
@albop This is beautiful. Thank you. You should be freelancing for hedge funds, getting paid millions. (If you decide to go down this route, please buy a yacht and invite me to come sailing.) The interface is really neat and the code is fast. I liked your explanations. Regarding your question "There is some decision to make about the syntax for the point where we evaluate.... The latter seem to be favoured by scipy.interpolate.interp2d", I would also expect the latter and following scipy seems like a good idea. I don't have any suggestions for improvements. Certainly it will accommodate all the needs of the lectures. @chrishyland and @spvdchachan might be able to help with tests, although their classes will be starting back soon... |
Thanks @jstac ! I don't know about the hedge fund, but a small boat is a good idea, and when I get one, you'll be welcome to come sailing and fishing... I'll reorganize the code a little bit and put in place a working version with all the interfaces very soon. Then it would be indeed very useful to check it works in all cases by writing some tests, and write a tiny little bit of documentation. There is just one little issue left... It could be faster. In particular, the regular grid method is still at least 4 times slower than the one already in interpolation.py using code generation. I guess I'll go now for the fastest and easiest path to get the |
Sounds like a good plan. QuantEcon's lectures will provide partial documentation and I can help put together a notebook of examples. |
Currently there are two wrapper functions for multilinear interpolation on regular grids. They are implemented in
splines/multilinear_numba.py
but could be seriously improved, while reusing the same low-level functionsmultilinear_interpolation_xd
andvec_multilinear_interpolation_xd
We could have one jitted, inplace function
mlininterp(a,b,n,y,u,out)
(name is a place holder) where:a
,b
,n
are 1d vectors or tuple of lengthd
(number of dimensions) denoting a cartesian grid (a
andb
are lower and upper bounds,n
number of nodes in each directiond
dimensional arrays with the scalar values to be interpolated at each node of the grid. Or ify
hasd+1
dimensions, then one interpolates vectors instead (y[...,:]
is the vector value at one grid point)u
is 2d array, where each line has the coordinates of a point at which to interpolateout
is a 1d-array ify
is d-dimensional or 2d ify
is (d+1)-dimensional and contains the output.With this inplace function, it is possible to deduce from the dimensions of
y
andout
only which is the value ofd
and whether they
represents scalar or vector values.I wonder what is the best way to write the allocating version
mlininterp(a,b,n,y,u)
in order to detect whether values are scalars or vectors. One could expect a,b,n to be tuples, in which case their type would contain the dimension of the problem. One could have two function names (which is cheating). One could have a different signature likemlinterp(grid,y,u)
wheregrid
would be a tuple of tuples like( (0.0,1.0,10), (-1.0, 1.0, 50) )
. Not all options are mutually exclusive.@jstac: what do you think ?
The text was updated successfully, but these errors were encountered: