pwrake 2.2.9 → 2.3.0

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.
@@ -0,0 +1,72 @@
1
+ require "pwrake/queue/task_queue"
2
+ require "pwrake/queue/queue_array"
3
+ require "pwrake/queue/no_action_queue"
4
+
5
+ module Pwrake
6
+
7
+ class NonLocalityQueue
8
+
9
+ def initialize(hostinfo_by_id, array_class, median_core, group_map=nil)
10
+ @hostinfo_by_id = hostinfo_by_id
11
+ @array_class = array_class
12
+ @median_core = median_core
13
+ @disable_rank = Rake.application.pwrake_options['DISABLE_RANK_PRIORITY']
14
+ Log.debug "#{self.class}: @disable_rank=#{@disable_rank.inspect}"
15
+ @q_input = @array_class.new(@median_core)
16
+ @q_no_input = FifoQueueArray.new(@median_core)
17
+ @turns = [0]
18
+ end
19
+
20
+ attr_reader :turns
21
+
22
+ def enq_impl(tw)
23
+ if tw.has_input_file?
24
+ @q_input.push(tw)
25
+ else
26
+ @q_no_input.push(tw)
27
+ end
28
+ end
29
+
30
+ def turn_empty?(turn)
31
+ empty?
32
+ end
33
+
34
+ def deq_start
35
+ @rank = @disable_rank ? 0 : @q_input.find_rank(@median_core)
36
+ end
37
+
38
+ def deq_impl(host_info, turn)
39
+ case turn
40
+ when 0
41
+ @q_input.shift(host_info,@rank) ||
42
+ @q_no_input.shift(host_info,@rank)
43
+ else
44
+ raise "invalid turn: #{turn}"
45
+ end
46
+ end
47
+
48
+ def size
49
+ @q_input.size +
50
+ @q_no_input.size
51
+ end
52
+
53
+ def clear
54
+ @q_input.clear
55
+ @q_no_input.clear
56
+ end
57
+
58
+ def empty?
59
+ @q_input.empty? &&
60
+ @q_no_input.empty?
61
+ end
62
+
63
+ def inspect_q
64
+ TaskQueue._qstr("input", @q_input) +
65
+ TaskQueue._qstr("no_input",@q_no_input)
66
+ end
67
+
68
+ def drop_host(host_info)
69
+ end
70
+
71
+ end
72
+ end
@@ -3,227 +3,137 @@ require "pwrake/task/task_rank"
3
3
 
4
4
  module Pwrake
5
5
 
6
- class PriorityQueueArray < Array
7
- def initialize(n)
8
- super()
9
- end
10
-
11
- def shift
12
- pop
13
- end
6
+ class QueueArray < Array
14
7
 
15
- def push(t)
16
- priority = t.priority
17
- if empty? || last.priority <= priority
18
- super(t)
19
- elsif first.priority > priority
20
- unshift(t)
21
- else
22
- lower = 0
23
- upper = size-1
24
- while lower+1 < upper
25
- mid = ((lower + upper) / 2).to_i
26
- if self[mid].priority <= priority
27
- lower = mid
28
- else
29
- upper = mid
30
- end
31
- end
32
- insert(upper,t)
33
- end
8
+ def initialize(nproc)
9
+ @nproc = nproc
10
+ super()
34
11
  end
35
12
 
36
- def index(t)
37
- if size < 40
38
- return super(t)
39
- end
40
- priority = t.priority
41
- if last.priority < priority || first.priority > priority
42
- nil
43
- else
44
- lower = 0
45
- upper = size-1
46
- while lower+1 < upper
47
- mid = ((lower + upper) / 2).to_i
48
- if self[mid].priority < priority
49
- lower = mid
13
+ def shift(host_info, req_rank=0)
14
+ i_tried = nil
15
+ size.times do |i|
16
+ tw = q_at(i)
17
+ if tw.rank >= req_rank && tw.acceptable_for(host_info)
18
+ if tw.tried_host?(host_info)
19
+ i_tried ||= i
50
20
  else
