fast evaluation of x(k+1) = x(k)*e(k)
Show older comments
Is there any special trick how to evaluate fast this recurrent formula:
x(1) = x0
x(k+1) = x(k)*e(k), k= 1,2, ...N-1
where N = length(x) = length(e)+1
e ... known vector
I mean faster then standard for-loop:
x(1) = x0;
for k = 1:N-1
x(k+1) = x(k)*e(k);
end
Answers (1)
Dyuman Joshi
on 8 Jan 2024
Edited: Dyuman Joshi
on 8 Jan 2024
Timings of for loop with preallocation and vectorization are comparable for a large number of elements -
x = 69420;
N = 5e6;
e = rand(1,N);
F1 = @() forloop(x, e, N);
F2 = @() forlooppre(x, e, N);
F3 = @() vectorization(x, e);
fprintf('Time taken by for loop without preallocation for a vector with %g elements = %f seconds', N, timeit(F1))
fprintf('Time taken by for loop with preallocation approach for a vector with %g elements = %f seconds', N, timeit(F2))
fprintf('Time taken by vectorized approach for a vector with %g elements = %f seconds', N, timeit(F3))
y1 = F1();
y2 = F2();
y3 = F3();
%Comparing results using tolerance
all(abs(y1-y2)<1e-10 & abs(y2-y3)<1e-10)
%% Function definitions
%For loop without preallocation
function x = forloop(x, e, N)
for k=1:N
x(k+1) = x(k)*e(k);
end
end
%For loop without preallocation
function x = forlooppre(x, e, N)
%preallocation
x = [x zeros(1, N)];
for k=1:N-1
x(k+1) = x(k)*e(k);
end
end
%Vectorized approach
function x = vectorization(x, e)
x = x.*[1 cumprod(e)];
end
10 Comments
Matt J
on 8 Jan 2024
Probably due to the cumprod overhead.
No, probably due to the overhead of horzcat.
I brought the concatenation out of the function and ran the timings, it looks like horzcat is the culprit for overhead -
x = 69420;
N = 5e6;
e = rand(1,N);
E = [1 e];
F1 = @() forloop(x, e, N);
F2 = @() forlooppre(x, e, N);
F3 = @() vectorization(x, E);
fprintf('Time taken by for loop without preallocation for a vector with %g elements = %f seconds', N, timeit(F1))
fprintf('Time taken by for loop with preallocation for a vector with %g elements = %f seconds', N, timeit(F2))
fprintf('Time taken by vectorized approach for a vector with %g elements = %f seconds', N, timeit(F3))
y1 = F1();
y2 = F2();
y3 = F3();
%Comparing results using tolerance
all(abs(y1-y2)<1e-10 & abs(y2-y3)<1e-10)
%% Function definitions
%For loop without preallocation
function x = forloop(x, e, N)
for k=1:N
x(k+1) = x(k)*e(k);
end
end
%For loop without preallocation
function x = forlooppre(x, e, N)
%preallocation
x = [x zeros(1, N)];
for k=1:N-1
x(k+1) = x(k)*e(k);
end
end
%Vectorized approach
function y = vectorization(x, e)
y = x.*cumprod(e);
end
Michal
on 8 Jan 2024
Seems to be working correctly here -
x = 6942000;
N = 5e6;
e = rand(1,N);
E = [1 e];
F1 = @() forloop(x, e, N);
F2 = @() forlooppre(x, e, N);
F3 = @() vectorization(x, E);
fprintf('Time taken by for loop without preallocation for a vector with %g elements = %f seconds', N, timeit(F1))
fprintf('Time taken by for loop with preallocation for a vector with %g elements = %f seconds', N, timeit(F2))
fprintf('Time taken by vectorized approach for a vector with %g elements = %f seconds', N, timeit(F3))
y1 = F1();
y2 = F2();
y3 = F3();
%Comparing results using tolerance
all(abs(y1-y2)<1e-10 & abs(y2-y3)<1e-10)
%% Function definitions
%For loop without preallocation
function x = forloop(x, e, N)
for k=1:N
x(k+1) = x(k)*e(k);
end
end
%For loop without preallocation
function x = forlooppre(x, e, N)
%preallocation
x = [x zeros(1, N)];
for k=1:N-1
x(k+1) = x(k)*e(k);
end
end
%Vectorized approach
function x = vectorization(x, e)
x = x.*cumprod(e);
end
Michal
on 9 Jan 2024
The code above was ran on
ver
Linux and MATLAB Version R2023b Update 5
Categories
Find more on Loops and Conditional Statements in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!