pwrake 0.9.8 → 0.9.9

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d50d7fd5c00627f0eea3d59e26632c4e9e4c0f6d
4
- data.tar.gz: 3d9d6638a9dde0ce9feebc1ba210d9ce1d94b310
3
+ metadata.gz: cdc080259b5fb3f1b2c487375c56d2c319c4ad4b
4
+ data.tar.gz: 8f28b6ff5df2e0160abf7c259808d85632c5db27
5
5
  SHA512:
6
- metadata.gz: c7517d29d640a06db61bc8a656615d43706564c49596d594830cadbbe0134b79bfe71c542e182de003baff492b58008bcb90e60b97aab587de1460f21cd99ce6
7
- data.tar.gz: 99f101b28c359ea3157caf688205da6734bb95569dd1eea6fed5cc6787e6b1f9a7bd01a35ab1e7dd694e2782c0969480f4abea1d18bc68d963bc85658d9432c6
6
+ metadata.gz: ba5588c3bf612d56321bba8e36d331f2a4404b2815d3765b6b0baf7a483462498e852f31780147c38631c3c11b46ba9583849faeaec00d3792bbff29f9e332fb
7
+ data.tar.gz: b6dd586b0982cfedd38ea166c9f7621fce13f90af61ad2f0ae334c659b9bd70be014d63c7ed9719c259ae5ca613940ab338fd627c11218fb5f2be3ba5510d08e
@@ -6,8 +6,78 @@ module Pwrake
6
6
  end
7
7
  end
8
8
 
9
+ # copy from ruby's thread.rb
10
+ class ConditionVariable
11
+ #
12
+ # Creates a new ConditionVariable
13
+ #
14
+ def initialize
15
+ @waiters = {}
16
+ @waiters_mutex = Mutex.new
17
+ end
18
+
19
+ #
20
+ # Releases the lock held in +mutex+ and waits; reacquires the lock on wakeup.
21
+ #
22
+ # If +timeout+ is given, this method returns after +timeout+ seconds passed,
23
+ # even if no other thread doesn't signal.
24
+ #
25
+ def wait(mutex, timeout=nil)
26
+ Thread.handle_interrupt(StandardError => :never) do
27
+ begin
28
+ Thread.handle_interrupt(StandardError => :on_blocking) do
29
+ @waiters_mutex.synchronize do
30
+ @waiters[Thread.current] = true
31
+ end
32
+ mutex.sleep timeout
33
+ end
34
+ ensure
35
+ @waiters_mutex.synchronize do
36
+ @waiters.delete(Thread.current)
37
+ end
38
+ end
39
+ end
40
+ self
41
+ end
42
+
43
+ #
44
+ # Wakes up the first thread in line waiting for this lock.
45
+ #
46
+ def signal
47
+ Thread.handle_interrupt(StandardError => :on_blocking) do
48
+ begin
49
+ t, _ = @waiters_mutex.synchronize { @waiters.shift }
50
+ t.run if t
51
+ rescue ThreadError
52
+ retry # t was already dead?
53
+ end
54
+ end
55
+ self
56
+ end
57
+
58
+ #
59
+ # Wakes up all threads waiting for this lock.
60
+ #
61
+ def broadcast
62
+ Thread.handle_interrupt(StandardError => :on_blocking) do
63
+ threads = nil
64
+ @waiters_mutex.synchronize do
65
+ threads = @waiters.keys
66
+ @waiters.clear
67
+ end
68
+ for t in threads
69
+ begin
70
+ t.run
71
+ rescue ThreadError
72
+ end
73
+ end
74
+ end
75
+ self
76
+ end
77
+ end
9
78
 
10
79
  class LocalityConditionVariable < ConditionVariable
80
+
11
81
  def signal(hints=nil)
12
82
  if hints.nil?
13
83
  super()
@@ -63,6 +63,8 @@ EOL
63
63
  @elap = @end_time - @start_time
64
64
  read_elap_each_cmd
65
65
  make_cmd_stat
66
+
67
+ @stat = TaskStat.new(@task_file,@sh_table)
66
68
  end
67
69
 
68
70
  attr_reader :base, :ncore, :elap
@@ -142,9 +144,11 @@ EOL
142
144
 
143
145
  def tr_count(x,y)
144
146
  sum = x+y
147
+ xp = x*100.0/sum
148
+ yp = y*100.0/sum
145
149
  td = "<td align='right' valign='top'>"
