If you are impatient, you might want to put up a progress bar or waitbar()
during long for
loop in MATLAB. However, you should avoid use of waitbar()
or you have to use it efficiently. MATLAB's drawing is notoriously slow. waitbar()
suffers from it.
waitbar()
may be suitable when ...
1. You really need elaborated progress message during runtime.
2. You need a Cancel button during the process.
3. In the for
loop, the number of iterations is relatively small.
4. One iteration takes quite a long time (eg. > a few minuntes).
Otherwise, you should think of using simple frpintf()
instead. It's not really cool in appearance, but it is much faster if you only want to know where you are in the iterations.
Here is a comparison between fprintf()
and waitbar()
.
% waitbarVAfprintf
trials = 10;
elapsed1 = zeros(10,1);
for j = 1:10
clear n
tic
n = 1000;
fprintf('%d to go\n',n)
for i = 1:n
fprintf('*')
end
fprintf('\n')
elapsed1(j) = toc;
end
elapsed2 = zeros(10,1);
for j = 1:10
clear n
tic
n = 1000;
for i = 1:n
if round(i/n*100) > round((i-1)/n*100)
fprintf('*')
end
end
fprintf('\n')
elapsed2(j) = toc;
end
elapsed3 = zeros(10,1);
for j = 1:10
clear n wbmsg wb
tic
n = 1000;
for i = 1:n
wbmsg = sprintf('In progress: %.1f%%', i/n*100);
if ~exist('wb', 'var')
wb = waitbar((i-1)/n, wbmsg);
else
waitbar((i-1)/n, wb, wbmsg);
end
end
delete(wb) % cannot use 'close'!!!
elapsed3(j) = toc;
end
elapsed4 = zeros(10,1);
for j = 1:10
clear n wbmsg wb
tic
n = 1000;
for i = 1:n
if round(i/n*100) > round((i-1)/n*100)
wbmsg = sprintf('In progress: %.1f%%', i/n*100);
if ~exist('wb', 'var')
wb = waitbar((i-1)/n, wbmsg);
else
waitbar((i-1)/n, wb, wbmsg);
end
end
end
delete(wb) % cannot use 'close'!!!
elapsed4(j) = toc;
end
%%
fprintf('1. fprintf: %f %s %f msec per cycle\n',...
mean(elapsed1),char(177),std(elapsed1));
fprintf('2. fprintf for each %%: %f %s %f msec per cycle\n',...
mean(elapsed2),char(177),std(elapsed2));
fprintf('3. waitbar: %f %s %f msec per cycle\n',...
mean(elapsed3),char(177),std(elapsed3));
fprintf('4. waitbar for each %%: %f %s %f msec per cycle\n',...
mean(elapsed4),char(177),std(elapsed4));
fprintf('fprintf is %.1f-fold faster than waitbar updating at every cycle\n',...
mean(elapsed3./elapsed1));
fprintf('fprintf for each %% is %.1f-fold faster than waitbar for each %%\n',...
mean(elapsed4./elapsed2));
fprintf('fprintf for each %% is %.1f-fold faster than frpintf updating at every cycle\n',...
mean(elapsed1./elapsed2));
fprintf('waitbar for each %% is %.1f-fold faster than waitbar updating at every cycle\n',...
mean(elapsed3./elapsed4));
fprintf('fprintf for each %% is %.1f-fold faster than waitbar updating at every cycle\n',...
mean(elapsed3./elapsed2));
Results look like this.
fprintf is 360.9-fold faster than waitbar updating at every cycle
fprintf for each % is 510.3-fold faster than waitbar for each %
fprintf for each % is 10.7-fold faster than frpintf updating at every cycle
waitbar for each % is 7.5-fold faster than waitbar updating at every cycle
fprintf for each % is 3829.7-fold faster than waitbar updating at every cycle
Look, fprintf()
printing *
in Command Window for each iteration (i.e. you'll see 1,000 *
s in the end) is 361-fold faster than waitbar()
.
When printing or updating only at every 1% increment in progress, fprintf()
is 510-fold faster than waitbar()
.
fprintf()
printing *
only at every 1% increment in progress (i.e. you'll see only 100 *
s in the end) is 3,830-fold faster than waitbar()
updating at every iteration !!!
Conclusion: You should know that waitbar()
is slow. In order to use waitbar()
efficiently, it is recommended that you only update waitbar()
for a certain number of iterations rather than updating it in every iteration.
n = 1000;
for i = 1:n
if round(i/n*100) > round((i-1)/n*100)
wbmsg = sprintf('In progress: %.1f%%', i/n*100);
if ~exist('wb', 'var')
wb = waitbar((i-1)/n, wbmsg);
else
waitbar((i-1)/n, wb, wbmsg);
end
end
end