Methods to Speed-up fsolve

75 views (last 30 days)
Carlos Acasuso
Carlos Acasuso on 2 Dec 2020
Edited: Matt J on 2 Dec 2020
Hello,
I am attempting to speed-up a solution to a system of equations.
I have already made huge progress by rewriting my problem to use fsolve, instead of solving symbolically using vpasolve, where I have gone down from around 0.3s to now solving in 0.0045s.
I am solving this system in a for loop for 1,000 data points, so it is running in around 4.5s.
My idea is to make it as efficient as possible, as the data files I am planning to execute could range to >100,000 data points.
For this, I have done background reading on using Parallel Computing such as parfor, parfeval or spmd to try use more of my available computer power and bring the execution time down by a few folds, if possible.
tic
for i = 1:1000
LDamperFL_st = string(LDamperFL(i));
LDamperFR_st = string(LDamperFR(i));
SteerRackTravel_st = string(SteerRackTravel(i));
f = replace(f,["LDamperFL","LDamperFR","xSteerRack"], [LDamperFL_st, LDamperFR_st, SteerRackTravel_st]);
Sfun_R = str2func(f);
Solution(:,i) = fsolve(Sfun_R, rand(14,1), opts);
end
toc
The solution output (Solution) consists of a 14x1000 double array.
I have attempted to use parfor, but the solution takes significantly longer (15.2s for a loop of 1000 data points, 0.0152s per solution)
I have attempted to use parforeval:
tic
[Solution] = parfeval(ResolveKin, 1, LDamperFL, LDamperFR, SteerRackTravel, f, opts);
toc
where my function is:
function [KinSol] = ResolveKin(LDamperFL, LDamperFR, SteerRackTravel, f, opts)
for i = 1:1000
LDamperFL_st = string(LDamperFL(i));
LDamperFR_st = string(LDamperFR(i));
SteerRackTravel_st = string(SteerRackTravel(i));
f = replace(f,["LDamperFL","LDamperFR","xSteerRack"], [LDamperFL_st, LDamperFR_st, SteerRackTravel_st]);
Sfun_R = str2func(f);
KinSol(:,i) = fsolve(Sfun_R, rand(14,1), opts);
end
end
But I get the following error:
Not enough input arguments.
I have also attempted to us spmd by I get an error:
Warning: Saving Composites is not supported.
For spmd, I believe I am just not coding it correctly, but I struggle to figure out how to do this.
Finally, I have also attempted to set my fsolve "opts" as shown below, in an attempt to run fsolve in parallel and test if this helps to run the loop quicker.
opts = optimoptions('fsolve', 'Display', 'none', 'UseParallel',true);
But if I do so it takes much longer to execute my 1000 data points loop, taking 318s (0.318s per soltuion)
Thank you very much for your help, very much appreciated.
I could share my full script privately if it helped.
Regards,
Carlos

Accepted Answer

Matt J
Matt J on 2 Dec 2020
Edited: Matt J on 2 Dec 2020
If the solutions are expected to evolve continuously, it can save time to use the last result as the initial guess for the next one. Also, pre-allocating KinSol should also speed things up.
function [KinSol] = ResolveKin(LDamperFL, LDamperFR, SteerRackTravel, f, opts)
x0=rand(14,1);%<---
KinSol=nan(14,1000); %<---
for i = 1:size(KinSol,2) %<---
LDamperFL_st = string(LDamperFL(i));
LDamperFR_st = string(LDamperFR(i));
SteerRackTravel_st = string(SteerRackTravel(i));
f = replace(f,["LDamperFL","LDamperFR","xSteerRack"], [LDamperFL_st, LDamperFR_st, SteerRackTravel_st]);
Sfun_R = str2func(f);
x0 = fsolve(Sfun_R, x0, opts);%<---
KinSol(:,i) = x0;%<---
end
end
Aside from that, I do not understand why you are updating f in every iteration of the loop. After the first iteration, it doesn't look like f will change at all. If you are doing this just to substitute new sets of numeric data into the formula for f, there are indeed more efficient ways to accomplish this.
  1 Comment
Carlos Acasuso
Carlos Acasuso on 2 Dec 2020
Edited: Carlos Acasuso on 2 Dec 2020
Thank you very much Matt J, just looking into your tips I'll let you know soon how I get on.
Just to answer your last question, it is indeed to subsititute the values of LDamperFL, LDamperFR, SteerRackTravel into my function, as the function (i.e. the system of 14 equations) needs to be solved for every instance when these three variables change, and these are just pre-stored in single-vector arrays.
It is then that I need to solve this problem in a loop for the length of my LDamperFL, LDamperFR, SteerRackTravel arrays (these three are all same length).
Hope that is clearer. I will also investigate more efficient ways of doing this as you've linked.

Sign in to comment.

More Answers (0)

Categories

Find more on Parallel for-Loops (parfor) in Help Center and File Exchange

Products


Release

R2019b

Community Treasure Hunt

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

Start Hunting!