The same script/funktion different time with MatLab - matlab

i am somekind of "advanced" beginner in programing. I couldn't find answer to my question, i found this, MATLAB Speed Difference in Identical Code, but it is not exactly what i'm looking for. I have the following problem, my script or function consists of couple of segments, when i run them manually with Run Section, i need something like 15 sec. including scroling and clicking. When i start them as one function i need 72 sec. The code is:
a=diff(Min_ZR);
b=zeros(38000000,1)*NaN;
i=1;
while i<length(a)
if a(i)==1;
b(i)=1;
i=i+1;
else
b(i)=0;
i=i+1;
end
end
b(i:end) = [];
%%
iL=2;
kL=2;
L1=zeros(38000000,1)*0;
while iL<length(test_L)
if test_L(iL)==1
L1(iL)=L1(kL-1)+1;
iL=iL+1;
kL=iL;
else
L1(iL)=L1(iL-1);
iL=iL+1;
end
end
L1(iL:end)=[];
%%
iR=2;
kR=2;
L2=zeros(38000000,1)*0;
while iR<length(test_R)
if test_R(iR)==1
L2(iR)=L2(kR-1)+1;
iR=iR+1;
kR=iR;
else
L2(iR)=L2(iR-1);
iR=iR+1;
end
end
L2(iR:end)=[];
%%
iZ=2;
kZ=2;
ZR=zeros(38000000,1)*0;
%while i<length(test_R)
while iZ<length(b)
if b(iZ)==1
ZR(iZ)=ZR(kZ-1)+1;
iZ=iZ+1;
kZ=iZ;
else
ZR(iZ)=ZR(iZ-1);
iZ=iZ+1;
end
end
ZR(iZ:end)=[];
%%
L1=L1/4;
L2=L2/4;
ZR=ZR/8*34/22;
i=1;
diff_L1=zeros(38000000,1)*NaN;
diff_L2=zeros(38000000,1)*NaN;
while i<=length(ZR)
diff_L1(i)=L1(i)-ZR(i);
diff_L2(i)=L2(i)-ZR(i);
i=i+1;
end
diff_L1(i:end)=[];
diff_L2(i:end)=[];
l=length(ZR);
Drehmoment=zeros(l,1);
Drehmoment(1:10000)=100;
Drehmoment(10001:end)=380;
%%
figure % new figure
[hAx,hLine1,hLine2] = plotyy(ZR,diff_L2,ZR,Drehmoment);
title('Zahnradwandern 30.03.2016')
xlabel('Gesamtumdrehungen /1 ')
ylabel(hAx(1),'Differenzumdrehungen /1 ') % left y-axis
ylabel(hAx(2),'Drehmoment / Nm') % right y-axis
set(hAx(1),'Xlim',[0 1050000])
set(hAx(2),'Xlim',[0 1050000])
set(hAx(1),'Xtick',0:50000:1050000)
set(hAx(1),'XTickLabel',{'0','','100000','','200000','','300000','','400000','','500000','','600000','','700000','','800000','','900000','','1000000',''})
set(hAx(1),'Ylim',[-2 38])
set(hAx(1),'YTick',-2:2:38)
set(hAx(2),'YTick',0:20:400)
set(hAx(2),'Ylim',[0 400])
grid on
hold on
plot (ZR,diff_L1,'color','g')
hold off
legend('Differenzumdrehungen PL2','Differenzumdrehungen PL1','Antriebsmoment')
For each section i need less then 1 or 2 sec. just for the Plot i need a bit more, but as i wrote 15 sec. tops it is nowhere near to 72 sec. that i get when i Run the Function.
Thank you in advance.

I've found the Problem, if i start the program with run and time, it tells me 72 sec, or after i used hint 4. from Crowley 60 sec. It also says that the "Run and Time fkt" don't use resources but if i just Run the program it completes in under 10sec.