146
- m = td + "%s<br/>%.2f%%</td>" % [format_comma(x),x*100.0/sum]
147
- m << td + "%s<br/>%.2f%%</td>" % [format_comma(y),y*100.0/sum]
150
+ m = td + '%s<br/>''%.2f%%</td>' % [format_comma(x),xp]
151
+ m << td + '%s<br/>''%.2f%%</td>' % [format_comma(y),yp]
148
152
  m << td + "%s</td>" % format_comma(sum)
149
153
  m
150
154
  end
@@ -192,7 +196,6 @@ EOL
192
196
  html << "<table>\n"
193
197
  html << "<img src='./#{File.basename(histogram_plot)}' align='top'/></br>\n"
194
198
 
195
- task_locality
196
199
  html << "<h2>Locality statistics</h2>\n"
197
200
  html << "<table>\n"
198
201
 
@@ -216,44 +219,25 @@ EOL
216
219
  html << "<th>local</th><th>remote</th><th>total</th>"
217
220
  html << "<th>local</th><th>remote</th><th>total</th>"
218
221
  html << "</tr>\n"
219
- n_same_input = 0
220
- size_same_input = 0
221
- n_diff_input = 0
222
- size_diff_input = 0
223
- n_same_output = 0
224
- size_same_output = 0
225
- n_diff_output = 0
226
- size_diff_output = 0
227
- elap_host = 0
228
- @exec_hosts.each do |h|
222
+ @stat.exec_hosts.each do |h|
229
223
  html << "<tr><td>#{h}</td>"
230
- html << "<td align='right'>%.3f</td>" % @elap_host[h]
224
+ html << "<td align='right'>%.3f</td>" % @stat[h,nil,:elap]
231
225
  html << "<td></td>"
232
- html << tr_count(@n_same_input[h],@n_diff_input[h])
233
- html << tr_count(@size_same_input[h],@size_diff_input[h])
226
+ html << tr_count(@stat[h,true,:in_num],@stat[h,false,:in_num])
227
+ html << tr_count(@stat[h,true,:in_size],@stat[h,false,:in_size])
234
228
  html << "<td></td>"
235
- html << tr_count(@n_same_output[h],@n_diff_output[h])
236
- html << tr_count(@size_same_output[h],@size_diff_output[h])
237
-
229
+ html << tr_count(@stat[h,true,:out_num],@stat[h,false,:out_num])
230
+ html << tr_count(@stat[h,true,:out_size],@stat[h,false,:out_size])
238
231
  html << "</tr>\n"
239
- n_same_input += @n_same_input[h]
240
- size_same_input += @size_same_input[h]
241
- n_diff_input += @n_diff_input[h]
242
- size_diff_input += @size_diff_input[h]
243
- n_same_output += @n_same_output[h]
244
- size_same_output += @size_same_output[h]
245
- n_diff_output += @n_diff_output[h]
246
- size_diff_output += @size_diff_output[h]
247
- elap_host += @elap_host[h]
248
232
  end
249
233
  html << "<tr><td>total</td>"
250
- html << "<td align='right'>%.3f</td>" % elap_host
234
+ html << "<td align='right'>%.3f</td>" % @stat.total(nil,:elap)
251
235
  html << "<td></td>"
252
- html << tr_count(n_same_input,n_diff_input)
253
- html << tr_count(size_same_input,size_diff_input)
236
+ html << tr_count(@stat.total(true,:in_num),@stat.total(false,:in_num))
237
+ html << tr_count(@stat.total(true,:in_size),@stat.total(false,:in_size))
254
238
  html << "<td></td>"
255
- html << tr_count(n_same_output,n_diff_output)
256
- html << tr_count(size_same_output,size_diff_output)
239
+ html << tr_count(@stat.total(true,:out_num),@stat.total(false,:out_num))
240
+ html << tr_count(@stat.total(true,:out_size),@stat.total(false,:out_size))
257
241
 
258
242
  html << "</tr>\n"
259
243
  html << "<table>\n"
@@ -262,64 +246,12 @@ EOL
262
246
  File.open(@html_file,"w") do |f|
263
247
  f.puts html
264
248
  end
