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.
@@ -1,12 +1,14 @@
1
1
  require "pwrake/queue/queue_array"
2
2
  require "pwrake/queue/no_action_queue"
3
+ require "pwrake/queue/non_locality_queue"
3
4
 
4
5
  module Pwrake
5
6
 
6
7
  class TaskQueue
7
8
 
8
- def initialize(hostinfo_by_id, group_map=nil)
9
- @enable_steal = true
9
+ def initialize(queue_class, hostinfo_by_id, group_map=nil)
10
+ @queue_class = Pwrake.const_get(queue_class)
11
+ @hostinfo_by_id = hostinfo_by_id
10
12
  @q_no_action = NoActionQueue.new
11
13
  @q_reserved = Hash.new
12
14
  def @q_reserved.first
@@ -16,137 +18,99 @@ module Pwrake
16
18
  self[keys.last]
17
19
  end
18
20
 
19
- @hostinfo_by_id = hostinfo_by_id
20
-
21
- pri = Rake.application.pwrake_options['QUEUE_PRIORITY'] || "LIHR"
21
+ pri = Rake.application.pwrake_options['QUEUE_PRIORITY'] || "LIFO"
22
22
  case pri
23
- when /prio/i
24
- @array_class = PriorityQueueArray
25
- when /fifo/i
26
- @array_class = FifoQueueArray # Array # Fifo
27
- when /lifo/i
23
+ when /^fifo$/i
24
+ @array_class = FifoQueueArray
25
+ when /^lifo$/i
28
26
  @array_class = LifoQueueArray
29
- when /lihr/i
27
+ when /^lihr$/i
30
28
  @array_class = LifoHrfQueueArray
31
- when /prhr/i
32
- @array_class = PriorityHrfQueueArray
33
- when /rank/i
34
- @array_class = RankQueueArray
35
29
  else
36
30
  raise RuntimeError,"unknown option for QUEUE_PRIORITY: "+pri
37
31
  end
38
32
  Log.debug "@array_class=#{@array_class.inspect}"
39
- init_queue(group_map)
40
- end
41
33
 
42
- def init_queue(group_map=nil)
43
- @q_input = @array_class.new(0)
44
- @q_no_input = FifoQueueArray.new
45
- @n_turn = 1
46
- end
34
+ # median number of cores
35
+ a = @hostinfo_by_id.map{|id,host_info| host_info.ncore}.sort
36
+ n = a.size
37
+ @median_core = (n%2==0) ? (a[n/2-1]+a[n/2])/2 : a[(n-1)/2]
47
38
 
48
- attr_accessor :enable_steal
39
+ @q = @queue_class.new(hostinfo_by_id,@array_class,@median_core,group_map)
40
+ end
49
41
 
50
- # enq
51
42
  def enq(tw)
52
43
  if tw.nil? || tw.actions.empty?
53
44
  @q_no_action.push(tw)
54
45
  else
55
- enq_body(tw)
46
+ @q.enq_impl(tw)
56
47
  end
57
48
  end
58
49
 
59
- def enq_body(tw)
60
- enq_impl(tw)
61
- end
62
-
63
- def enq_impl(tw)
64
- if tw.has_input_file?
65
- @q_input.push(tw)
66
- else
67
- @q_no_input.push(tw)
50
+ def deq_task(&block)
51
+ Log.debug "deq_task from:"+(empty? ? " (empty)" : "\n#{inspect_q}")
52
+ deq_noaction_task(&block)
53
+ deq_reserve(&block)
54
+ @q.deq_start
55
+ unless @q.empty?
56
+ @q.turns.each{|turn| deq_turn(turn,&block) }
68
57
  end
69
58
  end
70
59
 
71
60
  def deq_noaction_task(&block)
72
- Log.debug "deq_noaction_task:"+(empty? ? " (empty)" : "\n#{inspect_q}")
73
61
  while tw = @q_no_action.shift
74
62
  Log.debug "deq_noaction: #{tw.name}"
75
63
  yield(tw)
76
64
  end
77
65
  end
78
66
 