Does your code improve it's performance when:
you change indexes i to ii. i and j are reserved for imaginary units;
define b=nan(length(a),1); and L1=zeros(length(test_L),1); and ommit b(:,end)=[]; and L1(iL:end)=[];;
use for ii=1:length(a) instead of while loop;
use b=zeros(length(a),1);b(a==1)=1; instead of whole while loop;
use diff_L=L1-R1 instead of while loop;
use Drehmoment=ones(l,1)*380;Drehmoment(1:100000)=100;?
These are just suggestions where you can loose your time...
EDIT regarding to hbadert's comment
Have you tried:
Block=1;
BlockTic(Block)=tic;
%%Block 1
BlockToc(Block)=toc;
Block=Block+1;
BlockTic(Block)=tic;
%%...
BlockToc(Block)=toc;
AllTime=BlockToc(end)-BlockTic(1);
Times=BlockToc-BlockTic;
disp(['Global time: ',num2str(AllTime)])
disp('Block times:')
disp(Times')

Related

Matlab Timing Program

For work, I need to write a Matlab program that will trigger a stimulus (TTL pulse) after set amounts of time. First, I need the program to wait 32 mins. Then, I want it to execute the stimulus pulse, wait 5 seconds, execute the stimulus pulse again, then wait an additional 115 seconds. I need it to do 5 iterations of this (excluding the 32 min wait period).
I am terrible at Matlab syntax. I worked with Python a little bit, but this particular function requires Matlab because it has a toolkit that works with the stimulus generator.
For what it's worth, the trigger output as it appears in existing code looks like this:
if i > 1
% insert output trigger for page 1
pages(1).Page = 1 + VSG.DUALPAGE + VSG.TRIGGERPAGE;
end;
Here's my crappy attempt at the loop part of the code, which is giving me all kinds of syntax errors:
% Use for loop for 5 iterations
for i = 1:5
% trigger TTL pulse
pages(1).Page = 1 + VSG.DUALPAGE + VSG.TRIGGERPAGE;
% trying to use tic and toc as a timer that resets each iteration
timerID = tic;
% I thought to use a while loop for the timing
% 5 second wait period
while true
if(toc(timerID)>5)
break;
end
% trigger TTL pulse again
pages(1).Page = 1 + VSG.DUALPAGE + VSG.TRIGGERPAGE;
% 115 second wait period
while true
if(toc(timerID)>120)
break;
end
end
That's all I've got. Any help at all would be greatly appreciated. Feel free to tell me if I need to use a completely different approach as I know I'm terrible at Matlab. Thank you.
You can use pause for this. Try something like this:
pause(32*60); % Pause 32 minutes
for ii = 1:5
pages(1).Page = 1 + VSG.DUALPAGE + VSG.TRIGGERPAGE;
pause(5);
pages(1).Page = 1 + VSG.DUALPAGE + VSG.TRIGGERPAGE;
pause(115);
end

How to delete decimals that have repeating decimals

I'm working on a code able to work data from star of a public catalogue. I've already got arrays of every single variable that is available:
enter code here fid=fopen('000006+2553.txt','r');
i=1;
while 1
tline=fgetl(fid);
if ~ischar(tline), break, end
A{i}=tline;
i=i+1;
end
k=1;
for j=1:1:length(A)
if length(A{j}) > 50 && length(A{j})<=92
B{k}=A{j};
k=k+1;
end
end
m=1;
for l=1:1:length(B)
C=strread(B{l},'%s','delimiter',' ');
HJD(m)=str2num(C{1});
MAG_3(m)=str2num(C{2});
MAG_0(m)=str2num(C{3});
MAG_1(m)=str2num(C{4});
MAG_2(m)=str2num(C{5});
MAG_4(m)=str2num(C{6});
MER_3(m)=str2num(C{7});
MER_0(m)=str2num(C{8});
MER_1(m)=str2num(C{9});
MER_2(m)=str2num(C{10});
MER_4(m)=str2num(C{11});
FRAME(m)=str2num(C{13});
m=m+1;
end
My problem is, that some of the values in the arrays are repeating decimals, like 29.99999 and 99.99999....etc. Since this numbers are the result of saturation of the sensor, they are wrong data, and must be eliminated. Is there anyway I can tell MATLAB to delete this particular numbers? Any help would be appreciated.

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)

Matlab: Print progress from parfor loop

