pwrake 0.9.5 → 0.9.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/README.md +83 -4
- data/lib/pwrake/application.rb +34 -0
- data/lib/pwrake/file_utils.rb +43 -16
- data/lib/pwrake/gfarm_feature.rb +79 -40
- data/lib/pwrake/locality_aware_queue.rb +141 -111
- data/lib/pwrake/logger.rb +7 -1
- data/lib/pwrake/master.rb +21 -2
- data/lib/pwrake/option.rb +106 -56
- data/lib/pwrake/profiler.rb +44 -12
- data/lib/pwrake/report/parallelism.rb +262 -0
- data/lib/pwrake/report/report.rb +355 -0
- data/lib/pwrake/report/report_multi.rb +196 -0
- data/lib/pwrake/report/stat.rb +115 -0
- data/lib/pwrake/report.rb +6 -0
- data/lib/pwrake/shell.rb +30 -10
- data/lib/pwrake/task_algorithm.rb +174 -50
- data/lib/pwrake/task_queue.rb +130 -50
- data/lib/pwrake/version.rb +1 -1
- data/spec/004/Rakefile +1 -1
- data/spec/009/pwrake_conf.yaml +1 -0
- data/spec/011/Rakefile +15 -0
- data/spec/helper.rb +7 -3
- data/spec/pwrake_spec.rb +12 -0
- metadata +15 -9
@@ -0,0 +1,355 @@
|
|
1
|
+
module Pwrake
|
2
|
+
|
3
|
+
class Report
|
4
|
+
|
5
|
+
HTML_HEAD = <<EOL
|
6
|
+
<html><head><style>
|
7
|
+
<!--
|
8
|
+
h2 {
|
9
|
+
background-color:#eee;
|
10
|
+
}
|
11
|
+
h1 {
|
12
|
+
background-color:#0ff;
|
13
|
+
}
|
14
|
+
table {
|
15
|
+
margin:0px;
|
16
|
+
border-style:solid;
|
17
|
+
border-width:1px;
|
18
|
+
}
|
19
|
+
td {
|
20
|
+
margin:0px;
|
21
|
+
border-style:solid;
|
22
|
+
border-width:1px;
|
23
|
+
}
|
24
|
+
-->
|
25
|
+
</style>
|
26
|
+
</head>
|
27
|
+
<body>
|
28
|
+
EOL
|
29
|
+
|
30
|
+
@@id = 0
|
31
|
+
@@id_fmt = nil
|
32
|
+
|
33
|
+
def initialize(base,pattern)
|
34
|
+
@base = base
|
35
|
+
@pattern = pattern
|
36
|
+
|
37
|
+
@@id = @@id.succ
|
38
|
+
@id = @@id
|
39
|
+
|
40
|
+
@csv_file = base+'.csv'
|
41
|
+
@task_file = base+'.task'
|
42
|
+
@html_file = base+'.html'
|
43
|
+
|
44
|
+
open(@base+".log","r").each do |s|
|
45
|
+
if /num_cores=(\d+)/ =~ s
|
46
|
+
@ncore = $1.to_i
|
47
|
+
break
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
@sh_table = CSV.read(@csv_file,:headers=>true)
|
52
|
+
h = {}
|
53
|
+
@sh_table.each do |row|
|
54
|
+
if host = row['host']
|
55
|
+
h[host] = true
|
56
|
+
end
|
57
|
+
end
|
58
|
+
@hosts = h.keys.sort
|
59
|
+
@start_time = Time.parse(@sh_table[0]["start_time"])
|
60
|
+
@end_time = Time.parse(@sh_table[-1]["start_time"])
|
61
|
+
@elap = @end_time - @start_time
|
62
|
+
read_elap_each_cmd
|
63
|
+
make_cmd_stat
|
64
|
+
end
|
65
|
+
|
66
|
+
attr_reader :base, :ncore, :elap
|
67
|
+
attr_reader :csv_file, :html_file
|
68
|
+
attr_reader :cmd_elap, :cmd_stat
|
69
|
+
attr_reader :sh_table, :task_table
|
70
|
+
attr_reader :id
|
71
|
+
|
72
|
+
def id_str
|
73
|
+
if @@id_fmt.nil?
|
74
|
+
id_len = Math.log10(@@id).floor + 1
|
75
|
+
@@id_fmt = "#%0#{id_len}d"
|
76
|
+
end
|
77
|
+
@@id_fmt % @id
|
78
|
+
end
|
79
|
+
|
80
|
+
def read_elap_each_cmd
|
81
|
+
@cmd_elap = {}
|
82
|
+
@sh_table.each do |row|
|
83
|
+
command = row['command']
|
84
|
+
elap = row['elap_time']
|
85
|
+
if command && elap
|
86
|
+
elap = elap.to_f
|
87
|
+
found = nil
|
88
|
+
@pattern.each do |cmd,regex|
|
89
|
+
if regex =~ command
|
90
|
+
if a = @cmd_elap[cmd]
|
91
|
+
a << elap
|
92
|
+
else
|
93
|
+
@cmd_elap[cmd] = [elap]
|
94
|
+
end
|
95
|
+
found = true
|
96
|
+
end
|
97
|
+
end
|
98
|
+
if !found
|
99
|
+
if cmd = get_command( command )
|
100
|
+
if a = @cmd_elap[cmd]
|
101
|
+
a << elap
|
102
|
+
else
|
103
|
+
@cmd_elap[cmd] = [elap]
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
@cmd_elap
|
110
|
+
end
|
111
|
+
|
112
|
+
def get_command(s)
|
113
|
+
if /\(([^()]+)\)/ =~ s
|
114
|
+
s = $1
|
115
|
+
end
|
116
|
+
a = s.split(/;/)
|
117
|
+
a.each do |x|
|
118
|
+
if /^\s*(\S+)/ =~ x
|
119
|
+
k = $1
|
120
|
+
next if k=='cd'
|
121
|
+
return k
|
122
|
+
end
|
123
|
+
end
|
124
|
+
nil
|
125
|
+
end
|
126
|
+
|
127
|
+
def make_cmd_stat
|
128
|
+
@cmd_stat = {}
|
129
|
+
@cmd_elap.each do |cmd,elap|
|
130
|
+
@cmd_stat[cmd] = s = Stat.new(elap)
|
131
|
+
if elap.size > 1
|
132
|
+
s.make_logx_histogram(1.0/8)
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
def format_comma(x)
|
138
|
+
x.to_s.gsub(/(?<=\d)(?=(?:\d\d\d)+(?!\d))/, ',')
|
139
|
+
end
|
140
|
+
|
141
|
+
def tr_count(x,y)
|
142
|
+
sum = x+y
|
143
|
+
td = "<td align='right' valign='top'>"
|
144
|
+
m = td + "%s<br/>%.2f%%</td>" % [format_comma(x),x*100.0/sum]
|
145
|
+
m << td + "%s<br/>%.2f%%</td>" % [format_comma(y),y*100.0/sum]
|
146
|
+
m << td + "%s</td>" % format_comma(sum)
|
147
|
+
m
|
148
|
+
end
|
149
|
+
|
150
|
+
def report_html
|
151
|
+
html = HTML_HEAD + "<body><h1>Pwrake Statistics</h1>\n"
|
152
|
+
html << "<h2>Workflow</h2>\n"
|
153
|
+
html << "<table>\n"
|
154
|
+
html << "<tr><th>log file</th><td>#{@base}</td><tr>\n"
|
155
|
+
html << "<tr><th>ncore</th><td>#{@ncore}</td><tr>\n"
|
156
|
+
html << "<tr><th>elapsed time(sec)</th><td>#{@elap}</td><tr>\n"
|
157
|
+
html << "<tr><th>start time</th><td>#{@start_time}</td><tr>\n"
|
158
|
+
html << "<tr><th>end time</th><td>#{@end_time}</td><tr>\n"
|
159
|
+
html << "</table>\n"
|
160
|
+
html << "<table>\n"
|
161
|
+
html << "<tr><th>hosts</th><tr>\n"
|
162
|
+
@hosts.each do |h|
|
163
|
+
html << "<tr><td>#{h}</td><tr>\n"
|
164
|
+
end
|
165
|
+
html << "</table>\n"
|
166
|
+
html << "<h2>Parallelism</h2>\n"
|
167
|
+
fimg = Parallelism.plot_parallelism2(@csv_file)
|
168
|
+
html << "<img src='#{fimg}' align='top'/></br>\n"
|
169
|
+
|
170
|
+
html << "<h2>Parallelism by host</h2>\n"
|
171
|
+
fimg2 = Parallelism.plot_parallelizm_by_host(@sh_table,@base)
|
172
|
+
html << "<img src='#{fimg2}' align='top'/></br>\n"
|
173
|
+
|
174
|
+
html << "<h2>Command statistics</h2>\n"
|
175
|
+
html << "<table>\n"
|
176
|
+
html << "<tr><th>command</th>"
|
177
|
+
html << Stat.html_th
|
178
|
+
html << "</tr>\n"
|
179
|
+
@cmd_stat.each do |cmd,stat|
|
180
|
+
html << "<tr><td>#{cmd}</td>"
|
181
|
+
html << stat.html_td
|
182
|
+
html << "</tr>\n"
|
183
|
+
end
|
184
|
+
html << "<table>\n"
|
185
|
+
html << "<img src='#{histogram_plot}' align='top'/></br>\n"
|
186
|
+
|
187
|
+
task_locality
|
188
|
+
html << "<h2>Locality statistics</h2>\n"
|
189
|
+
html << "<table>\n"
|
190
|
+
|
191
|
+
html << "<tr><th></th><th rowspan=3>gross elapsed time (sec)</th><th></th>"
|
192
|
+
html << "<th colspan=6>read</th>"
|
193
|
+
html << "<th></th>"
|
194
|
+
html << "<th colspan=6>write</th>"
|
195
|
+
html << "</tr>\n"
|
196
|
+
|
197
|
+
|
198
|
+
html << "<tr><th></th><th></th>"
|
199
|
+
html << "<th colspan=3>count</th><th colspan=3>file size (bytes)</th>"
|
200
|
+
html << "<th></th>"
|
201
|
+
html << "<th colspan=3>count</th><th colspan=3>file size (bytes)</th>"
|
202
|
+
html << "</tr>\n"
|
203
|
+
|
204
|
+
html << "<tr><th>host</th><th></th>"
|
205
|
+
html << "<th>local</th><th>remote</th><th>total</th>"
|
206
|
+
html << "<th>local</th><th>remote</th><th>total</th>"
|
207
|
+
html << "<th></th>"
|
208
|
+
html << "<th>local</th><th>remote</th><th>total</th>"
|
209
|
+
html << "<th>local</th><th>remote</th><th>total</th>"
|
210
|
+
html << "</tr>\n"
|
211
|
+
n_same_input = 0
|
212
|
+
size_same_input = 0
|
213
|
+
n_diff_input = 0
|
214
|
+
size_diff_input = 0
|
215
|
+
n_same_output = 0
|
216
|
+
size_same_output = 0
|
217
|
+
n_diff_output = 0
|
218
|
+
size_diff_output = 0
|
219
|
+
elap_host = 0
|
220
|
+
@exec_hosts.each do |h|
|
221
|
+
html << "<tr><td>#{h}</td>"
|
222
|
+
html << "<td align='right'>%.3f</td>" % @elap_host[h]
|
223
|
+
html << "<td></td>"
|
224
|
+
html << tr_count(@n_same_input[h],@n_diff_input[h])
|
225
|
+
html << tr_count(@size_same_input[h],@size_diff_input[h])
|
226
|
+
html << "<td></td>"
|
227
|
+
html << tr_count(@n_same_output[h],@n_diff_output[h])
|
228
|
+
html << tr_count(@size_same_output[h],@size_diff_output[h])
|
229
|
+
|
230
|
+
html << "</tr>\n"
|
231
|
+
n_same_input += @n_same_input[h]
|
232
|
+
size_same_input += @size_same_input[h]
|
233
|
+
n_diff_input += @n_diff_input[h]
|
234
|
+
size_diff_input += @size_diff_input[h]
|
235
|
+
n_same_output += @n_same_output[h]
|
236
|
+
size_same_output += @size_same_output[h]
|
237
|
+
n_diff_output += @n_diff_output[h]
|
238
|
+
size_diff_output += @size_diff_output[h]
|
239
|
+
elap_host += @elap_host[h]
|
240
|
+
end
|
241
|
+
html << "<tr><td>total</td>"
|
242
|
+
html << "<td align='right'>%.3f</td>" % elap_host
|
243
|
+
html << "<td></td>"
|
244
|
+
html << tr_count(n_same_input,n_diff_input)
|
245
|
+
html << tr_count(size_same_input,size_diff_input)
|
246
|
+
html << "<td></td>"
|
247
|
+
html << tr_count(n_same_output,n_diff_output)
|
248
|
+
html << tr_count(size_same_output,size_diff_output)
|
249
|
+
|
250
|
+
html << "</tr>\n"
|
251
|
+
html << "<table>\n"
|
252
|
+
|
253
|
+
html << "</body></html>\n"
|
254
|
+
File.open(@html_file,"w") do |f|
|
255
|
+
f.puts html
|
256
|
+
end
|
257
|
+
puts "generate "+@html_file
|
258
|
+
end
|
259
|
+
|
260
|
+
def task_locality
|
261
|
+
@task_table = CSV.read(@task_file,:headers=>true)
|
262
|
+
file_size = {}
|
263
|
+
file_host = {}
|
264
|
+
@task_table.each do |row|
|
265
|
+
name = row['task_name']
|
266
|
+
file_size[name] = row['file_size'].to_i
|
267
|
+
file_host[name] = (row['file_host']||'').split('|')
|
268
|
+
end
|
269
|
+
|
270
|
+
@n_same_output = Hash.new(0)
|
271
|
+
@size_same_output= Hash.new(0)
|
272
|
+
@n_diff_output = Hash.new(0)
|
273
|
+
@size_diff_output= Hash.new(0)
|
274
|
+
@n_same_input = Hash.new(0)
|
275
|
+
@size_same_input = Hash.new(0)
|
276
|
+
@n_diff_input = Hash.new(0)
|
277
|
+
@size_diff_input = Hash.new(0)
|
278
|
+
h = {}
|
279
|
+
@task_table.each do |row|
|
280
|
+
if row['executed']=='1'
|
281
|
+
name = row['task_name']
|
282
|
+
exec_host = row['exec_host']
|
283
|
+
h[exec_host] = true
|
284
|
+
if file_host[name].include?(exec_host)
|
285
|
+
@n_same_output[exec_host] += 1
|
286
|
+
@size_same_output[exec_host] += file_size[name]
|
287
|
+
else
|
288
|
+
@n_diff_output[exec_host] += 1
|
289
|
+
@size_diff_output[exec_host] += file_size[name]
|
290
|
+
end
|
291
|
+
preq_files = (row['preq']||'').split('|')
|
292
|
+
preq_files.each do |preq|
|
293
|
+
if (sz=file_size[preq]) && sz > 0
|
294
|
+
if file_host[preq].include?(exec_host)
|
295
|
+
@n_same_input[exec_host] += 1
|
296
|
+
@size_same_input[exec_host] += sz
|
297
|
+
else
|
298
|
+
@n_diff_input[exec_host] += 1
|
299
|
+
@size_diff_input[exec_host] += sz
|
300
|
+
end
|
301
|
+
end
|
302
|
+
end
|
303
|
+
end
|
304
|
+
end
|
305
|
+
@exec_hosts = h.keys.sort
|
306
|
+
|
307
|
+
@elap_host = Hash.new(0)
|
308
|
+
@sh_table.each do |row|
|
309
|
+
if (h = row['host']) && (t = row['elap_time'])
|
310
|
+
@elap_host[h] += t.to_f
|
311
|
+
end
|
312
|
+
end
|
313
|
+
end
|
314
|
+
|
315
|
+
def histogram_plot
|
316
|
+
command_list = []
|
317
|
+
@cmd_stat.each do |cmd,stat|
|
318
|
+
if stat.n > 2
|
319
|
+
command_list << cmd
|
320
|
+
end
|
321
|
+
end
|
322
|
+
hist_image = @base+"_hist.png"
|
323
|
+
IO.popen("gnuplot","r+") do |f|
|
324
|
+
f.puts "
|
325
|
+
set terminal png # size 480,360
|
326
|
+
set output '#{hist_image}'
|
327
|
+
set ylabel 'histogram'
|
328
|
+
set xlabel 'Execution time (sec)'
|
329
|
+
set logscale x
|
330
|
+
set title 'histogram of elapsed time'"
|
331
|
+
a = []
|
332
|
+
|
333
|
+
command_list.each_with_index do |n,i|
|
334
|
+
a << "'-' w histeps ls #{i+1} title ''"
|
335
|
+
a << "'-' w lines ls #{i+1} title '#{n}'"
|
336
|
+
end
|
337
|
+
f.puts "plot "+ a.join(',')
|
338
|
+
|
339
|
+
command_list.each do |cmd|
|
340
|
+
stat = @cmd_stat[cmd]
|
341
|
+
2.times do
|
342
|
+
stat.hist_each do |x1,x2,y|
|
343
|
+
x = Math.sqrt(x1*x2)
|
344
|
+
f.printf "%f %d\n", x, y
|
345
|
+
end
|
346
|
+
f.puts "e"
|
347
|
+
end
|
348
|
+
end
|
349
|
+
hist_image
|
350
|
+
end
|
351
|
+
end
|
352
|
+
|
353
|
+
|
354
|
+
end
|
355
|
+
end
|
@@ -0,0 +1,196 @@
|
|
1
|
+
module Pwrake
|
2
|
+
|
3
|
+
class ReportMulti
|
4
|
+
|
5
|
+
def initialize(list,pattern)
|
6
|
+
@reports = list.map do |base|
|
7
|
+
r = Report.new(base,pattern)
|
8
|
+
puts r.base+" elap=#{r.elap}"
|
9
|
+
r
|
10
|
+
end
|
11
|
+
@pattern = pattern
|
12
|
+
@elap_png = 'elap.png'
|
13
|
+
end
|
14
|
+
|
15
|
+
def report(stat_html)
|
16
|
+
if true
|
17
|
+
@reports.each do |r|
|
18
|
+
r.report_html
|
19
|
+
end
|
20
|
+
plot_elap
|
21
|
+
end
|
22
|
+
html = Report::HTML_HEAD + "<body><h1>Pwrake Statistics</h1>\n"
|
23
|
+
html << "<h2>Log files</h2>\n"
|
24
|
+
html << "<table>\n"
|
25
|
+
html << "<tr><th>log file</th><th>id</th><th>ncore</th><th>elapsed time(sec)</th><tr>\n"
|
26
|
+
@reports.each do |r|
|
27
|
+
html << "<tr><td><a href='#{r.html_file}'>#{r.base}</a></td>"
|
28
|
+
html << "<td>#{r.id_str}</td><td>#{r.ncore}</td><td>#{r.elap}</td><tr>\n"
|
29
|
+
end
|
30
|
+
html << "</table>\n"
|
31
|
+
html << "<h2>Elapsed time</h2>\n"
|
32
|
+
html << "<img src='#{@elap_png}' align='top'/></br>\n"
|
33
|
+
|
34
|
+
html << "<h2>Histogram of Execution time</h2>\n"
|
35
|
+
html << report_histogram()
|
36
|
+
html << "</body></html>\n"
|
37
|
+
|
38
|
+
File.open(stat_html,"w") do |f|
|
39
|
+
f.puts html
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def plot_elap
|
44
|
+
a = @reports.map{|r| r.ncore * r.elap}.min
|
45
|
+
elaps = @reports.map{|r| r.elap}
|
46
|
+
logmin = Math.log10(elaps.min)
|
47
|
+
logmax = Math.log10(elaps.max)
|
48
|
+
mid = (logmin+logmax)/2
|
49
|
+
wid = (logmax-logmin).ceil*0.5
|
50
|
+
ymin = 10**(mid-wid)
|
51
|
+
ymax = 10**(mid+wid)
|
52
|
+
IO.popen("gnuplot","r+") do |f|
|
53
|
+
f.puts "
|
54
|
+
set terminal png size 640,480
|
55
|
+
set output '#{@elap_png}'
|
56
|
+
set xlabel 'ncore'
|
57
|
+
set ylabel 'time (sec)'
|
58
|
+
set yrange [#{ymin}:#{ymax}]
|
59
|
+
set logscale xy
|
60
|
+
plot #{a}/x,'-' w lp lw 2 ps 2 title 'elapsed time'
|
61
|
+
"
|
62
|
+
@reports.sort_by{|r| r.ncore}.each do |r|
|
63
|
+
f.puts "#{r.ncore} #{r.elap}"
|
64
|
+
end
|
65
|
+
f.puts "e"
|
66
|
+
end
|
67
|
+
puts "Ncore-time plot: "+@elap_png
|
68
|
+
end
|
69
|
+
|
70
|
+
def report_histogram
|
71
|
+
@images = {}
|
72
|
+
@cmd_rep = {}
|
73
|
+
|
74
|
+
@reports.each do |r|
|
75
|
+
r.cmd_stat.each do |cmd,stat|
|
76
|
+
if stat.n > 2
|
77
|
+
@cmd_rep[cmd] ||= {}
|
78
|
+
@cmd_rep[cmd][r.id_str] = r # stat
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
@cmd_rep.each_key do |cmd|
|
84
|
+
@images[cmd] = 'hist_'+cmd.gsub(/[\/.]/,'_')+'.png'
|
85
|
+
end
|
86
|
+
histogram_plot
|
87
|
+
histogram_html
|
88
|
+
end
|
89
|
+
|
90
|
+
def histogram_html
|
91
|
+
html = ""
|
92
|
+
@cmd_rep.each do |cmd,cmd_rep|
|
93
|
+
html << "<p>Statistics of Elapsed time of #{cmd}</p>\n<table>\n"
|
94
|
+
html << "<th>id</th><th>ncore</th>"+Stat.html_th
|
95
|
+
cmd_rep.each do |id,r|
|
96
|
+
s = r.cmd_stat[cmd]
|
97
|
+
html << "<tr><td>#{id}</td><td>#{r.ncore}</td>" + s.html_td + "</tr>\n"
|
98
|
+
end
|
99
|
+
html << "</table>\n"
|
100
|
+
html << "<img src='./#{@images[cmd]}'/>\n"
|
101
|
+
end
|
102
|
+
html
|
103
|
+
end
|
104
|
+
|
105
|
+
def histogram_plot
|
106
|
+
@cmd_rep.each do |cmd,cmd_rep|
|
107
|
+
IO.popen("gnuplot","r+") do |f|
|
108
|
+
f.puts "
|
109
|
+
set terminal png # size 480,360
|
110
|
+
set output '#{@images[cmd]}'
|
111
|
+
set ylabel 'histogram'
|
112
|
+
set xlabel 'Execution time (sec)'
|
113
|
+
set logscale x
|
114
|
+
set title '#{cmd}'"
|
115
|
+
a = []
|
116
|
+
ncores = cmd_rep.keys
|
117
|
+
ncores.each_with_index{|n,i|
|
118
|
+
a << "'-' w histeps ls #{i+1} title ''"
|
119
|
+
a << "'-' w lines ls #{i+1} title '#{n}'"
|
120
|
+
}
|
121
|
+
f.puts "plot "+ a.join(',')
|
122
|
+
|
123
|
+
cmd_rep.each do |ncore,r|
|
124
|
+
s = r.cmd_stat[cmd]
|
125
|
+
2.times do
|
126
|
+
s.hist_each do |x1,x2,y|
|
127
|
+
x = Math.sqrt(x1*x2)
|
128
|
+
f.printf "%f %d\n", x, y
|
129
|
+
end
|
130
|
+
f.puts "e"
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
puts "Histogram plot: #{@images[cmd]}"
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
def histogram_plot2
|
139
|
+
@cmd_rep.each do |cmd,cmd_rep|
|
140
|
+
IO.popen("gnuplot","r+") do |f|
|
141
|
+
f.puts "
|
142
|
+
set terminal png # size 480,360
|
143
|
+
set output '#{@images[cmd]}'
|
144
|
+
set nohidden3d
|
145
|
+
set palette rgb 33,13,10
|
146
|
+
set pm3d
|
147
|
+
set ticslevel 0
|
148
|
+
unset colorbox
|
149
|
+
set yrange [#{cmd_rep.size}:0]
|
150
|
+
set logscale x
|
151
|
+
set title '#{cmd}'"
|
152
|
+
a = []
|
153
|
+
ncores = cmd_rep.keys.sort
|
154
|
+
ncores.each_with_index{|n,i|
|
155
|
+
a << "'-' w lines ls #{i+1} title '#{n} cores'"
|
156
|
+
}
|
157
|
+
f.puts "splot "+ a.join(',')
|
158
|
+
|
159
|
+
ncores.each_with_index do |ncore,i|
|
160
|
+
s = cmd_rep[ncore]
|
161
|
+
y = i
|
162
|
+
s.hist_each do |x1,x2,z|
|
163
|
+
f.printf "%g %g 0\n", x1,y
|
164
|
+
f.printf "%g %g 0\n", x2,y
|
165
|
+
f.printf "%g %g 0\n", x2,y
|
166
|
+
end
|
167
|
+
f.puts ""
|
168
|
+
s.hist_each do |x1,x2,z|
|
169
|
+
f.printf "%g %g %g\n", x1,y,z
|
170
|
+
f.printf "%g %g %g\n", x2,y,z
|
171
|
+
f.printf "%g %g 0\n", x2,y,z
|
172
|
+
end
|
173
|
+
f.puts ""
|
174
|
+
y = i+1
|
175
|
+
s.hist_each do |x1,x2,z|
|
176
|
+
f.printf "%g %g %g\n", x1,y,z
|
177
|
+
f.printf "%g %g %g\n", x2,y,z
|
178
|
+
f.printf "%g %g 0\n", x2,y,z
|
179
|
+
end
|
180
|
+
f.puts ""
|
181
|
+
s.hist_each do |x1,x2,z|
|
182
|
+
f.printf "%g %g 0\n", x1,y
|
183
|
+
f.printf "%g %g 0\n", x2,y
|
184
|
+
f.printf "%g %g 0\n", x2,y
|
185
|
+
end
|
186
|
+
f.puts "e"
|
187
|
+
i = i+1
|
188
|
+
end
|
189
|
+
end
|
190
|
+
puts "Histogram plot: #{@images[cmd]}"
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
@@ -0,0 +1,115 @@
|
|
1
|
+
module Pwrake
|
2
|
+
|
3
|
+
class Stat
|
4
|
+
|
5
|
+
def initialize(data)
|
6
|
+
@data = data
|
7
|
+
@n = data.size
|
8
|
+
if @n>0
|
9
|
+
@min = data.min
|
10
|
+
@max = data.max
|
11
|
+
@sum = data.inject(0){|s,x| s+x}
|
12
|
+
@mean = @sum/@n
|
13
|
+
@median = _median
|
14
|
+
@mean_absolute_deviation = data.inject(0){|s,x| (x-@mean).abs} / @n
|
15
|
+
if @n>1
|
16
|
+
@variance = data.inject(0){|s,x| y=x-@mean; y**2} / (@n-1)
|
17
|
+
@sdev = Math.sqrt(@variance)
|
18
|
+
@skew = data.inject(0){|s,x| y=(x-@mean)/@sdev; y**3} / @n
|
19
|
+
@kurt = data.inject(0){|s,x| y=(x-@mean)/@sdev; y**4} / @n - 3
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
attr_reader :n
|
25
|
+
attr_reader :min, :max, :sum, :mean, :median
|
26
|
+
attr_reader :mean_absolute_deviation
|
27
|
+
attr_reader :variance, :sdev, :skew, :kurt
|
28
|
+
attr_reader :hist, :hist_min, :hist_max, :bin
|
29
|
+
|
30
|
+
def make_logx_histogram(bin)
|
31
|
+
@bin = bin # 1.0/10
|
32
|
+
@i_max = (Math.log10(@max)/@bin).floor
|
33
|
+
@i_min = (Math.log10(@min)/@bin).floor
|
34
|
+
@hist_min = 10**(@i_min * @bin)
|
35
|
+
@hist_max = 10**((@i_max+1) * @bin)
|
36
|
+
@hist = Array.new(@i_max-@i_min+1,0)
|
37
|
+
@data.each do |x|
|
38
|
+
i = (Math.log10(x)/@bin-@i_min).floor
|
39
|
+
raise "invalid index i=#{i}" if i<0 || i>@i_max-@i_min
|
40
|
+
@hist[i] += 1
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def hist_each
|
45
|
+
if @hist
|
46
|
+
n = @hist.size
|
47
|
+
n.times do |i|
|
48
|
+
x1 = 10**(@bin*(i+@i_min))
|
49
|
+
x2 = 10**(@bin*(i+1+@i_min))
|
50
|
+
y = @hist[i]
|
51
|
+
yield x1,x2,y
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def _median
|
57
|
+
if @n==1
|
58
|
+
@data[0]
|
59
|
+
elsif @n==2
|
60
|
+
@mean
|
61
|
+
else
|
62
|
+
case @n%2
|
63
|
+
when 1
|
64
|
+
i = (@n-1)/2
|
65
|
+
@data.sort[i]
|
66
|
+
else
|
67
|
+
i = @n/2
|
68
|
+
s = @data.sort
|
69
|
+
(s[i]+s[i+1])/2
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def report
|
75
|
+
case @n
|
76
|
+
when 0
|
77
|
+
"no data"
|
78
|
+
when 1
|
79
|
+
"n=1 mean=%g"%@mean
|
80
|
+
else
|
81
|
+
"n=%i mean=%g median=%g min=%g max=%g sdev=%g skew=%g kurt=%g" %
|
82
|
+
[@n, @mean, @median, @min, @max, @sdev||0, @skew||0, @kurt||0]
|
83
|
+
"n=%i mean=%g median=%g min=%g max=%g sdev=%g" %
|
84
|
+
[@n, @mean, @median, @min, @max, @sdev||0]
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def stat_array
|
89
|
+
[@n, @mean, @median, @min, @max, @sdev||0]
|
90
|
+
end
|
91
|
+
|
92
|
+
def html_td
|
93
|
+
"<td>%i</td><td>%g</td><td>%g</td><td>%g</td><td>%g</td><td>%g</td>" %
|
94
|
+
[@n, @mean, @median, @min, @max, @sdev||0]
|
95
|
+
end
|
96
|
+
|
97
|
+
def self.html_th
|
98
|
+
"<th>%s</th><th>%s</th><th>%s</th><th>%s</th><th>%s</th><th>%s</th>" %
|
99
|
+
%w[n mean median min max sdev]
|
100
|
+
end
|
101
|
+
|
102
|
+
def report2
|
103
|
+
case @n
|
104
|
+
when 0
|
105
|
+
" no data"
|
106
|
+
when 1
|
107
|
+
" n=1\n mean=%g"%@mean
|
108
|
+
else
|
109
|
+
" n=%i\n mean=%g\n median=%g\n min=%g\n max=%g\n sdev=%g\n skew=%g\n kurt=%g" %
|
110
|
+
[@n, @mean, @median, @min, @max, @sdev||0, @skew||0, @kurt||0]
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
end
|
115
|
+
end
|