MATLAB tic/toc in called function - matlab

In MATLAB, I want to time a function written by someone else, and their function might use tic/toc internally. I want my own tic/toc. But if the inner function calls tic, then the outer timer gets reset.
How can I avoid this? I don't want to use timeit because timeit will call the inner function multiple times, which I don't want.
MWE:
Outer script:
tic
inner_function()
elapsed_time = toc;
fprintf('Function took %f seconds\n', elapsed_time)
Inner function:
function [] = inner_function()
pause(2)
tic
toc
end
Then:
>> outer_script
Elapsed time is 0.000024 seconds.
Function took 0.000232 seconds
If you comment out the tic/toc in inner_function() you get this, which is what I want:
>> outer_script
Function took 2.000362 seconds
Just for a little more context, the outer script is mine, and I use it to test functions written by my students. I want to allow them to use tic/toc however they want in their code, but I also want to be able to time their code independently.

You can do this by assigning your tic calls to a variable. Give your desired timer to toc later on as an argument.
function [] = inner_function()
pause(2)
tic
toc
end
Rerunning a modified example,
clock2 = tic;
inner_function()
elapsed_time = toc(clock2);
fprintf('Function took %f seconds\n', elapsed_time)
Elapsed time is 0.000009 seconds.
Function took 2.009997 seconds

Related

Edit the Timer Function once it has started

I'm trying to figure out how to have a timer add time once it has begun. The idea is if a person clicks certain buttons in a GUI the timer increases by a given amount of time that is determined by a different variable. When I couldn't figure that out, I decided to just make a second timer that starts on a button click but the second timer won't display even though the code is the exact same so now I'm really at a loss.
enter image description here
enter image description here
As far as I know, there's no way to adjust a running timer. I would recommend trying to use tic/toc. Put your time limit in some variable (tLimit), get the start time with tic, and then compute the elapsed time with toc and compare to tLimit.
tLimit = <some number>;
tStart = tic;
Then later in the code you check how much time has elapsed:
if toc(tStart) > tLimit
% done
end
If you need to add time:
tLimit = tLimit + tExtra
If you really want to run your check in a timer object, you could create a function which does the time comparison, and have your timer run that:
function timeCheck(timerObj,~)
global tStart
global tLimit
if toc(tStart) > tLimit
fprintf('Time''s up! %0.1f seconds elapsed\n', toc(tStart));
stop(timerObj);
end
end
Then:
global tStart
global tLimit
tLimit = <some number>;
t = timer;
t.TimerFcn = #timeCheck;
t.ExecutionMode = 'fixedRate';
tStart = tic;
start(t);

Performance measurement: How to avoid timing the assignment of toc to a variable

for i=1:1
tic; M=R*R; toc;
elapsed_time = toc;
fprintf('Function took %8f seconds\n', elapsed_time)
x = sprintf('%0.8f',t);
tsum = t+tsum;
end
This is my code and output is;
Elapsed time is 0.000355 seconds.
Function took 0.000483 seconds
The first time (elapsed time) is the time that only calculate M=R*R
time but when I print out my calculated time (the function took), the time value is increasing because it also calculates assigning operation (elapsed_time = toc;). How can I calculate the time in the variable ignoring assigning operation?
You're using toc twice without a second tic. You simply need to assign a variable to the toc output the first time. Trust me, this variable assignment takes no time at all:
for i=1:1
tic; M=R*R;
elapsed_time = toc;
fprintf('Function took %8f seconds\n', elapsed_time)
x = sprintf('%0.8f',t);
tsum = t+tsum;
end

MATLAB: Product of products with execution time in milliseconds

