Alternative for interp1 for fast computation

I am working with matrices of size (1000 x 1000) and have a function that involves log and tanh functions. To avoid the computational complexity I want to store the results in the form of a lookup table and access them directly without performing log(tanh(abs(x))) everytime. I am using interp1 function to do this, but this is very slow. Could someone please help me speed up the below function?
range = 0:0.1:6;
data = log(tanh(abs(range)));
value = [0 0.1 0.2105];
out = interp1(range,data,value,'nearest');

5 Comments

why do you say it's slow?
Consider a matrix of size (1000 x 1000), and I want to compute log(tanh(abs(x))) for each element of the matrix. The elements are changing constantly between 0 to 6, and performing this for huge matrices wil definitely take longer duration. So I have precomputed the data and stored it in a lookup table, so that it can skip mathematical computation of log(tanh(abs(x))) and directly fetch the data. However when I try to access the data from the precomputed lookup table using interp1 function, the computation time is still longer. How can I speed up the program execution? Is there any alternative way to do this?
Stephen23
Stephen23 on 26 Nov 2018
Edited: Stephen23 on 26 Nov 2018
"Is there any alternative way to do this?"
Probably by just calling log(tanh(abs(x))) directly.
I doubt that you will find many methods that are more efficient than calls to highly optimized log, tanh, and abs. Is this line really the major bottle-neck in your code?
It is not clear why you think that interpolation should be faster than these numeric oeprations.
Yes the FEX https://www.mathworks.com/matlabcentral/fileexchange/28376-faster-linear-interpolation is definitely fastest solution ... based on matlab scripts (without MEX).

Sign in to comment.

 Accepted Answer

Jan
Jan on 27 Nov 2018
Edited: Jan on 27 Nov 2018
You can try this C-Mex function for a linear interpolation: https://www.mathworks.com/matlabcentral/fileexchange/25463-scaletime
range = 0:0.1:6;
data = log(tanh(range)); % No abs() needed for the given range
value = linspace(0, 6, 1e6); % Equivalent to 1000x1000 matrix
tic;
index = value * (numel(range)-1) / 6 + 1;
out = ScaleTime(data, index);
toc
tic
out2 = log(tanh(value));
toc

7 Comments

This works fine when the range is non-negative, could you please advise what needs to be done for range = -6:0.1:6
And do you want to apply abs() again or to get the complex results?
Yes I want to apply the abs() again.
Then:
index = abs(value) * (numel(range)-1) / 6 + 1;
The index equation is right only when range = 0:0.1:6, however this is giving wrong index value for range between -6:0.1:6
range = -6:0.1:6;
data = -log(tanh(abs(range))); % All the elements are non-negative
value = [0.1 0.5];
tic;
index = abs(value) * (numel(range)-1) / 6 + 1;
out = ScaleTime(data, index);
toc
step = 0.1;
index = floor((value - range(1))/step) + 1;
range = 0.1:6;
data = -log(tanh(range));
value = [-0.5, 0.5];
index = abs(value) * (numel(range)-1) / 6 + 1;
out = ScaleTime(data, index);
You need to create the look-up-table data only for the positive inputs, if you provide positive inputs only.

Sign in to comment.

More Answers (1)

range = 0:0.1:6;
data = log(tanh(abs(range)))
edges = [-Inf, 0.5*(range(1:end-1)+range(2:end)), Inf]; % this is done once
value = linspace(0,6,1024);
% This replace INTERP1
[~,~,loc]=histcounts(value,edges);
out = data(loc)

2 Comments

This one is definitely faster than interp1 function but still not better than directly using the log(tanh(abs(x))) function.
I just tried the below sample code to check the speed.
tic;
for i = 1:1000000
range = 0:0.1:6;
data = -log(tanh(abs(range)));
value = [0 0.1 0.2105];
out1 = interp1(range,data,value,'nearest');
end
toc;
tic;
for i = 1:1000000
range = 0:0.1:6;
data = -log(tanh(abs(range)));
edges = [-Inf, 0.5*(range(1:end-1)+range(2:end)), Inf]; % this is done once
value = [0 0.1 0.2105];
% This replaces INTERP1
[~,~,loc]=histcounts(value,edges);
out2 = data(loc);
end
toc;
tic;
for i = 1:1000000
value = [0 0.1 0.2105];
out3 = -log(tanh(abs(range)));
end
toc;
Sorry you timing is flawed for 2 reasons:
  • includes the non-relevant parts
  • too small data therefore overhead of histcounts and interp1 will kills any advantage

Sign in to comment.

Asked:

on 26 Nov 2018

Commented:

on 28 Jul 2021

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!