79
- def deq_task(&block) # locality version
80
- Log.debug "deq_task from:"+(empty? ? " (empty)" : "\n#{inspect_q}")
81
- queued = 0
82
- @n_turn.times do |turn|
83
- next if turn_empty?(turn)
84
- queued += deq_turn(turn,&block)
67
+ def deq_reserve(&block)
68
+ @q_reserved.each do |host_info,tw|
69
+ n_idle = host_info.idle_cores || 0
70
+ n_core = tw.use_cores(host_info)
71
+ if n_idle >= n_core
72
+ @q_reserved.delete(host_info)
73
+ Log.debug "deq_reserve: #{tw.name} n_use_cores=#{n_core}"
74
+ yield(tw,host_info,n_core)
75
+ end
85
76
  end
86
77
  end
87
78
 
88
79
  def deq_turn(turn,&block)
89
- queued = 0
90
- while true
80
+ begin
91
81
  count = 0
92
82
  @hostinfo_by_id.each_value do |host_info|
93
- #Log.debug "TaskQueue#deq_turn host_info=#{host_info.name}"
94
- if turn_empty?(turn)
95
- return queued
96
- elsif (n_idle = host_info.idle_cores) && n_idle > 0
97
- if tw = @q_reserved[host_info]
98
- n_use = tw.n_used_cores(host_info)
99
- if n_idle < n_use
100
- next
101
- end
102
- @q_reserved.delete(host_info)
103
- Log.debug "deq_reserve: #{tw.name} n_use_cores=#{n_use}"
104
- elsif tw = deq_impl(host_info,turn)
105
- n_use = tw.n_used_cores(host_info)
106
- if n_idle < n_use
107
- @q_reserved[host_info] = tw
108
- Log.debug "reserve host: #{host_info.name} for #{tw.name} (#{n_use} cores)"
109
- next
110
- end
111
- Log.debug "deq: #{tw.name} n_use_cores=#{n_use}"
112
- end
113
- if tw
114
- yield(tw,host_info,n_use)
83
+ return if @q.turn_empty?(turn)
84
+ n_idle = host_info.idle_cores || 0
85
+ next if n_idle == 0 || @q_reserved[host_info]
86
+ if tw = @q.deq_impl(host_info,turn)
87
+ n_core = tw.use_cores(host_info)
88
+ if n_idle >= n_core
89
+ Log.debug "deq: #{tw.name} n_use_cores=#{n_core}"
90
+ yield(tw,host_info,n_core)
115
91
  count += 1
116
- queued += 1
92
+ else
93
+ @q_reserved[host_info] = tw
94
+ Log.debug "reserve host: #{host_info.name} for #{tw.name} (#{n_core} cores)"
117
95
  end
118
96
  end
119
97
  end
120
- break if count == 0
121
- end
122
- queued
123
- end
124
-
125
- def turn_empty?(turn)
126
- empty?
127
- end
128
-
129
- def deq_impl(host_info=nil, turn=nil)
130
- @q_no_action.shift ||
131
- @q_input.shift(host_info) ||
132
- @q_no_input.shift(host_info)
98
+ end while count > 0
133
99
  end
134
100
 
135
101
  def clear
136
102
  @q_no_action.clear
137
103
  @q_reserved.clear
138
- @q_input.clear
139
- @q_no_input.clear
104
+ @q.clear
140
105
  end
141
106
 
142
107
  def empty?
143
108
  @q_no_action.empty? &&
144
- @q_reserved.empty? &&
145
- @q_input.empty? &&
146
- @q_no_input.empty?
109
+ @q_reserved.empty? &&
110
+ @q.empty?
147
111
  end
148
112
 
149
- def _qstr(h,q)
113
+ def self._qstr(h,q)
150
114
  s = " #{h}: size=#{q.size} "
151
115
  case q.size
152
116
  when 0
@@ -156,20 +120,19 @@ module Pwrake
156
120
  when 2
157
121
  s << "[#{q.first.name}, #{q.last.name}]\n"
158
122
  else
159
- s << "[#{q.first.name},..,#{q.last.name}]\n"
123
+ s << "[#{q.first.name}, .., #{q.last.name}]\n"
160
124
  end
161
125
  s
162
126
  end
163
127
 
164
128
  def inspect_q
165
- _qstr("noaction",@q_no_action) +
166
- _qstr("input", @q_input) +
167
- _qstr("no_input",@q_no_input) +
168
- _qstr("reserved",@q_reserved)
129
+ TaskQueue._qstr("noaction",@q_no_action) +
130
+ @q.inspect_q +
131
+ TaskQueue._qstr("reserved",@q_reserved)
169
132
  end