265
- puts "generate "+@html_file
266
- end
267
-
268
- def task_locality
269
- @task_table = CSV.read(@task_file,:headers=>true)
270
- file_size = {}
271
- file_host = {}
272
- @task_table.each do |row|
273
- name = row['task_name']
274
- file_size[name] = row['file_size'].to_i
275
- file_host[name] = (row['file_host']||'').split('|')
276
- end
249
+ #puts "generate "+@html_file
277
250
 
278
- @n_same_output = Hash.new(0)
279
- @size_same_output= Hash.new(0)
280
- @n_diff_output = Hash.new(0)
281
- @size_diff_output= Hash.new(0)
282
- @n_same_input = Hash.new(0)
283
- @size_same_input = Hash.new(0)
284
- @n_diff_input = Hash.new(0)
285
- @size_diff_input = Hash.new(0)
286
- h = {}
287
- @task_table.each do |row|
288
- if row['executed']=='1'
289
- name = row['task_name']
290
- exec_host = row['exec_host']
291
- h[exec_host] = true
292
- if file_host[name].include?(exec_host)
293
- @n_same_output[exec_host] += 1
294
- @size_same_output[exec_host] += file_size[name]
295
- else
296
- @n_diff_output[exec_host] += 1
297
- @size_diff_output[exec_host] += file_size[name]
298
- end
299
- preq_files = (row['preq']||'').split('|')
300
- preq_files.each do |preq|
301
- if (sz=file_size[preq]) && sz > 0
302
- if file_host[preq].include?(exec_host)
303
- @n_same_input[exec_host] += 1
304
- @size_same_input[exec_host] += sz
305
- else
306
- @n_diff_input[exec_host] += 1
307
- @size_diff_input[exec_host] += sz
308
- end
309
- end
310
- end
311
- end
312
- end
313
- @exec_hosts = h.keys.sort
314
-
315
- @elap_host = Hash.new(0)
316
- @sh_table.each do |row|
317
- if (h = row['host']) && (t = row['elap_time'])
318
- @elap_host[h] += t.to_f
319
- end
320
- end
251
+ printf "%s,%d,%d,%d,%d\n",@html_file, @stat.total(true,:in_num),@stat.total(false,:in_num),@stat.total(true,:in_size),@stat.total(false,:in_size)
321
252
  end
322
253
 
254
+
323
255
  def histogram_plot
324
256
  command_list = []
325
257
  @cmd_stat.each do |cmd,stat|
@@ -357,7 +289,72 @@ set title 'histogram of elapsed time'"
357
289
  hist_image
358
290
  end
359
291
  end
292
+ end
293
+
294
+ class TaskStat
295
+
296
+ def initialize(task_file, sh_table)
297
+ @task_table = CSV.read(task_file,:headers=>true)
298
+ @count = Hash.new(0)
299
+ task_locality
300
+ stat_sh_table(sh_table)
301
+ end
302
+
303
+ attr_reader :exec_hosts
304
+
305
+ def count(exec_host, loc, key, val)
306
+ @count[[exec_host,loc,key]] += val
307
+ @count[[loc,key]] += val
308
+ end
309
+
310
+ def total(loc,key)
311
+ @count[[loc,key]]
312
+ end
313
+
314
+ def [](exec_host,loc,key)
315
+ @count[[exec_host,loc,key]]
316
+ end
317
+
318
+ def task_locality
319
+ file_size = {}
320
+ file_host = {}
321
+ h = {}
322
+ @task_table.each do |row|
323
+ name = row['task_name']
324
+ file_size[name] = row['file_size'].to_i
325
+ file_host[name] = (row['file_host']||'').split('|')
326
+ h[row['exec_host']] = true
327
+ end
328
+ @exec_hosts = h.keys.sort
329
+
330
+ @task_table.each do |row|
331
+ if row['executed']=='1'
332
+ name = row['task_name']
333
+ exec_host = row['exec_host']
334
+ loc = file_host[name].include?(exec_host)
335
+ count(exec_host, loc, :out_num, 1)
336
+ count(exec_host, loc, :out_size, file_size[name])
337
+
338
+ preq_files = (row['preq']||'').split('|')
339
+ preq_files.each do |preq|
340
+ sz = file_size[preq]
341
+ if sz && sz > 0
342
+ loc = file_host[preq].include?(exec_host)
343
+ count(exec_host, loc, :in_num, 1)
344
+ count(exec_host, loc, :in_size, sz)
345
+ end
346
+ end
347
+ end
348
+ end
349
+ end
360
350
 
