interrupt a function when it takes too long

59 Ansichten (letzte 30 Tage)
Alexandra McClernon Ownbey
Alexandra McClernon Ownbey am 28 Mär. 2020
Beantwortet: jwiix am 24 Sep. 2024
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.

Antworten (3)

Edric Ellis
Edric Ellis am 30 Mär. 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);
if ~didFinish
% Execution didn't finish in time, cancel this iteration
cancel(fut);
else
% Did complete, retrieve results
out(idx) = fetchOutputs(fut);
end
end
If this approach works, you might even be able to run multiple copies of your function simultaneously by making multiple calls to parfeval.
  1 Kommentar
Alexandra McClernon Ownbey
I have a method of characteristics code written in fortran77. I wrote a wrapper in matlab to help me quickly iterate through different input values. These values don't always converge in the MOC code, which causes the fortran script to continue to run. The code only takes a few seconds to run when it converges. I wanted to add functionality that would continue to the next iteration of the MOC if the current iteration did not converge quickly.

Melden Sie sich an, um zu kommentieren.


John D'Errico
John D'Errico am 28 Mär. 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;
end
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.
  1 Kommentar
Alexandra McClernon Ownbey
Alexandra McClernon Ownbey am 28 Mär. 2020
this will not work. using a while loop only works if i check how long the function takes after the fact. I need to check it simultaneously (hence my question for parfor).

Melden Sie sich an, um zu kommentieren.


jwiix
jwiix am 24 Sep. 2024
function [outputArg1,outputArg2] = yourFunction()
%YOURFUNCTION Summary of this function goes here
% Detailed explanation goes here
outputArg1 = 1;
outputArg2 = 2;
end
function [outputArg1,outputArg2] = yourFunction2()
%YOURFUNCTION Summary of this function goes here
% Detailed explanation goes here
outputArg1 = 1;
outputArg2 = 2;
wait(10);
end
function result = runWithTimeoutSimplified(func, timeout)
% Create a parallel pool if it doesn't exist
if isempty(gcp('nocreate'))
parpool('local', 1);
end
% Start the function asynchronously
f = parfeval(@() func(), 1);
tic;
a=true;
runFlag=0;
while a
b=toc;
a=b<timeout;
% Wait for the function to complete or timeout
if strcmpi(f.State,'running')
runFlag =1;
else
runFlag=0;
[result] = fetchOutputs(f);
break;
end
end
if runFlag
cancel(f);
disp('Operation cancelled due to timeout')
else
disp(result);
end
end
% Then in console:
>> result = runWithTimeoutSimplified(@yourFunction, 5) % This should pass and display result
>> result = runWithTimeoutSimplified(@yourFunction2, 5) % This will fail and be cancelled after timeout .. in this case 5 seconds
You can put the
runWithTimeoutSimplified(@yourFunction, 5)
in your for loop but you will need to manage your errors since any terminated function will throw an error when you cancel it. Failing anything better wrap your function call in a try / catch

Produkte


Version

R2017a

Community Treasure Hunt

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

Start Hunting!

Translated by