I have a code that actually works but the output is supposed to be multiplied together. Also, the time of execution was not in milliseconds. This is the Matlab code
function product = prod(A)
tic;
A=input('matrix A =');
[rows, columns] = size(A);
for i=1:rows
prod=A(i,i)*A(i,end)
end
seconds=toc
For instance if given A=[1,2,3;4,5,6;7,8,9] when i=1 we have 1*3=3 when i=2 we have 2*6=12 when i=3 we have 9*9=81.
The output I want should be 3*12*81=2916 (the product of the values above) and the time of execution should be milliseconds.
When I extend the solution you proffer for the code below, it does not multiply them together and the time elapsed seems to be big
When the above code is used for the matrix A = [2,3,6,4;2,1,7,-2;6,8,1,-3;5,3,4,1].
My output is
out = -22, -23, -7, -3
Elapsed time is 10.200446 seconds.
I want all the output to multiple each other so that it will be
out = -22*-23*-7*-3 = 10626
Well, it took me some time to decipher what you have been trying to do, but finally, I was able to reconstruct your output. So first, there is no need for the prod function, it only makes things messy.
Here is a simple function that does the trick:
function out = testValue
A=input('matrix A =');
out=1;
if mod(size(A),2)==0
for i = 1:length(A)
out = out*(A(i,i)*A(i,end)-A(i,end-1)*A(end,i));
end
else
for i = 1:(length(A)-1)/2
out = out*(A(i,i)*A(i,end)-A(i,end-1)*A(end,i));
end
end
end
Some remarks on the code above:
No need for the columns variable
I omitted the tic toc - you can add them back if needed
No use for the prod function, instead the input for prod is simply what you consider as its output.
You have to initialize out=1 for a cumulative product
I'm sure there are cleverer ways to do this, but as #beaker wrote it is not clear what exactly is the purpose of this code.
Hope this helps :)

How to extract the elapsed time from a timer object in MATLAB?

