pwrake 0.9.7 → 0.9.8
Sign up to get free protection for your applications and to get access to all the features.
- 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
|