interrupt a function when it takes too long
41 views (last 30 days)
Is there a way to interrupt a function that has been taking too long in a for loop and continue to the next iteration? I am calling a function inside a for-loop and know about how long it should take for that function to converge. If it doesn't converge, I would like to move to the next iteration. Would using parfor be the best method?
I know there is a previous post answering this question, but that was an old version of matlab. I am wondering if this capability has been added since then.
John D'Errico on 28 Mar 2020
This is not what parfor is designed to solve, nor even what you could reasonably solve with parfor.
Since you are calling the function inside a for loop, change how you set up the loop. Use a while loop instead, where you keep track of the time consumed, or perhaps the number of iterations. Stop the loop when you have spent too much time. Since a while loop is based on a test anyway, this becomes a simple thing. You might decide to loop until EITHER you achieve the convergence tolerance, OR the maximum number of iterations has been hit, OR the total time consumed has been exceeded. As I said, this is one of the things a while loop is designed to do.
A rough outline of code MIGHT be:
errortol = 1.e-8;
maxiter = 1000;
maxtime = 10;
iter = 0;
tstart = tic;
tcurrent = tstart;
while (iter < maxiter) && ((tcurrent - start) < maxtime) && (currenterror > errortol)
% increment the iteration counter
iter = iter + 1;
% Perform whatever stuff you need to do here.
% To compute a test for convergence, you will need to compute the
% change in your objective, (or however you will predict convergence.)
currenterror = ...
% How much time has been spent in this particulr process?
tcurrent = toc;
So something like that. The code I've shown is more pseudo-code than real code, since I have no idea what iterations you are doing.
As you can see, the while loop iterates only as long as all of the conditions are true, what you want to see happen.
Edric Ellis on 30 Mar 2020
The simplest approach would be to modify the potentially long-running function so that it checks whether it has exceeded its time budget. You haven't told us anything about that function, so it's not clear whether or not this might work for you.
If you aren't able to modify this function, you could possibly use parfeval to run the function on a worker process, and monitor the time taken on the client. Something a bit like this:
for idx = 1:N % your outer for-loop
% Invoke your function on a worker
fut = parfeval(@maybeLongRunningFunction, 1, <args>);
% Block for up to maxTime seconds waiting for a result
didFinish = wait(fut, 'finished', maxTime);
% Execution didn't finish in time, cancel this iteration
% Did complete, retrieve results
out(idx) = fetchOutputs(fut);
If this approach works, you might even be able to run multiple copies of your function simultaneously by making multiple calls to parfeval.