pwrake 0.9.7 → 0.9.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/pwrake/application.rb +1 -0
- data/lib/pwrake/cache_aware_queue.rb +184 -0
- data/lib/pwrake/gfarm_feature.rb +5 -33
- data/lib/pwrake/gfwhere_pool.rb +112 -0
- data/lib/pwrake/locality_aware_queue.rb +15 -13
- data/lib/pwrake/master.rb +13 -5
- data/lib/pwrake/option.rb +14 -9
- data/lib/pwrake/report/parallelism.rb +154 -29
- data/lib/pwrake/report/report.rb +14 -6
- data/lib/pwrake/report/report_multi.rb +2 -2
- data/lib/pwrake/shell.rb +13 -17
- data/lib/pwrake/task_algorithm.rb +136 -15
- data/lib/pwrake/task_queue.rb +310 -67
- data/lib/pwrake/version.rb +1 -1
- metadata +4 -2
data/lib/pwrake/task_queue.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require "pwrake/cache_aware_queue.rb"
|
2
|
+
|
1
3
|
module Pwrake
|
2
4
|
|
3
5
|
class TaskConditionVariable < ConditionVariable
|
@@ -6,7 +8,12 @@ module Pwrake
|
|
6
8
|
end
|
7
9
|
end
|
8
10
|
|
11
|
+
|
9
12
|
class PriorityQueueArray < Array
|
13
|
+
def initialize(n)
|
14
|
+
super()
|
15
|
+
end
|
16
|
+
|
10
17
|
def push(t)
|
11
18
|
task_id = t.task_id
|
12
19
|
if empty? || last.task_id <= task_id
|
@@ -55,80 +62,324 @@ module Pwrake
|
|
55
62
|
end
|
56
63
|
end # PriorityQueueArray
|
57
64
|
|
65
|
+
|
58
66
|
class LifoQueueArray < Array
|
67
|
+
def initialize(n)
|
68
|
+
super()
|
69
|
+
end
|
70
|
+
|
59
71
|
def shift
|
60
72
|
pop
|
61
73
|
end
|
62
74
|
end
|
63
75
|
|
76
|
+
|
77
|
+
class FifoQueueArray < Array
|
78
|
+
def initialize(n)
|
79
|
+
super()
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
|
84
|
+
# Rank-Even Last In First Out
|
85
|
+
class RankQueueArray
|
86
|
+
def initialize(n)
|
87
|
+
@q = []
|
88
|
+
@size = 0
|
89
|
+
@n = (n>0) ? n : 1
|
90
|
+
end
|
91
|
+
|
92
|
+
def push(t)
|
93
|
+
r = t.rank
|
94
|
+
a = @q[r]
|
95
|
+
if a.nil?
|
96
|
+
@q[r] = a = []
|
97
|
+
end
|
98
|
+
@size += 1
|
99
|
+
a.push(t)
|
100
|
+
end
|
101
|
+
|
102
|
+
def size
|
103
|
+
@size
|
104
|
+
end
|
105
|
+
|
106
|
+
def empty?
|
107
|
+
@size == 0
|
108
|
+
end
|
109
|
+
|
110
|
+
def shift
|
111
|
+
if empty?
|
112
|
+
return nil
|
113
|
+
end
|
114
|
+
(@q.size-1).downto(0) do |i|
|
115
|
+
a = @q[i]
|
116
|
+
next if a.nil? || a.empty?
|
117
|
+
@size -= 1
|
118
|
+
if a.size <= @n
|
119
|
+
return pop_last_max(a)
|
120
|
+
else
|
121
|
+
return shift_weighted
|
122
|
+
end
|
123
|
+
end
|
124
|
+
raise "ELIFO: @q=#{@q.inspect}"
|
125
|
+
end
|
126
|
+
|
127
|
+
def shift_weighted
|
128
|
+
weight, weight_avg = RANK_STAT.rank_weight
|
129
|
+
wsum = 0.0
|
130
|
+
q = []
|
131
|
+
@q.each_with_index do |a,i|
|
132
|
+
next if a.nil? || a.empty?
|
133
|
+
w = weight[i]
|
134
|
+
w = weight_avg if w.nil?
|
135
|
+
# w *= a.size
|
136
|
+
wsum += w
|
137
|
+
q << [a,wsum]
|
138
|
+
end
|
139
|
+
#
|
140
|
+
x = rand() * wsum
|
141
|
+
Log.debug "--- shift_weighted x=#{x} wsum=#{wsum} weight=#{weight.inspect}"
|
142
|
+
q.each do |a,w|
|
143
|
+
if w > x
|
144
|
+
return a.pop
|
145
|
+
end
|
146
|
+
end
|
147
|
+
raise "ELIFO: wsum=#{wsum} x=#{x}"
|
148
|
+
end
|
149
|
+
|
150
|
+
def pop_last_max(a)
|
151
|
+
if a.size < 2
|
152
|
+
return a.pop
|
153
|
+
end
|
154
|
+
y_max = nil
|
155
|
+
i_max = nil
|
156
|
+
n = [@n, a.size].min
|
157
|
+
(-n..-1).each do |i|
|
158
|
+
y = a[i].input_file_size
|
159
|
+
if y_max.nil? || y > y_max
|
160
|
+
y_max = y
|
161
|
+
i_max = i
|
162
|
+
end
|
163
|
+
end
|
164
|
+
a.delete_at(i_max)
|
165
|
+
end
|
166
|
+
|
167
|
+
def first
|
168
|
+
return nil if empty?
|
169
|
+
@q.size.times do |i|
|
170
|
+
a = @q[i]
|
171
|
+
unless a.nil? || a.empty?
|
172
|
+
return a.first
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
def last
|
178
|
+
return nil if empty?
|
179
|
+
@q.size.times do |i|
|
180
|
+
a = @q[-i-1]
|
181
|
+
unless a.nil? || a.empty?
|
182
|
+
return a.last
|
183
|
+
end
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
def delete(t)
|
188
|
+
n = 0
|
189
|
+
@q.each do |a|
|
190
|
+
if a
|
191
|
+
a.delete(t)
|
192
|
+
n += a.size
|
193
|
+
end
|
194
|
+
end
|
195
|
+
@size = n
|
196
|
+
end
|
197
|
+
|
198
|
+
def clear
|
199
|
+
@q.clear
|
200
|
+
@size = 0
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
|
205
|
+
class NoActionQueue
|
206
|
+
def initialize
|
207
|
+
@que = []
|
208
|
+
@num_waiting = 0
|
209
|
+
@mutex = Mutex.new
|
210
|
+
@cond = ConditionVariable.new
|
211
|
+
@halt = false
|
212
|
+
@th_end = {}
|
213
|
+
prio = Pwrake.application.pwrake_options['NOACTION_QUEUE_PRIORITY'] || 'fifo'
|
214
|
+
case prio
|
215
|
+
when /fifo/i
|
216
|
+
@prio = 0
|
217
|
+
Log.debug "--- NOACTION_QUEUE_PRIORITY=FIFO"
|
218
|
+
when /lifo/i
|
219
|
+
@prio = 1
|
220
|
+
Log.debug "--- NOACTION_QUEUE_PRIORITY=LIFO"
|
221
|
+
when /rand/i
|
222
|
+
@prio = 2
|
223
|
+
Log.debug "--- NOACTION_QUEUE_PRIORITY=RAND"
|
224
|
+
else
|
225
|
+
raise RuntimeError,"unknown option for NOACTION_QUEUE_PRIORITY: "+prio
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
229
|
+
def push(obj)
|
230
|
+
if @halt
|
231
|
+
@que.push obj
|
232
|
+
else
|
233
|
+
@mutex.synchronize do
|
234
|
+
@que.push obj
|
235
|
+
@cond.signal
|
236
|
+
end
|
237
|
+
end
|
238
|
+
end
|
239
|
+
alias << push
|
240
|
+
alias enq push
|
241
|
+
|
242
|
+
def pop
|
243
|
+
@mutex.synchronize do
|
244
|
+
t = Time.now
|
245
|
+
while true
|
246
|
+
if @th_end.delete(Thread.current)
|
247
|
+
return false
|
248
|
+
elsif @halt
|
249
|
+
@cond.wait @mutex
|
250
|
+
elsif @que.empty?
|
251
|
+
if @finished
|
252
|
+
@cond.signal
|
253
|
+
return false
|
254
|
+
end
|
255
|
+
@cond.wait @mutex
|
256
|
+
else
|
257
|
+
case @prio
|
258
|
+
when 0
|
259
|
+
x = @que.shift
|
260
|
+
when 1
|
261
|
+
x = @que.pop
|
262
|
+
when 2
|
263
|
+
x = @que.delete_at(rand(@que.size))
|
264
|
+
end
|
265
|
+
Log.debug "--- NATQ#deq %.6f sec #{x.inspect}"%[Time.now-t]
|
266
|
+
return x
|
267
|
+
end
|
268
|
+
end
|
269
|
+
end
|
270
|
+
end
|
271
|
+
|
272
|
+
alias shift pop
|
273
|
+
alias deq pop
|
274
|
+
|
275
|
+
def halt
|
276
|
+
@mutex.lock
|
277
|
+
@halt = true
|
278
|
+
end
|
279
|
+
|
280
|
+
def resume
|
281
|
+
@halt = false
|
282
|
+
@mutex.unlock
|
283
|
+
@cond.broadcast
|
284
|
+
end
|
285
|
+
|
286
|
+
def empty?
|
287
|
+
@que.empty?
|
288
|
+
end
|
289
|
+
|
290
|
+
def clear
|
291
|
+
@que.clear
|
292
|
+
end
|
293
|
+
|
294
|
+
def length
|
295
|
+
@que.length
|
296
|
+
end
|
297
|
+
alias size length
|
298
|
+
|
299
|
+
def first
|
300
|
+
@que.first
|
301
|
+
end
|
302
|
+
|
303
|
+
def last
|
304
|
+
@que.last
|
305
|
+
end
|
306
|
+
|
307
|
+
def finish
|
308
|
+
@finished = true
|
309
|
+
@cond.broadcast
|
310
|
+
end
|
311
|
+
|
312
|
+
def thread_end(th)
|
313
|
+
@th_end[th] = true
|
314
|
+
@cond.broadcast
|
315
|
+
end
|
316
|
+
|
317
|
+
def stop
|
318
|
+
clear
|
319
|
+
finish
|
320
|
+
end
|
321
|
+
end
|
322
|
+
|
323
|
+
|
64
324
|
class TaskQueue
|
65
325
|
|
66
|
-
def initialize(
|
326
|
+
def initialize(core_list)
|
67
327
|
@finished = false
|
68
328
|
@halt = false
|
69
329
|
@mutex = Mutex.new
|
70
|
-
@th_end =
|
330
|
+
@th_end = {}
|
71
331
|
@enable_steal = true
|
72
|
-
@
|
73
|
-
|
74
|
-
case
|
332
|
+
@q_noaction = NoActionQueue.new
|
333
|
+
pri = Pwrake.application.pwrake_options['QUEUE_PRIORITY'] || "RANK"
|
334
|
+
case pri
|
75
335
|
when /dfs/i
|
76
336
|
@array_class = PriorityQueueArray
|
77
337
|
when /fifo/i
|
78
|
-
@array_class = Array # Fifo
|
338
|
+
@array_class = FifoQueueArray # Array # Fifo
|
79
339
|
when /lifo/i
|
80
340
|
@array_class = LifoQueueArray
|
341
|
+
when /rank/i
|
342
|
+
@array_class = RankQueueArray
|
81
343
|
else
|
82
|
-
raise RuntimeError,"unknown option for QUEUE_PRIORITY"
|
344
|
+
raise RuntimeError,"unknown option for QUEUE_PRIORITY: "+pri
|
83
345
|
end
|
84
346
|
Log.debug "--- TQ#initialize @array_class=#{@array_class.inspect}"
|
85
|
-
init_queue(
|
347
|
+
init_queue(core_list)
|
86
348
|
end
|
87
349
|
|
88
|
-
def init_queue(
|
350
|
+
def init_queue(core_list)
|
89
351
|
@cv = TaskConditionVariable.new
|
90
|
-
@
|
352
|
+
@q_input = @array_class.new(core_list.size)
|
91
353
|
@q_later = Array.new
|
92
354
|
end
|
93
355
|
|
94
356
|
attr_reader :mutex
|
95
357
|
attr_accessor :enable_steal
|
96
358
|
|
97
|
-
def reserve(item)
|
98
|
-
@reservation[item] = Thread.current
|
99
|
-
end
|
100
|
-
|
101
359
|
def halt
|
102
|
-
@
|
103
|
-
|
104
|
-
|
360
|
+
@q_noaction.halt
|
361
|
+
@mutex.lock
|
362
|
+
@halt = true
|
105
363
|
end
|
106
364
|
|
107
365
|
def resume
|
108
|
-
@
|
109
|
-
|
110
|
-
|
111
|
-
|
366
|
+
@halt = false
|
367
|
+
@q_noaction.resume
|
368
|
+
@mutex.unlock
|
369
|
+
@cv.broadcast
|
112
370
|
end
|
113
371
|
|
114
372
|
def synchronize(condition)
|
115
373
|
ret = nil
|
116
374
|
if condition
|
117
|
-
|
118
|
-
|
119
|
-
begin
|
375
|
+
halt
|
376
|
+
begin
|
120
377
|
ret = yield
|
121
|
-
|
122
|
-
|
123
|
-
@halt = false
|
124
|
-
@mutex.unlock
|
378
|
+
ensure
|
379
|
+
resume
|
125
380
|
end
|
126
381
|
else
|
127
|
-
|
128
|
-
end
|
129
|
-
@reserved_q.keys.each do |th|
|
130
|
-
Log.debug "--- run #{th}";
|
131
|
-
th.run
|
382
|
+
ret = yield
|
132
383
|
end
|
133
384
|
ret
|
134
385
|
end
|
@@ -137,46 +388,41 @@ module Pwrake
|
|
137
388
|
def enq(item)
|
138
389
|
Log.debug "--- TQ#enq #{item.name}"
|
139
390
|
t0 = Time.now
|
140
|
-
if
|
141
|
-
|
391
|
+
if item.actions.empty?
|
392
|
+
@q_noaction.enq(item)
|
393
|
+
elsif @halt
|
394
|
+
enq_body(item)
|
142
395
|
else
|
143
396
|
@mutex.synchronize do
|
144
|
-
|
145
|
-
|
397
|
+
enq_body(item)
|
398
|
+
@cv.signal(item.suggest_location)
|
146
399
|
end
|
147
400
|
end
|
148
|
-
@reserved_q.keys.each{|th|
|
149
|
-
Log.debug "--- run #{th}";
|
150
|
-
th.run
|
151
|
-
}
|
152
401
|
Log.debug "--- TQ#enq #{item.name} enq_time=#{Time.now-t0}"
|
153
402
|
end
|
154
403
|
|
155
404
|
def enq_body(item)
|
156
|
-
|
157
|
-
@reserved_q[th] = item
|
158
|
-
else
|
159
|
-
enq_impl(item)
|
160
|
-
end
|
405
|
+
enq_impl(item)
|
161
406
|
end
|
162
407
|
|
163
|
-
def enq_impl(
|
164
|
-
if
|
165
|
-
@
|
408
|
+
def enq_impl(t)
|
409
|
+
if t.has_input_file?
|
410
|
+
@q_input.push(t)
|
166
411
|
else
|
167
|
-
@q_later.push(
|
412
|
+
@q_later.push(t)
|
168
413
|
end
|
169
414
|
end
|
170
415
|
|
171
|
-
|
172
416
|
# deq
|
173
417
|
def deq(hint=nil)
|
418
|
+
if hint == '(noaction)'
|
419
|
+
return @q_noaction.deq
|
420
|
+
end
|
174
421
|
n = 0
|
175
422
|
loop do
|
176
423
|
@mutex.synchronize do
|
177
424
|
t0 = Time.now
|
178
|
-
if @th_end.
|
179
|
-
@th_end.shift
|
425
|
+
if @th_end.delete(Thread.current)
|
180
426
|
return false
|
181
427
|
|
182
428
|
elsif @halt
|
@@ -184,17 +430,11 @@ module Pwrake
|
|
184
430
|
@cv.wait(@mutex)
|
185
431
|
n = 0
|
186
432
|
|
187
|
-
elsif item = @reserved_q.delete(Thread.current)
|
188
|
-
Log.debug "--- deq from reserved_q=#{item.inspect}"
|
189
|
-
return item
|
190
|
-
|
191
433
|
elsif empty? # no item in queue
|
192
|
-
#Log.debug "--- empty=true in #{self.class}#deq @finished=#{@finished.inspect}"
|
193
434
|
if @finished
|
194
|
-
|
435
|
+
@cv.signal
|
195
436
|
return false
|
196
437
|
end
|
197
|
-
#Log.debug "--- waiting in #{self.class}#deq @finished=#{@finished.inspect}"
|
198
438
|
@cv.wait(@mutex)
|
199
439
|
n = 0
|
200
440
|
|
@@ -204,36 +444,38 @@ module Pwrake
|
|
204
444
|
Log.debug "--- TQ#deq #{t_inspect} deq_time=#{Time.now-t0}"
|
205
445
|
return t
|
206
446
|
end
|
207
|
-
#@cv.signal([hint])
|
208
447
|
n += 1
|
209
448
|
end
|
210
449
|
end
|
211
|
-
#Thread.pass
|
212
450
|
end
|
213
451
|
end
|
214
452
|
|
215
453
|
def deq_impl(hint,n)
|
216
454
|
Log.debug "--- TQ#deq_impl #{@q.inspect}"
|
217
|
-
@
|
455
|
+
@q_input.shift || @q_later.shift
|
218
456
|
end
|
219
457
|
|
220
458
|
def clear
|
221
|
-
@
|
459
|
+
@q_noaction.clear
|
460
|
+
@q_input.clear
|
222
461
|
@q_later.clear
|
223
|
-
@reserved_q.clear
|
224
462
|
end
|
225
463
|
|
226
464
|
def empty?
|
227
|
-
@
|
465
|
+
@q_noaction.empty? &&
|
466
|
+
@q_input.empty? &&
|
467
|
+
@q_later.empty?
|
228
468
|
end
|
229
469
|
|
230
470
|
def finish
|
231
471
|
Log.debug "--- TQ#finish"
|
472
|
+
@q_noaction.finish
|
232
473
|
@finished = true
|
233
474
|
@cv.broadcast
|
234
475
|
end
|
235
476
|
|
236
477
|
def stop
|
478
|
+
@q_noaction.stop
|
237
479
|
@mutex.synchronize do
|
238
480
|
clear
|
239
481
|
finish
|
@@ -241,8 +483,9 @@ module Pwrake
|
|
241
483
|
end
|
242
484
|
|
243
485
|
def thread_end(th)
|
244
|
-
@th_end
|
486
|
+
@th_end[th] = true
|
245
487
|
@cv.broadcast
|
488
|
+
@q_noaction.thread_end(th)
|
246
489
|
end
|
247
490
|
|
248
491
|
def after_check(tasks)
|
data/lib/pwrake/version.rb
CHANGED
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.
|
4
|
+
version: 0.9.8
|
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-
|
11
|
+
date: 2013-10-17 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: Parallel workflow extension for Rake
|
14
14
|
email:
|
@@ -26,9 +26,11 @@ files:
|
|
26
26
|
- bin/pwrake
|
27
27
|
- lib/pwrake.rb
|
28
28
|
- lib/pwrake/application.rb
|
29
|
+
- lib/pwrake/cache_aware_queue.rb
|
29
30
|
- lib/pwrake/counter.rb
|
30
31
|
- lib/pwrake/file_utils.rb
|
31
32
|
- lib/pwrake/gfarm_feature.rb
|
33
|
+
- lib/pwrake/gfwhere_pool.rb
|
32
34
|
- lib/pwrake/graphviz.rb
|
33
35
|
- lib/pwrake/locality_aware_queue.rb
|
34
36
|
- lib/pwrake/logger.rb
|