351
+ def stat_sh_table(sh_table)
352
+ sh_table.each do |row|
353
+ if (h = row['host']) && (t = row['elap_time'])
354
+ count(h, nil, :elap, t.to_f)
355
+ end
356
+ end
357
+ end
361
358
 
362
359
  end
363
360
  end
@@ -1,5 +1,3 @@
1
- require "pwrake/cache_aware_queue.rb"
2
-
3
1
  module Pwrake
4
2
 
5
3
  class TaskConditionVariable < ConditionVariable
@@ -81,6 +79,47 @@ module Pwrake
81
79
  end
82
80
 
83
81
 
82
+ # LIFO + HRF
83
+ class LifoHrfQueueArray < Array
84
+ def initialize(n)
85
+ @n = (n>0) ? n : 1
86
+ @count = []
87
+ end
88
+
89
+ def push(t)
90
+ super(t)
91
+ r = t.rank
92
+ @count[r] = (@count[r]||0) + 1
93
+ end
94
+
95
+ def shift
96
+ if empty?
97
+ return nil
98
+ end
99
+ (@count.size-1).downto(0) do |r|
100
+ c = @count[r]
101
+ if c && c>0
102
+ t = (c<=@n) ? pop_last_rank(r) : pop
103
+ @count[t.rank] -= 1
104
+ return t
105
+ end
106
+ end
107
+ nil
108
+ end
109
+
110
+ def pop_last_rank(r)
111
+ (size-1).downto(0) do |i|
112
+ t = at(i)
113
+ if t.rank == r
114
+ delete_at(i)
115
+ return t
116
+ end
117
+ end
118
+ nil
119
+ end
120
+ end
121
+
122
+
84
123
  # Rank-Even Last In First Out
85
124
  class RankQueueArray
86
125
  def initialize(n)
@@ -338,6 +377,8 @@ module Pwrake
338
377
  @array_class = FifoQueueArray # Array # Fifo
339
378
  when /lifo/i
340
379
  @array_class = LifoQueueArray
380
+ when /lihr/i
381
+ @array_class = LifoHrfQueueArray
341
382
  when /rank/i
342
383
  @array_class = RankQueueArray
343
384
  else
@@ -1,3 +1,3 @@
1
1
  module Pwrake
2
- VERSION = "0.9.8"
2
+ VERSION = "0.9.9"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pwrake
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.8
4
+ version: 0.9.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - Masahiro TANAKA
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-10-17 00:00:00.000000000 Z
11
+ date: 2014-02-12 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Parallel workflow extension for Rake
14
14
  email:
@@ -18,7 +18,7 @@ executables:
18
18
  extensions: []
19
19
  extra_rdoc_files: []
20
20
  files:
21
- - .gitignore
21
+ - ".gitignore"
22
22
  - Gemfile
23
23
  - LICENSE.txt
24
24
  - README.md
@@ -26,7 +26,6 @@ files:
26
26
  - bin/pwrake
27
27
  - lib/pwrake.rb
28
28
  - lib/pwrake/application.rb
29
- - lib/pwrake/cache_aware_queue.rb
30
29
  - lib/pwrake/counter.rb
31
30
  - lib/pwrake/file_utils.rb
32
31
  - lib/pwrake/gfarm_feature.rb
@@ -77,17 +76,17 @@ require_paths:
77
76
  - lib
78
77
  required_ruby_version: !ruby/object:Gem::Requirement
79
78
  requirements:
80
- - - '>='
79
+ - - ">="
81
80
  - !ruby/object:Gem::Version
82
81
  version: '0'
83
82
  required_rubygems_version: !ruby/object:Gem::Requirement
84
83
  requirements:
85
- - - '>='
84
+ - - ">="
86
85
  - !ruby/object:Gem::Version
87
86
  version: '0'
88
87
  requirements: []
89
88
  rubyforge_project:
90
- rubygems_version: 2.0.3
89
+ rubygems_version: 2.2.0
91
90
  signing_key:
92
91
  specification_version: 4
93
92
  summary: Adding Parallel and Distributed feature to Rake
@@ -109,4 +108,3 @@ test_files:
109
108
  - spec/helper.rb
110
109
  - spec/hosts
111
110
  - spec/pwrake_spec.rb