51
- upper = mid
21
+ Log.debug "#{self.class}: task=#{tw.name} i=#{i}/#{size} rank=#{tw.rank}"
22
+ return q_delete_at(i)
52
23
  end
53
24
  end
54
- mid = upper
55
- if self[mid].priority == priority
56
- Log.debug "TQA#index=#{mid}, priority=#{priority}"
57
- mid
58
- end
59
25
  end
60
- end
61
- end # PriorityQueueArray
62
-
63
-
64
- class LifoQueueArray < Array
65
- def initialize(n_cores=nil)
66
- super()
67
- end
68
-
69
- def shift(host_info=nil)
70
- return super() unless host_info
71
- i_tried = []
72
- (size-1).downto(0) do |i|
73
- tw = at(i)
74
- if tw.tried_host?(host_info)
75
- i_tried << i
76
- elsif tw.acceptable_for(host_info)
77
- return delete_at(i)
78
- end
79
- end
80
- i_tried.each do |i|
81
- tw = at(i)
82
- if tw.acceptable_for(host_info)
83
- return delete_at(i)
84
- end
26
+ if i_tried
27
+ tw = q_at(i_tried)
28
+ Log.debug "#{self.class}(retry): task=#{tw.name} i=#{i_tried}/#{size} rank=#{tw.rank}"
29
+ return q_delete_at(i_tried)
85
30
  end
86
31
  nil
87
32
  end
88
- end
89
33
 
90
- class FifoQueueArray < Array
91
- def initialize(n_cores=nil)
92
- super()
93
- end
94
-
95
- def shift(host_info=nil)
96
- return super() unless host_info
97
- i_tried = []
98
- size.times do |i|
99
- tw = at(i)
100
- if tw.tried_host?(host_info)
101
- i_tried << i
102
- elsif tw.acceptable_for(host_info)
103
- return delete_at(i)
104
- end
34
+ def find_rank(ncore)
35
+ if empty?
36
+ return 0
105
37
  end
106
- i_tried.each do |i|
107
- tw = at(i)
108
- if tw.acceptable_for(host_info)
109
- return delete_at(i)
38
+ count = []
39
+ size.times do |i|
40
+ tw = q_at(i)
41
+ r = tw.rank
42
+ c = (count[r]||0) + tw.use_cores(ncore)
43
+ if c >= @nproc
44
+ return r
110
45
  end
46
+ count[r] = c
111
47
  end
112
- nil
48
+ count.size - 1
113
49
  end
114
- end
115
50
 
116
- class RankCounter
51
+ end
117
52
 
118
- def initialize
119
- @ntask = []
120
- @nproc = 0
121
- @mutex = Mutex.new
53
+ class LifoQueueArray < QueueArray
54
+ def q_at(i)
55
+ at(size-1-i)
122
56
  end
123
-
124
- def add_nproc(n)
125
- @mutex.synchronize do
126
- @nproc += n
127
- end
57
+ def q_delete_at(i)
58
+ delete_at(size-1-i)
128
59
  end
60
+ end
129
61
 
130
- def incr(r)
131
- @mutex.synchronize do
132
- @ntask[r] = (@ntask[r]||0) + 1
133
- end
62
+ class FifoQueueArray < QueueArray
63
+ def q_at(i)
64
+ at(i)
134
65
  end
135
-
136
- def get_task
137
- @mutex.synchronize do
138
- (@ntask.size-1).downto(0) do |r|
139
- c = @ntask[r]
140
- if c && c>0
141
- t = yield(c, @nproc, r)
142
- #t = (c<=@n) ? pop_last_rank(r) : pop
143
- if t
144
- @ntask[t.rank] -= 1
145
- Log.debug "RankCount rank=#{r} nproc=#{@nproc} count=#{c} t.rank=#{t.rank} t.name=#{t.name}"
146
- end
147
- return t
148
- end
149
- end
150
- end
151
- nil
66
+ def q_delete_at(i)
67
+ delete_at(i)
152
68
  end
153
69
  end
154
70
 
