improving the speed of parallel optimization
Mostrar comentarios más antiguos
Hi, I am trying to optimize in parallel but the speed is increased just slightly by using parfor. Do you have any further recommendations? Thanks!
parfor i = 1:M
options = optimset('MaxFunEvals',Inf,'MaxIter',10,...
'Algorithm','interior-point','Display','iter');
startTime = tic;
[x(:,i),fval(:,i)] = fmincon(@(x)revenue(price(1:N,1),ro,g,eff,x,N,k1,init_s(i),inFlow(:,i),alpha_par(i),b_par(i)),x0(1:2*N,i),A,b(:,i),Aeq,beq(:,i),LB(:,i),UB(:,i),[],options);
time_fmincon_parallel = toc(startTime);
fprintf('Parallel FMINCON optimization takes %g seconds.\n',time_fmincon_parallel);
end
Respuestas (2)
Walter Roberson
el 4 de Jun. de 2018
0 votos
Instead of running the fmincon calls in parallel, try running them in a loop, but using the option UseParallel to allow parallel estimation of the gradient.
Remember, it is common for Parallel processing to be slower than serial, depending on the amount of data to be transferred compared to the amount of work to be done per iteration, and taking into account that non-parallel workers can use the built-in parallelization of some operations on large "enough" matrices by calling into LaPACK / MKL.
9 comentarios
sensation
el 4 de Jun. de 2018
Walter Roberson
el 6 de Jun. de 2018
Generalities:
- if you can rewrite the problem as a linear or quadratic problem, you probably should do that and use an appropriate solver, as there are analytic methods to deal with those
- nonlinear constraints are expensive; avoid them if you can. Fortunately for you, you do not have any
- linear equality constraints are slower than linear inequalities
- When you have a linear equality, examine your code. You might be able to reduce by one or more variables, rewriting the remaining variable internally in the objective function as (constant minus linear sum of the remaining variables). Reducing the number of variables also makes it faster to estimate gradient and hessian as the cost of estimating hessians grows with the square of the number of variables
- Sometimes there are regions where certain variables have no effect on the outcome. It can sometimes make sense to break up the problem into sub-problems with different objective functions that deal only with the regions where the variables are meaningful
- never load() inside your objective function; load first and pass the data in as part of the parameters to the objective function
- Give some thought to vectorizing your objective function. Your objective function will be executed many many times, so you want it to be efficient.
- if you have an efficient function for calculating gradients, then provide it in the options instead of having it estimate the gradients and hessian. But do keep in mind that having an analytic function to calculate the gradients or hessian does not always mean that you should calculate it analytically: getting all of the details right for exact solutions can be computationally expensive. The gradient and hessian estimation that is done is sort of like doing a truncated taylor expansion: because of the truncation it could end being much faster, but on the other hand the effective truncation can lead to some pretty misleading results. If your objective function is somewhat smooth at a macro level then gradient estimation can be enough, but if it has some pretty steep areas then you might need to provide a more analytic estimator.
sensation
el 6 de Jun. de 2018
Walter Roberson
el 6 de Jun. de 2018
We would need to know depth() to be able to answer.
If you have the symbolic toolbox, then what can help is to create a symbolic vector the same of appropriate length and pass it into your objective function, hopefully getting back a symbolic expression for your objective function. Sometimes the result is just ugly messy, but other times the interaction with the inputs turns out to be fairly clean and you can use diff() and gradient() to come up with reasonable functions and then matlabFunction() to create appropriate function handles.
One trick with matlabFunction is to consider using the 'File' output option, which by default enables the optimization option. The symbolic engine then spends a bunch of time doing common sub-expression optimization to come out with a more efficient series of statements to do the calculation. But this process can take a lot of time; if the expression is longer and more complicated then it can take more than an hour, so it is only worth doing if the expression is not complicated or if the objective function will be executed a lot of times.
sensation
el 6 de Jun. de 2018
Walter Roberson
el 6 de Jun. de 2018
About how large is N?
sensation
el 6 de Jun. de 2018
sensation
el 21 de Jun. de 2018
Walter Roberson
el 21 de Jun. de 2018
If I recall correctly, with N even close to that large, asking matlabFunction to optimize the code takes far far too long, so I do not think you are going to be able to take advantage of that.
This is a more optimal implementation of storage(),
function S=storage(init_s,inFlow,x,N)
D=inFlow-totalflow(x,N);
D(1) = D(1) + ( init_s(1) + D(1) );
S=cumsum(D);
end
14 comentarios
What are the dimensions of all the quantities in your objective function
R= -sum(price*((HH*ro*g*eff)*x(1:N))/k1);
In particular, are any of them scalars?
sensation
el 21 de Jun. de 2018
Matt J
el 21 de Jun. de 2018
ro,g,eff,k1 are constants
Are they scalar constants?
Matt J
el 21 de Jun. de 2018
HH calculated [4000,200].
It doesn't look possible for HH to be 4000x200. Your depth() function returns an N-vector, not an NxM matrix.
sensation
el 21 de Jun. de 2018
sensation
el 21 de Jun. de 2018
At the end I meant if I derive HH values the vector would be [N,M] but ofcourse the calculations are done for each case study in optimization separately.
OK, then for clarity please say again what the dimensions are of all of the variables in the calculation
R= -sum(price*((HH*ro*g*eff)*x(1:N))/k1);
as they exist in the workspace of revenue() when it is executed. It looks like HH has to be a 1xN row vector, not an Nx1 column vector, based on the calculations I see in storage().
sensation
el 21 de Jun. de 2018
Matt J
el 21 de Jun. de 2018
OK, so HH is a 1xN row , x(1:N) is an Nx1 column, What about price? Row or column?
And what about ro,g,eff,k1. Earlier, you said they are scalars, not vectors. Is that still true?
sensation
el 22 de Jun. de 2018
If that's the case, then your objective function only depends on 'price' through its sum, which you shoud pre-compute before calling fmincon. Your objective computation then simplifies to
sumprice=-(ro*g*eff/k1)*sum(price);
function R=revenue(x,N,sumprice,init_s,inFlow,alpha_par,b_par)
HH=depth(alpha_par,b_par,init_s,inFlow,x,N);
R= sumprice*(HH*x(1:N));
end
So now you have 2 ways of making the computation more efficient: the above modification of your objective function and the re-implementation of storage() in my initial post.
sensation
el 26 de Jun. de 2018
I have implemented those suggestions and its a bit faster
How fast is it now? It should have been a lot faster than what you were doing.
Do you know maybe how I can run it with quadprog instead of fmincon?
The problem doesn't look quadratic, except maybe when b_par=1.
sensation
el 28 de Jun. de 2018
Categorías
Más información sobre Solver Outputs and Iterative Display en Centro de ayuda y File Exchange.
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!