Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I efficiently replace a function with a lookup?

I am trying to increase the speed of code that operates on large datasets. I need to perform the function out = sinc(x), where x is a 2048-by-37499 matrix of doubles. This is very expensive and is the bottleneck of my program (even when computed on the GPU).

I am looking for any solution which improves the speed of this operation. I expect that this might be achieved by pre-computing a vector LookUp = sinc(y) where y is the vector y = min(min(x)):dy:max(max(x)), i.e. a vector spanning the whole range of expected x elements.

How can I efficiently generate an approximation of sinc(x) from this LookUp vector?

I need to avoid generating a three dimensional array, since this would consume more memory than I have available.

Here is a test for the interp1 solution:

a = -15;
b = 15;
rands = (b-a).*rand(1024,37499) + a;

sincx = -15:0.000005:15;
sincy = sinc(sincx);

tic
res1 = interp1(sincx,sincy,rands);
toc

tic
res2 = sinc(rands);
toc'

sincx = gpuArray(sincx);
sincy = gpuArray(sincy);
r = gpuArray(rands);

tic
r = interp1(sincx,sincy,r);
toc

r = gpuArray(rands);

tic
r = sinc(r);
toc

Elapsed time is 0.426091 seconds.
Elapsed time is 0.472551 seconds.
Elapsed time is 0.004311 seconds.
Elapsed time is 0.130904 seconds.

Corresponding to CPU interp1, CPU sinc, GPU interp1, GPU sinc respectively

like image 357
B. Thomas Avatar asked Nov 04 '15 14:11

B. Thomas


2 Answers

Not sure I understood completely your problem. But once you have LookUp = sinc(y) you can use the Matlab function interp1

out = interp1(y,LookUp,x)

where x can be a matrix of any size

like image 66
alexmogavero Avatar answered Oct 12 '22 16:10

alexmogavero


I came to the conclusion, that your code can not be improved significantly. The fastest possible lookup table is based on simple indexing. For a performance test, lets just perform the test based on random data:

%test data:
x=rand(2048,37499);
%relevant code:
out = sinc(x);

Now the lookup based on integer indices:

a=min(x(:));
b=max(x(:));
n=1000;
x2=round((x-a)/(b-a)*(n-1)+1);
lookup=sinc(1:n);
out2=lookup(x2);

Regardless of the size of the lookup table or the input data, the last lines in both code blocks take roughly the same time. Having sinc evaluate roughly as fast as a indexing operation, I can only assume that it is already implemented using a lookup table.

like image 37
Daniel Avatar answered Oct 12 '22 15:10

Daniel