-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathparfor_progress.m
More file actions
121 lines (115 loc) · 4.82 KB
/
parfor_progress.m
File metadata and controls
121 lines (115 loc) · 4.82 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
function [percent, elapsed] = parfor_progress(N, varargin)
%PARFOR_PROGRESS Progress and duration for parallel executions (e.g. parfor)
%
% PARFOR_PROGRESS works by storing progress and start time in a temporary
% file. This is needed because parallel threads cannot communicate with one
% another so there is no simple way to know the execution order. This
% function is safe to use for large number of iterations as only 3 numbers
% are written to the file, i.e. it stays small (read and written quickly).
% Obviously, it works for non-parallel iterations too.
%
% FILE = PARFOR_PROGRESS(N) initializes the progress monitor for a set
% of N upcoming iterations, parallel or not.
%
% PARFOR_PROGRESS(FILE) updates the progress inside your parfor loop and
% displays an updated progress bar and estimated remaining time.
%
% DELETE(FILE) deletes the parfor progress file. A better way is to set a
% cleanup code C=ONCLEANUP(@() DELETE(FILE)) instead, in case an error or
% user-break occurs during parfor execution, or else files may stack up.
%
% To suppress output just ask for a return value, e.g.
% PERCENT = PARFOR_PROGRESS(FILE) or
% [PERCENT, ELAPSED] = PARFOR_PROGRESS(FILE) which returns the progress
% fraction and elapsed time in seconds.
%
% EXAMPLE:
%
% N = 100;
% pf = parfor_progress(N);
% fin = onCleanup(@() delete(pf)); % delete file on exit/error/break
% parfor i=1:N
% pause(rand); % Replace with real code
% parfor_progress(pf);
% end
%
% See also PARFOR.
%
% Author: Bogdan Roman, http://www.damtp.cam.ac.uk/user/abr28, 2014
% inspired by the work of Jeremy Scheff, http://www.jeremyscheff.com
narginchk(1, 2);
if isnumeric(N) && N > 0
if nargin > 1
file = varargin{1};
else
file = [tempname '_parfor.txt'];
end
fid = fopen(file, 'w');
if fid < 0, error('Could not open file for writing (perms?): %s', file); end
% write N, start time (0.1s resolution), and iteration (0 for now)
progress = [N floor(now*864000) 0];
fprintf(fid, '%d\n%d\n0\n', progress);
fclose(fid);
computeprogress(progress, false, true);
percent = file;
elapsed = 0;
else
file = N;
if ~ischar(file) || ~exist(file, 'file')
error('Not initialized. See HELP PARFOR_PROGRESS.');
end
% update (read and write) in one go
fid = fopen(file, 'r+');
progress = fscanf(fid, '%f'); % read the 3 values
progress(3) = progress(3) + 1; % update iteration number
fseek(fid, 0, 'bof');
fprintf(fid, '%d\n%d\n%d\n', round(progress)); % write back to file
fclose(fid);
[percent, elapsed] = computeprogress(progress, true, nargout == 0);
end
end
%---------------- PRIVATE FUNCTIONS ----------------%
function [percent, elapsed] = computeprogress (progress, update, show)
elapsed = (now - progress(2)/864000) * 86400; % compute elapsed seconds
percent = progress(3) / progress(1);
if percent == 0
duration = 0;
remaining = 0;
else
duration = elapsed / percent; % TODO: improve this crude estimate, exp smoothing filter?
remaining = duration - elapsed;
end
if show
r = humantime(remaining);
e = humantime(elapsed);
t = humantime(duration);
s = sprintf('%8.2f%%, %s (el), %s (rem), %s (tot)\n', ...
percent * 100, e, r, t);
if update, back = repmat(char(8),1,length(s)); else back = ''; end
fprintf('%s%s', back, s);
% % if not GUI mode then show one line per tick (useful for log files)
% %screenSize = get(0,'ScreenSize');
% %if isequal(screenSize(3:4),[1 1])
% if ~usejava('jvm') || ~feature('ShowFigureWindows')
% fprintf('%6.2f%%, %s (el), %s (rem), %s (tot)\n', ...
% percent * 100, e, r, t);
% else
% width = 50; % width of progress bar
% ticks = round(percent*width);
% if update, back = repmat(char(8), 1, (width+8+length(r)+length(e)+4)); else back = ''; end
% disp([back, sprintf('%3d%%',round(percent*100)), ' [', ...
% repmat('=', 1, ticks), repmat(' ', 1, width - ticks), '] ' e ' / ' r]);
% end
end
end
function t = humantime (s)
if s < 60, t = sprintf('%4.1fs', s);
elseif s < 3600, t = sprintf('%4.1fm', s/60);
elseif s < 86400, t = sprintf('%4.1fh', s/3600);
elseif s < 604800, t = sprintf('%4.1fd', s/86400); % 86400 = 1 day = 24 * 3600
elseif s < 2629800, t = sprintf('%4.1fw', s/604800); % 604800 = 1 week = 7 * 86400
elseif s < 31557600, t = sprintf('%4.1fM', s/2629800); % 2629800 = 1 average month = 365.25/12 * 86400
else t = sprintf('%4.1fy', s/31557600); % 31557600 = 1 average year = 365.25 * 86400
end
%t = sprintf('%3dh%02dm%02ds', floor(s/3600), mod(floor(s/60),60), mod(floor(s),60));
end