pwrake 0.9.7 → 0.9.8

Sign up to get free protection for your applications and to get access to all the features.
@@ -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(*args)
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
- @reservation = {}
73
- @reserved_q = {}
74
- case Pwrake.application.pwrake_options['QUEUE_PRIORITY']||"DFS"
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(*args)
347
+ init_queue(core_list)
86
348
  end
87
349
 
88
- def init_queue(*args)
350
+ def init_queue(core_list)
89
351
  @cv = TaskConditionVariable.new
90
- @q_prior = @array_class.new
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
- @mutex.synchronize do
103
- @halt = true
104
- end
360
+ @q_noaction.halt
361
+ @mutex.lock
362
+ @halt = true
105
363
  end
106
364
 
107
365
  def resume
108
- @mutex.synchronize do
109
- @halt = false
110
- @cv.broadcast
111
- end
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
- @mutex.lock
118
- @halt = true
119
- begin
375
+ halt
376
+ begin
120
377
  ret = yield
121
- @cv.broadcast
122
- ensure
123
- @halt = false
124
- @mutex.unlock
378
+ ensure
379
+ resume
125
380
  end
126
381
  else
127
- ret = yield
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 @halt
141
- enq_body(item)
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
- enq_body(item)
145
- @cv.signal(item.suggest_location)
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
- if th = @reservation[item]
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(item)
164
- if item.prior?
165
- @q_prior.push(item)
408
+ def enq_impl(t)
409
+ if t.has_input_file?
410
+ @q_input.push(t)
166
411
  else
167
- @q_later.push(item)
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.first == Thread.current
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
- @cv.signal
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
- @q_prior.shift || @q_later.shift
455
+ @q_input.shift || @q_later.shift
218
456
  end
219
457
 
220
458
  def clear
221
- @q_prior.clear
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
- @q_prior.empty? && @q_later.empty? && @reserved_q.empty?
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.push(th)
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)
@@ -1,3 +1,3 @@
1
1
  module Pwrake
2
- VERSION = "0.9.7"
2
+ VERSION = "0.9.8"
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.7
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-09-06 00:00:00.000000000 Z
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