170
133
 
171
134
  def drop_host(host_info)
135
+ @q.drop_host(host_info)
172
136
  end
173
-
174
137
  end
175
138
  end
@@ -61,13 +61,12 @@ module Pwrake
61
61
 
62
62
 
63
63
  def plot_parallelism(csvtable, base, fmt)
64
+ fimg = base+'/parallelism.'+fmt
64
65
  a = count_start_end_from_csv_table(csvtable)
65
- return if a.size < 4
66
+ return fimg if a.size < 4
66
67
 
67
68
  #density = exec_density(a)
68
69
 
69
- fimg = base+'/parallelism.'+fmt
70
-
71
70
  n = a.size
72
71
  i = 0
73
72
  y = 0
@@ -120,13 +119,12 @@ plot '-' w l notitle
120
119
 
121
120
 
122
121
  def plot_parallelism2(csvtable, base, fmt)
122
+ fimg = base+'/parallelism.'+fmt
123
123
  a = count_start_end_from_csv_table(csvtable)
124
- return if a.size < 4
124
+ return fimg if a.size < 4
125
125
 
126
126
  density = exec_density(a)
127
127
 
128
- fimg = base+'/parallelism.'+fmt
129
-
130
128
  n = a.size
131
129
  i = 0
132
130
  y = 0
@@ -20,6 +20,7 @@ module Pwrake
20
20
  def pw_search_tasks(args)
21
21
  Log.debug "#{self.class}#pw_search_tasks start, task=#{name} args=#{args.inspect}"
22
22
  cl = Pwrake.clock
23
+ TaskWrapper.clear_rank
23
24
  task_args = TaskArguments.new(arg_names, args)
24
25
  # not synchronize owing to fiber
25
26
  search_with_call_chain(nil, task_args, InvocationChain::EMPTY)
@@ -7,8 +7,19 @@ module Pwrake
7
7
  attr_accessor :subflow
8
8
 
9
9
  def parse_description(description)
10
- if /\bn_?cores?[=:]\s*([+-]?\d+)/i =~ description
11
- @ncore = $1.to_i
10
+ if /\bn_?cores?[=:]\s*(-?[\/\d]+)/i =~ description
11
+ case x = $1
12
+ when /^\/\d+$/
13
+ @ncore = ('1'+x).to_r
14
+ when /^\d+\/\d+$/
15
+ @ncore = x.to_r
16
+ when /^-?\d+$/
17
+ @ncore = x.to_i
18
+ else
19
+ m = "invalid task property: ncore=#{x.inspect}"
20
+ Log.fatal m
21
+ raise RuntimeError,m
22
+ end
12
23
  end
13
24
  if /\bretry[=:]\s*(\d+)/i =~ description
14
25
  @retry = $1.to_i
@@ -18,9 +29,13 @@ module Pwrake
18
29
  @exclusive = true
19
30
  end
20
31
  end
32
+ @reserve = Rake.application.pwrake_options["RESERVE_NODE"]
21
33
  if /\breserve[=:]\s*(\S+)/i =~ description
22
- if /^(y|t)/i =~ $1
34
+ case $1
35
+ when /^(y|t|on)/i
23
36
  @reserve = true
37
+ when /^(n|f|off)/i
38
+ @reserve = false
24
39
  end
25
40
  end
26
41
  if /\ballow[=:]\s*(\S+)/i =~ description
@@ -42,7 +57,6 @@ module Pwrake
42
57
  @disable_steal = true
43
58
  end
44
59
  end
45
- @use_cores = nil
46
60
  end
47
61
 
48
62
  def merge(prop)
@@ -55,11 +69,39 @@ module Pwrake
55
69
  @retry = prop.retry if prop.retry
56
70
  @disable_steal = prop.disable_steal if prop.disable_steal
57
71
  @subflow = prop.subflow if prop.subflow
58
- @use_cores = nil
59
72
  end
60
73
 