I run a lot of long simulations in Matlab, typically taking from a couple of minutes to a couple of hours, so to speed things up I decided to run the simulations simultaneously using a parfor loop.
arglist = [arg1, arg2, arg3, arg4];
parfor ii = 1:size(arglist, 2)
myfun(arglist(ii));
end
Everything worked just fine, except for one thing: the progress printing. Since each simulation takes a lot of time, I usually print progress using something like
prevlength = 0;
for ii = 1:tot_iter
% Some calculations here
msg = sprintf('Working on %d of %d, %.2f percent done', ii, tot_iter, ii/tot_iter);
fprintf(repmat('\b', 1, prevlength))
fprintf(msg);
prevlength = numel(msg);
end
but, as could be expected, when doing this inside a parfor loop, you get chaos.
I have googled a lot in search of a solution and have found a bunch of "parfor progress printers" like this one. However, all of them print the progress of the entire parfor loop instead of showing how far each of the individual iterations have come. Since I only have about 4-8 iterations in the parfor loop, but each iteration takes about an hour, this approach isn't very helpful to me.
The ideal solution for me would be something that looks like this
Working on 127 of 10000, 1.27 percent done
Working on 259 of 10000, 2.59 percent done
Working on 3895 of 10000, 38.95 percent done
Working on 1347 of 10000, 13.47 percent done
that is, each simulation gets one line showing how far it has run. I'm not sure though if this is possible at all, I can at least not imagine any way to do this.
Another way would be to do something like this
Sim 1: 1.27% Sim 2: 2.59% Sim 3: 38.95% Sim 4: 13.47%
that is, show all the progresses on the same line. To do this, you would need to keep track of what position on the line each simulation is to write on and write there, without erasing the other progresses. I can't figure out how this would be done, is this possible to do?
If there is some other solution to my problem (showing the progress of each individual iteration) that I haven't thought of, I'd be happy to hear about it.
Since this is the first time I ask a question here on SO it is quite possible that there is something that I have missed; if so, please feel free to comment below.
Edit
After receiving this answer, I thought that I should share how I used it to solve my problem since I didn't use it exactly as in the answer, in case someone else encounters the same problem.
Here is a small test program with basically the same structure as my program, making use of the progress bar (parfor_progress) mentioned in the answer:
function parfor_progress_test()
cpus = feature('numCores');
matlabpool('open', cpus);
cleaner = onCleanup(#mycleaner);
args = [1000, 1000, 1000, 1000];
m = sum(args);
parfor_progress(m);
parfor ii = 1:size(args,2)
my_fun(args(ii));
end
parfor_progress(0);
end
function my_fun(N)
for ii = 1:N
pause(rand*0.01);
parfor_progress;
end
end
function mycleaner
matlabpool close;
fclose all;
end
Simple Progress Bar
Something like a progress bar could be done similar to this...
Before the parfor loop :
fprintf('Progress:\n');
fprintf(['\n' repmat('.',1,m) '\n\n']);
And during the loop:
fprintf('\b|\n');
Here we have m is the total number of iterations, the . shows the total number of iterations and | shows the number of iterations completed. The \n makes sure the characters are printed in the parfor loop.
Progress Bar and Percentage Completion
Otherwise you could try this: http://www.mathworks.com/matlabcentral/fileexchange/32101-progress-monitor--progress-bar--that-works-with-parfor
It will display a progress bar and percentage completion but can be easily modified to just include the percentage completion or progress bar.
This function amends a character to a file on every iteration and then reads the number of characters written to that file which indicates the number of iterations completed. This file accessing method is allowed in parfor's.
Assuming you correctly add the above to your MATLAB path somehow, you can then use the following:
arglist = [arg1, arg2, arg3, arg4];
parfor_progress(size(arglist, 2)); % Set the total number of iterations
parfor ii = 1:size(arglist, 2)
myfun(arglist(ii));
parfor_progress; % Increment the progress counter
end
parfor_progress(0); % Reset the progress counter
Time to Completion and Percentage Completion
There is also a function called showTimeToCompletion() which is available from: https://www.soundzones.com/software/sound-zone-tools/
and works alongside parfor_progress. This function allows you to print a detailed summary of the progress of a parfor loop (or any loop for that matter) which contains the start time, length of time running, estimated finish time and percentage completion. It makes smart use of the \b (backspace) character so that the command window isn't flooded with text. Although not strictly a progress 'bar' it is perhaps more informative.
The third example in the header of the function file,
fprintf('\t Completion: ');
showTimeToCompletion; startTime=tic;
len=1e2;
p = parfor_progress( len );
parfor i = 1:len
pause(1);
p = parfor_progress;
showTimeToCompletion( p/100, [], [], startTime );
end
outputs the following to the command window:
Completion: 31.00%
Remaining: 00:00:23
Total: 00:00:33
Expected Finish: 3:30:07PM 14-Nov-2017
Useful for estimating the completion of a running simulation, especially one that may take hours or days.
Starting in R2013b, you can use PARFEVAL to evaluate your function asynchronously and have the client display progress updates. (Obviously this approach is not quite as simple as adding stuff to your PARFOR loop). There's an example here.
The Diary property of the Future returned by PARFEVAL is updated continuously while processing, so that might also be useful if you have a small number of large tasks.
Starting in R2017a, you can use parallel.pool.DataQueue and afterEach to implement a waitbar for parfor, like so:
if isempty(gcp('nocreate'))
parpool('local', 3);
end
dq = parallel.pool.DataQueue;
N = 10;
wb = waitbar(0, 'Please wait...');
% Use the waitbar's UserData to track progress
wb.UserData = [0 N];
afterEach(dq, #(varargin) iIncrementWaitbar(wb));
afterEach(dq, #(idx) fprintf('Completed iteration: %d\n', idx));
parfor idx = 1:N
pause(rand());
send(dq, idx);
end
close(wb);
function iIncrementWaitbar(wb)
ud = wb.UserData;
ud(1) = ud(1) + 1;
waitbar(ud(1) / ud(2), wb);
wb.UserData = ud;
end
after exploring #Edric answer I found that there is an example in the Matlab documentation that exactly implements a waitbar for a pareval loop. Check help FetchNext
N = 100;
for idx = N:-1:1
% Compute the rank of N magic squares
F(idx) = parfeval(#rank, 1, magic(idx));
end
% Build a waitbar to track progress
h = waitbar(0, 'Waiting for FevalFutures to complete...');
results = zeros(1, N);
for idx = 1:N
[completedIdx, thisResult] = fetchNext(F);
% store the result
results(completedIdx) = thisResult;
% update waitbar
waitbar(idx/N, h, sprintf('Latest result: %d', thisResult));
end
% Clean up
delete(h)

How do I know how many iterations are left in a parfor loop in Matlab?

I am running a parfor loop in Matlab that takes a lot of time and I would like to know how many iterations are left. How can I get that info?
I don't believe you can get that information directly from MATLAB, short of printing something with each iteration and counting these lines by hand.
To see why, recall that each parfor iteration executes in its own workspace: while incrementing a counter within the loop is legal, accessing its "current" value is not (because this value does not really exist until completion of the loop). Furthermore, the parfor construct does not guarantee any particular execution order, so printing the iterator value isn't helpful.
cnt = 0;
parfor i=1:n
cnt = cnt + 1; % legal
disp(cnt); % illegal
disp(i); % legal ofc. but out of order
end
Maybe someone does have a clever workaround, but I think that the independent nature of the parfor iterations belies taking a reliable count. The restrictions mentioned above, plus those on using evalin, etc. support this conclusion.
As #Jonas suggested, you could obtain the iteration count via side effects occurring outside of MATLAB, e.g. creating empty files in a certain directory and counting them. This you can do in MATLAB of course:
fid = fopen(['countingDir/f' num2str(i)],'w');
fclose(fid);
length(dir('countingDir'));
Try this FEX file: http://www.mathworks.com/matlabcentral/fileexchange/32101-progress-monitor--progress-bar--that-works-with-parfor
You can easily modify it to return the iteration number instead of displaying a progress bar.
Something like a progress bar could be done similar to this...
Before the parfor loop :
fprintf('Progress:\n');
fprintf(['\n' repmat('.',1,m) '\n\n']);
And during the loop:
fprintf('\b|\n');
Here we have m is the total number of iterations, the . shows the total number of iterations and | shows the number of iterations completed. The \n makes sure the characters are printed in the parfor loop.
With Matlab 2017a or later you can use a data queue or a pollable data queue to achieve this. Here's the MathWorks documentation example of how to do a progress bar from the first link :
function a = parforWaitbar
D = parallel.pool.DataQueue;
h = waitbar(0, 'Please wait ...');
afterEach(D, #nUpdateWaitbar);
N = 200;
p = 1;
parfor i = 1:N
a(i) = max(abs(eig(rand(400))));
send(D, i);
end
function nUpdateWaitbar(~)
waitbar(p/N, h);
p = p + 1;
end
end
End result :
If you just want to know how much time is left approximately, you can run the program once record the max time and then do this
tStart = tic;
parfor i=1:n
tElapsed = toc(tStart;)
disp(['Time left in min ~ ', num2str( ( tMax - tElapsed ) / 60 ) ]);
...
end
I created a utility to do this:
http://www.mathworks.com/matlabcentral/fileexchange/48705-drdan14-parforprogress