Is there any way to extract the elapsed time from the beginning of each period from a timer object in MATLAB?
Say we have a timer object like this:
t=timer('ExecutionMode', 'fixedRate', ...
'Period', 15, ...
'TimerFcn',#(x,y)disp('Hello World!'))
The y contains the absolute timestamp. Store it when the timer is stated and take the difference:
function my_callback(m,x,y)
persistent starttime
switch m
case 'start'
starttime=y.Data.time;
case 'timer'
disp(datenum(y.Data.time-starttime)*24*60*60);
otherwise
error('unknown argument');
end
end
With a timer:
t=timer('ExecutionMode', 'fixedRate','Period', 15,'StartFcn',#(x,y)my_callback('start',x,y),'TimerFcn',#(x,y)my_callback('timer',x,y))
start(t)
Alternative solution using userdata:
t=timer('ExecutionMode', 'fixedRate','Period', 15,'StartFcn',#(x,y)set(x,'UserData',y.Data.time),'TimerFcn',#(x,y)disp(datenum(y.Data.time-get(x,'UserData'))*24*60*60))
Approach using tic, toc and 'UserData'
There is no direct method on the timer-object to read the elapsed time since its last call. It is possible to use a construct with tic and toc to achieve what you want.
The generic field 'UserData' can be used to add user-data to the timer object. We can write this value with set() and read it with get(). So we set this value with tic in the callback-function and get it back later to compute the time difference using toc.
More specifically, here is the callback-function:
function timerCallback(timerObj,event) %#ok<INUSD>
disp('Hello World!');
set(timerObj,'UserData',tic);
Now we can write a wrapper-function to get the elapsed time:
function retval = getElapsedTime(timerObj)
retval = toc(get(timerObj,'UserData'));
Example usage of proposed approach
To see if this approach works, we use pause to wait in a for loop and read the elapsed time approximately every second. Here is a complete example:
function timer_example
t = timer('ExecutionMode', 'fixedRate', ...
'Period', 5, ...
'TimerFcn', #timerCallback); % create timer
start(t); % start timer
pause on; % make sure pause can be used
for i = 1:10
pause(1); % wait a second
disp(getElapsedTime(t)); % display the elapsed time
end
stop(t); % stop timer
delete(t); % delete timer
function timerCallback(timerObj,event) %#ok<INUSD>
disp('Hello World!');
set(timerObj,'UserData',tic);
function retval = getElapsedTime(timerObj)
retval = toc(get(timerObj,'UserData'));
This gives the following output:
>> timer_example
Hello World!
1.0163
2.0173
3.0235
4.0285
Hello World!
0.0366
1.0390
2.0427
3.0461
4.0470
Hello World!
0.0515
Use tic as StartFcn of your timer and then use toc to elicit elapsed time, so:
timerObj = timer; %create timer object
timerObj.ExecutionMode = 'fixedSpacing';
timerObj.Period = 15;
timerObj.StartFcn = #(~,~)tic; % start ticking when timer starts
timerObj.TimerFcn = #myTimerFunc;
myTimerFunc is:
function [] = myTimerFunc(timerObj,event)
% use toc
disp(toc);
end

Execute for loop with time

I have a for loop like this
for t = 0: 1: 60
// my code
end
I want to execute my code in 1st, 2nd, 3rd, ..., 60th seconds. How to do this? Also how can I run my code at arbitrary times? For example in 1st, 3rd and 10th seconds?
What you can do is use the pause command and place how many seconds you want your code to pause for. Once you do that, you execute the code that you want. As an example:
times = 1:60;
for t = [times(1), diff(times)]
pause(t); % // Pause for t seconds
%// Place your code here...
...
...
end
As noted by #CST-Link, we should not take elapsed time into account, which is why we take the difference in neighbouring times of when you want to start your loop so that we can start your code as quickly as we can.
Also, if you want arbitrary times, place all of your times in an array, then loop through the array.
times = [1 3 10];
for t = [times(1), diff(times)]
pause(t); %// Pause for t seconds
%// Place your code here...
...
...
end
Polling is bad, but Matlab is by default single-threaded, so...
For the first case:
tic;
for t = 1:60
while toc < t, pause(0.01); end;
% your code
end;
For the second case:
tic;
for t = [1,3,10]
while toc < t, pause(0.01); end;
% your code
end;
The pause calls were added following the judicious observation of Amro about busy waiting. 0.01 seconds sounds like a good trade between timing precision and "amount" of spinning...
while pause is most of the time good enough, if you want better accuracy use java.lang.Thread.sleep.
For example the code below will display the minutes and seconds of your computer clock, exactly on the second (the function clock is accurate to ~ 1 microsecond), you can add your code instead of the disp command, the java.lang.Thread.sleep is just to illustrate it's accuracy (see after the code for an explanation)
while true
c=clock;
if mod(c(6),1)<1e-6
disp([c(5) c(6)])
java.lang.Thread.sleep(100); % Note: sleep() accepts [mSecs] duration
end
end
To see the difference in accuracy you can replace the above with java.lang.Thread.sleep(999); vs pause(0.999) and see how you sometimes skip an iteration.
For more info see here.
EDIT:
you can use tic\ toc instead of clock, this is probably more accurate because they take less time...
You can use a timer object. Here's an example that prints the numbers from 1 to 10 with 1 second between consecutive numbers. The timer is started, and it stops itself when a predefined number of executions is reached:
n = 1;
timerFcn = 'disp(n), n=n+1; if n>10, stop(t), end'; %// timer's callback
t = timer('TimerFcn' ,timerFcn, 'period', 1, 'ExecutionMode', 'fixedRate');
start(t) %// start the timer. Note that it will stop itself (within the callback)
A better version, with thanks to #Amro: specify the number of executions directly as a timer's property. Don't forget to stop the timer when done. But don't stop it too soon or it will not get executed the expected number of times!
n = 1;
timerFcn = 'disp(n), n=n+1;'; %// this will be the timer's callback
t = timer('TimerFcn', timerFcn, 'period', 1, 'ExecutionMode', 'fixedRate', ...
'TasksToExecute', 10);
start(t) %// start the timer.
%// do stuff. *This should last long enough* to avoid stopping the timer too soon
stop(t)