112
- has_rdoc:
@@ -1,184 +0,0 @@
1
- module Pwrake
2
-
3
- class MTimePriorityArray < Array
4
-
5
- def order_by(item)
6
- item.input_file_mtime
7
- end
8
-
9
- def push(t)
10
- order_value = order_by(t)
11
- if empty? || order_by(last) <= order_value
12
- super(t)
13
- elsif order_by(first) > order_value
14
- unshift(t)
15
- else
16
- lower = 0
17
- upper = size-1
18
- while lower+1 < upper
19
- mid = ((lower + upper) / 2).to_i
20
- if order_by(self[mid]) <= order_value
21
- lower = mid
22
- else
23
- upper = mid
24
- end
25
- end
26
- insert(upper,t)
27
- end
28
- end
29
-
30
- def index(t)
31
- if size < 40
32
- return super(t)
33
- end
34
- order_value = t.order_by
35
- if order_by(last) < order_value || order_by(first) > order_value
36
- nil
37
- else
38
- lower = 0
39
- upper = size-1
40
- while lower+1 < upper
41
- mid = ((lower + upper) / 2).to_i
42
- if order_by(self[mid]) < order_value
43
- lower = mid
44
- else
45
- upper = mid
46
- end
47
- end
48
- mid = upper
49
- if order_by(self[mid]) == order_value
50
- Log.debug "--- TQA#index=#{mid}, order_value=#{order_value}"
51
- mid
52
- end
53
- end
54
- end
55
- end
56
-
57
-
58
- # rank-Even Last In First Out
59
- class CacheAwareQueue
60
- def initialize(n)
61
- @q = []
62
- @i = 0
63
- @size = 0
64
- @n = (n>0) ? n : 1
65
- end
66
-
67
- def push(t)
68
- r = t.rank
69
- a = @q[r]
70
- if a.nil?
71
- @q[r] = a = MTimePriorityArray.new
72
- end
73
- @size += 1
74
- a.push(t)
75
- end
76
-
77
- def size
78
- @size
79
- end
80
-
81
- def empty?
82
- @size == 0
83
- end
84
-
85
- def shift
86
- if empty?
87
- return nil
88
- elsif @size < @n*2
89
- return shift_high_rank
90
- else
91
- return shift_weighted
92
- end
93
- end
94
-
95
- def shift_high_rank
96
- (@q.size-1).downto(0) do |i|
97
- a = @q[i]
98
- next if a.nil? || a.empty?
99
- @size -= 1
100
- return pop_last_max(a)
101
- end
102
- nil
103
- end
104
-
105
- def shift_weighted
106
- weight, weight_avg = RANK_STAT.rank_weight
107
- wsum = 0.0
108
- q = []
109
- @q.each_with_index do |a,i|
110
- next if a.nil? || a.empty?
111
- w = weight[i]
112
- w = weight_avg if w.nil?
113
- # w *= a.size
114
- wsum += w
115
- q << [a,wsum]
116
- end
117
- #
118
- x = rand() * wsum
119
- Log.debug "--- shift_weighted x=#{x} wsum=#{wsum} weight=#{weight.inspect}"
120
- @size -= 1
121
- q.each do |a,w|
122
- if w > x
123
- return a.pop
124
- end
125
- end
126
- raise "ELIFO: wsum=#{wsum} x=#{x}"
127
- end
128
-
129
- def pop_last_max(a)
130
- if a.size < 2
131
- return a.pop
132
- end
133
- y_max = nil
134
- i_max = nil
135
- n = [@n, a.size].min
136
- (-n..-1).each do |i|
137
- y = a[i].input_file_size
138
- if y_max.nil? || y > y_max
139
- y_max = y
140
- i_max = i
141
- end
142
- end
143
- a.delete_at(i_max)
144
- end
145
-
146
- def first
147
- return nil if empty?
148
- @q.size.times do |i|
149
- a = @q[i]
150
- unless a.nil? || a.empty?
151
- return a.first
152
- end
153
- end
154
- end
155
-
156
- def last
157
- return nil if empty?
158
- @q.size.times do |i|
159
- a = @q[-i-1]
160
- unless a.nil? || a.empty?
161
- return a.last
162
- end
163
- end
164
- end
165
-
166
- def delete(t)
167
- n = 0
168
- @q.each do |a|
169
- if a
170
- a.delete(t)
171
- n += a.size
172
- end
173
- end
174
- @size = n
175
- end
176
-
177
- def clear
178
- @q.clear
179
- @i = 0
180
- @size = 0
181
- end
182
- end
183
-
184
- end