interrupt a function when it takes too long
73 次查看(过去 30 天)
显示 更早的评论
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.
0 个评论
回答(3 个)
Edric Ellis
2020-3-30
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.
John D'Errico
2020-3-28
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.
jwiix
2024-9-24
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
0 个评论
另请参阅
类别
在 Help Center 和 File Exchange 中查找有关 Number Theory 的更多信息
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!