71
+
155
72
  # HRF mixin module
156
73
  module HrfQueue
157
74
 
158
- def hrf_init(n_cores=nil)
159
- @nproc = n_cores || 0
75
+ def hrf_init(nproc)
76
+ @nproc = nproc
160
77
  @count = []
161
78
  end
162
79
 
163
80
  def hrf_push(t)
164
81
  r = t.rank
165
- c = @count[r]
166
- @count[r] = (c) ? c+1 : 1
82
+ n = t.use_cores(@nproc)
83
+ @count[r] = (@count[r] || 0) + n
167
84
  end
168
85
 
169
- def hrf_get(host_info)
170
- (@count.size-1).downto(0) do |r|
86
+ def hrf_get(host_info, rank)
87
+ (@count.size-1).downto(rank) do |r|
171
88
  c = @count[r]
172
89
  if c && c>0
173
- t = (c <= @nproc) ? pop_last_rank(r,host_info) : pop_super(host_info)
90
+ t = (c <= @nproc) ?
91
+ pop_last_rank(r, host_info) :
92
+ pop_super(host_info, rank)
174
93
  hrf_delete(t) if t
175
94
  return t
176
95
  end
177
96
  end
178
- raise "no element"
97
+ Log.debug "#{self.class}#hrf_get: no item for rank=#{rank} @count=#{@count.inspect}"
179
98
  nil
180
99
  end
181
100
 
182
- def pop_last_rank(r,host_info)
183
- i_tried = []
184
- (size-1).downto(0) do |i|
185
- tw = at(i)
186
- if tw.rank == r
101
+ def pop_last_rank(r, host_info)
102
+ i_tried = nil
103
+ size.times do |i|
104
+ tw = q_at(i)
105
+ if tw.rank == r && tw.acceptable_for(host_info)
187
106
  if tw.tried_host?(host_info)
188
- i_tried << i
189
- elsif tw.acceptable_for(host_info)
190
- return delete_at(i)
107
+ i_tried ||= i
108
+ else
109
+ Log.debug "#{self.class}: task=#{tw.name} i=#{i}/#{size} rank=#{tw.rank}"
110
+ return q_delete_at(i)
191
111
  end
192
112
  end
193
113
  end
194
- i_tried.each do |i|
195
- tw = at(i)
196
- if tw.acceptable_for(host_info)
197
- return delete_at(i)
198
- end
114
+ if i_tried
115
+ tw = q_at(i_tried)
116
+ Log.debug "#{self.class}(retry): task=#{tw.name} i=#{i_tried}/#{size} rank=#{tw.rank}"
117
+ return q_delete_at(i_tried)
199
118
  end
200
119
  nil
201
120
  end
202
121
 
203
122
  def hrf_delete(t)
204
- @count[t.rank] -= 1
205
- end
206
-
207
- def check(t=nil)
208
- sum = 0
209
- @count.each{|x| sum+=x if x}
210
- if size != sum
211
- #$stderr.puts self.inspect
212
- #$stderr.puts t.inspect if t
213
- raise "sise != @count.sum"
214
- end
123
+ @count[t.rank] -= t.use_cores(@nproc)
215
124
  end
216
125
  end
217
126
 
127
+
218
128
  # LIFO + HRF
219
129
  class LifoHrfQueueArray
220
130
  include HrfQueue
221
131
  extend Forwardable
222
- def_delegators :@a, :empty?, :size, :first, :last, :at, :delete_at
132
+ def_delegators :@a, :empty?, :size, :first, :last, :q_at, :q_delete_at, :find_rank
223
133
 
224
- def initialize(n_cores)
225
- @a = LifoQueueArray.new
226
- hrf_init(n_cores)
134
+ def initialize(nproc)
135
+ @a = LifoQueueArray.new(nproc)
136
+ hrf_init(nproc)
227
137
  end
228
138
 
229
139
  def push(t)
@@ -231,9 +141,9 @@ module Pwrake
231
141
  hrf_push(t)
232
142
  end
233
143
 