61
- def use_cores
62
- @use_cores ||= (@exclusive) ? 0 : (@ncore || 1)
74
+ def use_cores(arg)
75
+ case arg
76
+ when HostInfo
77
+ ppn = arg.ncore
78
+ when Integer
79
+ ppn = arg
80
+ if ppn < 1
81
+ raise "invalid ppn: #{ppn}"
82
+ end
83
+ else
84
+ raise "invalid ppn: #{ppn}"
85
+ end
86
+
87
+ if @exclusive
88
+ return ppn
89
+ end
90
+
91
+ case @ncore
92
+ when Rational
93
+ if @ncore > 0 && @ncore <= 1
94
+ return [(@ncore*ppn).to_i, 1].min
95
+ end
96
+ when 1-ppn..ppn
97
+ return (@ncore>0) ? @ncore : @ncore+ppn
98
+ when nil
99
+ return 1
100
+ end
101
+
102
+ m = "ncore=#{@ncore} is out of range of cores per node: #{ppn}"
103
+ Log.fatal m
104
+ raise RuntimeError,m
63
105
  end
64
106
 
65
107
  def accept_host(host_info)
@@ -87,19 +129,5 @@ module Pwrake
87
129
  return true
88
130
  end
89
131
 
90
- def n_used_cores(host_info=nil)
91
- n = use_cores
92
- if n == 1
93
- return 1
94
- elsif host_info
95
- return host_info.check_cores(n)
96
- elsif n < 1
97
- m = "invalid for use_cores=#{n}"
98
- Log.fatal m
99
- raise RuntimeError,m
100
- end
101
- return n
102
- end
103
-
104
132
  end
105
133
  end
@@ -9,6 +9,7 @@ module Pwrake
9
9
 
10
10
  @@current_id = 1
11
11
  @@task_logger = nil
12
+ @@instances = []
12
13
 
13
14
  def initialize(task,task_args=nil)
14
15
  @task = task
@@ -31,14 +32,17 @@ module Pwrake
31
32
  @exec_host_id = nil
32
33
  @tried_hosts = {}
33
34
  @n_retry = @property.retry || Rake.application.pwrake_options["RETRY"] || 1
35
+ @@instances << self
34
36
  end
35
37
 
36
38
  def_delegators :@task, :name, :actions, :prerequisites, :subsequents
39
+ def_delegators :@property, :use_cores
37
40
 
38
41
  attr_reader :task, :task_id, :group, :group_id, :file_stat
39
42
  attr_reader :location
40
43
  attr_reader :assigned
41
44
  attr_reader :tried_hosts
45
+ attr_reader :n_used_cores
42
46
  attr_accessor :executed
43
47
  attr_accessor :exec_host, :exec_host_id
44
48
  attr_accessor :shell_id, :status
@@ -63,6 +67,11 @@ module Pwrake
63
67
  @@task_logger.close if @@task_logger
64
68
  end
65
69
 
70
+ def self.clear_rank
71
+ Log.debug "#{self}.clear_rank"
72
+ @@instances.each{|w| w.clear_rank}
73
+ end
74
+
66
75
  def preprocess
67
76
  @time_start = Time.now
68
77
  @clock_start = Pwrake.clock
@@ -267,11 +276,15 @@ module Pwrake
267
276
  end
268
277
  @rank = max_rank + step
269
278
  end
270
- #Log.debug "Task[#{name}] rank=#{@rank.inspect}"
279
+ Log.debug "Task[#{name}] rank=#{@rank.inspect}"
271
280
  end
272
281
  @rank
273
282
  end
274
283
 
284
+ def clear_rank
285
+ @rank = nil
286
+ end
287
+
275
288
  def file_size
276
289
  @file_stat ? @file_stat.size : 0
277
290
  end
@@ -340,8 +353,8 @@ module Pwrake
340
353
  @priority || 0
341
354
  end
342
355
 
343
- def n_used_cores(host_info=nil)
344
- @n_used_cores ||= @property.n_used_cores(host_info)
356
+ def set_used_cores(ncore)
357
+ @n_used_cores = ncore
345
358
  end
346
359
 
347
360
  def acceptable_for(host_info)
@@ -354,7 +367,7 @@ module Pwrake
354
367
  if @property.reserve
355
368
  return true
356
369
  end
357
- host_info.accept_core(@property.use_cores)
370
+ host_info.accept_core(@property.use_cores(host_info.ncore))
358
371
  end
359
372
 
360
373
  def tried_host?(host_info)
@@ -1,3 +1,3 @@
1
1
  module Pwrake
2
- VERSION = "2.2.9"
2
+ VERSION = "2.3.0"
3
3
  end