LoginSignup
0
0

More than 5 years have passed since last update.

A reason why you should avoid MATLAB-builtin waitbar() and instead use fprintf()

Last updated at Posted at 2016-06-30

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.png

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

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0