234
- def shift(host_info=nil)
144
+ def shift(host_info, rank)
235
145
  return nil if empty?
236
- hrf_get(host_info)
146
+ hrf_get(host_info, rank)
237
147
  end
238
148
 
239
149
  def delete(t)
@@ -243,155 +153,8 @@ module Pwrake
243
153
  x
244
154
  end
245
155
 
246
- def pop_super(host_info)
247
- @a.shift(host_info)
248
- end
249
- end
250
-
251
-
252
- # Priority + HRF
253
- class PriorityHrfQueueArray < PriorityQueueArray
254
- include HrfQueue
255
-
256
- def initialize(n)
257
- super(n)
258
- hrf_init(n)
259
- end
260
-
261
- def push(t)
262
- super(t)
263
- hrf_push(t)
264
- end
265
-
266
- def shift
267
- return nil if empty?
268
- hrf_get
269
- end
270
-
271
- def pop_super
272
- pop
273
- end
274
- end
275
-
276
-
277
- # Rank-Even Last In First Out
278
- class RankQueueArray
279
-
280
- def initialize(n)
281
- @q = []
282
- @size = 0
283
- @n = (n>0) ? n : 1
284
- end
285
-
286
- def push(t)
287
- r = t ? t.rank : 0
288
- a = @q[r]
289
- if a.nil?
290
- @q[r] = a = []
291
- end
292
- @size += 1
293
- a.push(t)
294
- end
295
-
296
- def size
297
- @size
298
- end
299
-
300
- def empty?
301
- @size == 0
302
- end
303
-
304
- def shift
305
- if empty?
306
- return nil
307
- end
308
- (@q.size-1).downto(0) do |i|
309
- a = @q[i]
310
- next if a.nil? || a.empty?
311
- @size -= 1
312
- if a.size <= @n
313
- return pop_last_max(a)
314
- else
315
- return shift_weighted
316
- end
317
- end
318
- raise "ELIFO: @q=#{@q.inspect}"
319
- end
320
-
321
- def shift_weighted
322
- weight, weight_avg = RANK_STAT.rank_weight
323
- wsum = 0.0
324
- q = []
325
- @q.each_with_index do |a,i|
326
- next if a.nil? || a.empty?
327
- w = weight[i]
328
- w = weight_avg if w.nil?
329
- # w *= a.size
330
- wsum += w
331
- q << [a,wsum]
332
- end
333
- #
334
- x = rand() * wsum
335
- Log.debug "shift_weighted x=#{x} wsum=#{wsum} weight=#{weight.inspect}"
336
- q.each do |a,w|
337
- if w > x
338
- return a.pop
339
- end
340
- end
341
- raise "ELIFO: wsum=#{wsum} x=#{x}"
342
- end
343
-
344
- def pop_last_max(a)
345
- if a.size < 2
346
- return a.pop
347
- end
348
- y_max = nil
349
- i_max = nil
350
- n = [@n, a.size].min
351
- (-n..-1).each do |i|
352
- y = a[i].input_file_size
353
- if y_max.nil? || y > y_max
354
- y_max = y
355
- i_max = i
356
- end
357
- end
358
- a.delete_at(i_max)
359
- end
360
-
361
- def first
362
- return nil if empty?
363
- @q.size.times do |i|
364
- a = @q[i]
365
- unless a.nil? || a.empty?
366
- return a.first
367
- end
368
- end
369
- end
370
-
371
- def last
372
- return nil if empty?
373
- @q.size.times do |i|
374
- a = @q[-i-1]
375
- unless a.nil? || a.empty?
376
- return a.last
377
- end
378
- end
379
- end
380
-
381
- def delete(t)
382
- n = 0
383
- @q.each do |a|
384
- if a
385
- a.delete(t)
386
- n += a.size
387
- end
388
- end
389
- @size = n
390
- end
391
-
392
- def clear
393
- @q.clear
394
- @size = 0
156
+ def pop_super(host_info, rank)
157
+ @a.shift(host_info, rank)
395
158
  end
396
159
  end
397
160