pwrake 0.9.9.2 → 2.0.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.
- checksums.yaml +4 -4
- data/.gitignore +2 -0
- data/CHANGES_V2.md +90 -0
- data/{LICENSE.txt → MIT-LICENSE} +2 -3
- data/README +12 -0
- data/README.md +75 -52
- data/bin/gfwhere-pipe +23 -12
- data/bin/pwrake +22 -29
- data/bin/pwrake_branch +24 -0
- data/lib/pwrake/branch.rb +22 -0
- data/lib/pwrake/branch/branch.rb +213 -0
- data/lib/pwrake/branch/branch_application.rb +53 -0
- data/lib/pwrake/branch/fiber_queue.rb +36 -0
- data/lib/pwrake/branch/file_utils.rb +101 -0
- data/lib/pwrake/branch/shell.rb +231 -0
- data/lib/pwrake/{profiler.rb → branch/shell_profiler.rb} +28 -27
- data/lib/pwrake/branch/worker_communicator.rb +104 -0
- data/lib/pwrake/{gfarm_feature.rb → gfarm/gfarm_path.rb} +2 -100
- data/lib/pwrake/gfarm/gfarm_postprocess.rb +53 -0
- data/lib/pwrake/iomux/channel.rb +70 -0
- data/lib/pwrake/iomux/handler.rb +124 -0
- data/lib/pwrake/iomux/handler_set.rb +35 -0
- data/lib/pwrake/iomux/runner.rb +62 -0
- data/lib/pwrake/logger.rb +3 -150
- data/lib/pwrake/master.rb +30 -137
- data/lib/pwrake/master/fiber_pool.rb +69 -0
- data/lib/pwrake/master/idle_cores.rb +30 -0
- data/lib/pwrake/master/master.rb +345 -0
- data/lib/pwrake/master/master_application.rb +150 -0
- data/lib/pwrake/master/postprocess.rb +16 -0
- data/lib/pwrake/{graphviz.rb → misc/graphviz.rb} +0 -0
- data/lib/pwrake/{mcgp.rb → misc/mcgp.rb} +63 -42
- data/lib/pwrake/option/host_map.rb +158 -0
- data/lib/pwrake/option/option.rb +357 -0
- data/lib/pwrake/option/option_filesystem.rb +112 -0
- data/lib/pwrake/queue/locality_aware_queue.rb +158 -0
- data/lib/pwrake/queue/no_action_queue.rb +67 -0
- data/lib/pwrake/queue/queue_array.rb +366 -0
- data/lib/pwrake/queue/task_queue.rb +164 -0
- data/lib/pwrake/report.rb +1 -0
- data/lib/pwrake/report/parallelism.rb +9 -3
- data/lib/pwrake/report/report.rb +50 -103
- data/lib/pwrake/report/task_stat.rb +83 -0
- data/lib/pwrake/task/task_algorithm.rb +107 -0
- data/lib/pwrake/task/task_manager.rb +32 -0
- data/lib/pwrake/task/task_property.rb +98 -0
- data/lib/pwrake/task/task_rank.rb +48 -0
- data/lib/pwrake/task/task_wrapper.rb +296 -0
- data/lib/pwrake/version.rb +1 -1
- data/lib/pwrake/worker/executor.rb +169 -0
- data/lib/pwrake/worker/gfarm_directory.rb +90 -0
- data/lib/pwrake/worker/invoker.rb +199 -0
- data/lib/pwrake/worker/load.rb +14 -0
- data/lib/pwrake/worker/log_executor.rb +73 -0
- data/lib/pwrake/worker/shared_directory.rb +74 -0
- data/lib/pwrake/worker/worker_main.rb +14 -0
- data/lib/pwrake/worker/writer.rb +59 -0
- data/setup.rb +1212 -1502
- data/spec/003/Rakefile +2 -2
- data/spec/008/Rakefile +2 -1
- data/spec/009/Rakefile +1 -1
- data/spec/009/pwrake_conf.yaml +1 -3
- data/spec/hosts +0 -2
- data/spec/pwrake_spec.rb +9 -8
- metadata +50 -21
- data/lib/pwrake.rb +0 -19
- data/lib/pwrake/application.rb +0 -232
- data/lib/pwrake/counter.rb +0 -54
- data/lib/pwrake/file_utils.rb +0 -98
- data/lib/pwrake/gfwhere_pool.rb +0 -109
- data/lib/pwrake/host_list.rb +0 -88
- data/lib/pwrake/locality_aware_queue.rb +0 -413
- data/lib/pwrake/option.rb +0 -400
- data/lib/pwrake/rake_modify.rb +0 -14
- data/lib/pwrake/shell.rb +0 -186
- data/lib/pwrake/task_algorithm.rb +0 -475
- data/lib/pwrake/task_queue.rb +0 -633
- data/lib/pwrake/timer.rb +0 -22
@@ -0,0 +1,112 @@
|
|
1
|
+
module Pwrake
|
2
|
+
|
3
|
+
class Option
|
4
|
+
|
5
|
+
attr_reader :worker_option
|
6
|
+
attr_reader :worker_progs
|
7
|
+
attr_reader :queue_class
|
8
|
+
|
9
|
+
def setup_filesystem
|
10
|
+
|
11
|
+
@worker_progs = %w[ writer log_executor executor invoker shared_directory ]
|
12
|
+
@worker_option = {
|
13
|
+
:base_dir => "",
|
14
|
+
:work_dir => self['WORK_DIR'],
|
15
|
+
:log_dir => self['LOG_DIR'],
|
16
|
+
:pass_env => self['PASS_ENV'],
|
17
|
+
:ssh_option => self['SSH_OPTION'],
|
18
|
+
:shell_command => self['SHELL_COMMAND'],
|
19
|
+
:shell_rc => self['SHELL_RC'],
|
20
|
+
:heartbeat => self['HEARTBEAT']
|
21
|
+
}
|
22
|
+
|
23
|
+
if @filesystem.nil?
|
24
|
+
case mount_type
|
25
|
+
when /gfarm2fs/
|
26
|
+
self['FILESYSTEM'] = @filesystem = 'gfarm'
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
#n_noaction_th = self['NUM_NOACTION_THREADS']
|
31
|
+
|
32
|
+
case @filesystem
|
33
|
+
when 'gfarm'
|
34
|
+
require "pwrake/queue/locality_aware_queue"
|
35
|
+
require "pwrake/gfarm/gfarm_path"
|
36
|
+
GfarmPath.subdir = self['GFARM_SUBDIR']
|
37
|
+
@filesystem = 'gfarm'
|
38
|
+
base = self['GFARM_BASEDIR']
|
39
|
+
prefix = self['GFARM_PREFIX']
|
40
|
+
mntpnt = "#{base}/#{prefix}"
|
41
|
+
@worker_option.merge!({
|
42
|
+
:shared_directory => "GfarmDirectory",
|
43
|
+
:base_dir => mntpnt,
|
44
|
+
:work_dir => GfarmPath.pwd.to_s,
|
45
|
+
:gfarm2fs_option => self['GFARM2FS_OPTION'],
|
46
|
+
:gfarm2fs_debug => self['GFARM2FS_DEBUG'],
|
47
|
+
:gfarm2fs_debug_wait => self['GFARM2FS_DEBUG_WAIT'],
|
48
|
+
:single_mp => self['GFARM_SINGLE_MP']
|
49
|
+
})
|
50
|
+
@worker_progs << "gfarm_directory"
|
51
|
+
|
52
|
+
if self['DISABLE_AFFINITY']
|
53
|
+
@queue_class = "TaskQueue"
|
54
|
+
else
|
55
|
+
@queue_class = "LocalityAwareQueue"
|
56
|
+
end
|
57
|
+
#@num_noaction_threads = (n_noaction_th || [8,@host_map.num_threads].max).to_i
|
58
|
+
else
|
59
|
+
@filesystem = 'nfs'
|
60
|
+
@queue_class = "TaskQueue"
|
61
|
+
#@num_noaction_threads = (n_noaction_th || 1).to_i
|
62
|
+
@worker_option[:shared_directory] = "SharedDirectory"
|
63
|
+
end
|
64
|
+
@worker_progs << "worker_main"
|
65
|
+
Log.debug "@queue_class=#{@queue_class}"
|
66
|
+
end
|
67
|
+
|
68
|
+
def max_postprocess_pool
|
69
|
+
case @filesystem
|
70
|
+
when 'gfarm'
|
71
|
+
self['MAX_GFWHERE_WORKER']
|
72
|
+
else
|
73
|
+
1
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def postprocess(runner)
|
78
|
+
case @filesystem
|
79
|
+
when 'gfarm'
|
80
|
+
require "pwrake/gfarm/gfarm_postprocess"
|
81
|
+
GfarmPostprocess.new(runner)
|
82
|
+
else
|
83
|
+
require "pwrake/master/postprocess"
|
84
|
+
Postprocess.new(runner)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def mount_type(d=nil)
|
89
|
+
mtab = '/etc/mtab'
|
90
|
+
if File.exist?(mtab)
|
91
|
+
d ||= mountpoint_of_cwd
|
92
|
+
open(mtab,'r') do |f|
|
93
|
+
f.each_line do |l|
|
94
|
+
if /#{d} (?:type )?(\S+)/o =~ l
|
95
|
+
return $1
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
nil
|
101
|
+
end
|
102
|
+
|
103
|
+
def mountpoint_of_cwd
|
104
|
+
d = Pathname.pwd
|
105
|
+
while !d.mountpoint?
|
106
|
+
d = d.parent
|
107
|
+
end
|
108
|
+
d
|
109
|
+
end
|
110
|
+
|
111
|
+
end
|
112
|
+
end
|
@@ -0,0 +1,158 @@
|
|
1
|
+
module Pwrake
|
2
|
+
|
3
|
+
class LocalityAwareQueue < TaskQueue
|
4
|
+
|
5
|
+
def init_queue(group_map=nil)
|
6
|
+
# group_map = {gid1=>[hid1,hid2,...], ...}
|
7
|
+
@size_q = 0
|
8
|
+
@q = {}
|
9
|
+
@host_map.by_id.each{|h| @q[h.id] = @array_class.new(h.ncore)}
|
10
|
+
@q_group = {}
|
11
|
+
group_map ||= {1=>@host_map.by_id.map{|h| h.id}}
|
12
|
+
group_map.each do |gid,ary|
|
13
|
+
q1 = {} # same group
|
14
|
+
q2 = @q.dup # other groups
|
15
|
+
ary.each{|hid| q1[hid] = q2.delete(hid)}
|
16
|
+
a = [q1,q2]
|
17
|
+
ary.each{|hid| @q_group[hid] = a}
|
18
|
+
end
|
19
|
+
@q_remote = @array_class.new(0)
|
20
|
+
@disable_steal = Rake.application.pwrake_options['DISABLE_STEAL']
|
21
|
+
@last_enq_time = Time.now
|
22
|
+
@n_turn = @disable_steal ? 1 : 2
|
23
|
+
end
|
24
|
+
|
25
|
+
|
26
|
+
def enq_impl(t)
|
27
|
+
hints = t && t.suggest_location
|
28
|
+
Log.debug "enq #{t.name} hints=#{hints.inspect}"
|
29
|
+
if hints.nil? || hints.empty?
|
30
|
+
@q_remote.push(t)
|
31
|
+
else
|
32
|
+
stored = false
|
33
|
+
hints.each do |h|
|
34
|
+
host_info = @host_map.by_name[h]
|
35
|
+
if host_info && q = @q[host_info.id]
|
36
|
+
t.assigned.push(host_info.id)
|
37
|
+
q.push(t)
|
38
|
+
stored = true
|
39
|
+
end
|
40
|
+
end
|
41
|
+
if stored
|
42
|
+
@size_q += 1
|
43
|
+
else
|
44
|
+
@q_remote.push(t)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
@last_enq_time = Time.now
|
48
|
+
end
|
49
|
+
|
50
|
+
def turn_empty?(turn)
|
51
|
+
case turn
|
52
|
+
when 0
|
53
|
+
@q_no_action.empty? && @size_q == 0 && @q_remote.empty?
|
54
|
+
when 1
|
55
|
+
@size_q == 0
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def deq_impl(host_info, turn)
|
60
|
+
host = host_info.name
|
61
|
+
case turn
|
62
|
+
when 0
|
63
|
+
if t = @q_no_action.shift
|
64
|
+
Log.debug "deq_no_action task=#{t&&t.name} host=#{host}"
|
65
|
+
return t
|
66
|
+
elsif t = deq_locate(host_info,host_info)
|
67
|
+
Log.debug "deq_locate task=#{t&&t.name} host=#{host}"
|
68
|
+
return t
|
69
|
+
elsif t = @q_remote.shift(host_info)
|
70
|
+
Log.debug "deq_remote task=#{t&&t.name}"
|
71
|
+
return t
|
72
|
+
else
|
73
|
+
nil
|
74
|
+
end
|
75
|
+
when 1
|
76
|
+
if t = deq_steal(host_info)
|
77
|
+
Log.debug "deq_steal task=#{t&&t.name} host=#{host}"
|
78
|
+
return t
|
79
|
+
else
|
80
|
+
nil
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def deq_locate(q_host,run_host)
|
86
|
+
q = @q[q_host.id]
|
87
|
+
if q && !q.empty?
|
88
|
+
t = q.shift(run_host)
|
89
|
+
if t
|
90
|
+
t.assigned.each do |h|
|
91
|
+
@q[h].delete(t)
|
92
|
+
end
|
93
|
+
@size_q -= 1
|
94
|
+
end
|
95
|
+
return t
|
96
|
+
else
|
97
|
+
nil
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
def deq_steal(host_info)
|
102
|
+
# select a task based on many and close
|
103
|
+
max_host = nil
|
104
|
+
max_num = 0
|
105
|
+
@q_group[host_info.id].each do |qg|
|
106
|
+
qg.each do |h,a|
|
107
|
+
if !a.empty? # && h!=host_info.id
|
108
|
+
d = a.size
|
109
|
+
if d > max_num
|
110
|
+
max_host = h
|
111
|
+
max_num = d
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
if max_num > 0
|
116
|
+
max_info = @host_map.by_id[max_host]
|
117
|
+
Log.debug "deq_steal max_host=#{max_info.name} max_num=#{max_num}"
|
118
|
+
t = host_info.steal_phase{|h| deq_locate(max_info,h)}
|
119
|
+
#Log.debug "deq_steal task=#{t.inspect}"
|
120
|
+
return t if t
|
121
|
+
end
|
122
|
+
end
|
123
|
+
nil
|
124
|
+
end
|
125
|
+
|
126
|
+
def inspect_q
|
127
|
+
s = _qstr("noaction",@q_no_action)
|
128
|
+
if @size_q == 0
|
129
|
+
n = @q.size
|
130
|
+
else
|
131
|
+
n = 0
|
132
|
+
@q.each do |h,q|
|
133
|
+
if q.size > 0
|
134
|
+
s << _qstr(@host_map.by_id[h].name,q)
|
135
|
+
else
|
136
|
+
n += 1
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
s << _qstr("local*#{n}",[]) if n > 0
|
141
|
+
s << _qstr("remote",@q_remote)
|
142
|
+
s
|
143
|
+
end
|
144
|
+
|
145
|
+
def clear
|
146
|
+
@q_no_action.clear
|
147
|
+
@q.each{|h,q| q.clear}
|
148
|
+
@q_remote.clear
|
149
|
+
end
|
150
|
+
|
151
|
+
def empty?
|
152
|
+
@size_q == 0 &&
|
153
|
+
@q_no_action.empty? &&
|
154
|
+
@q_remote.empty?
|
155
|
+
end
|
156
|
+
|
157
|
+
end
|
158
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
module Pwrake
|
2
|
+
|
3
|
+
class NoActionQueue
|
4
|
+
|
5
|
+
def initialize
|
6
|
+
@que = []
|
7
|
+
prio = Rake.application.pwrake_options['NOACTION_QUEUE_PRIORITY'] || 'fifo'
|
8
|
+
case prio
|
9
|
+
when /fifo/i
|
10
|
+
@prio = 0
|
11
|
+
Log.debug "NOACTION_QUEUE_PRIORITY=FIFO"
|
12
|
+
when /lifo/i
|
13
|
+
@prio = 1
|
14
|
+
Log.debug "NOACTION_QUEUE_PRIORITY=LIFO"
|
15
|
+
when /rand/i
|
16
|
+
@prio = 2
|
17
|
+
Log.debug "NOACTION_QUEUE_PRIORITY=RAND"
|
18
|
+
else
|
19
|
+
raise RuntimeError,"unknown option for NOACTION_QUEUE_PRIORITY: "+prio
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def push(obj)
|
24
|
+
@que.push obj
|
25
|
+
end
|
26
|
+
|
27
|
+
alias << push
|
28
|
+
alias enq push
|
29
|
+
|
30
|
+
def pop
|
31
|
+
case @prio
|
32
|
+
when 0
|
33
|
+
x = @que.shift
|
34
|
+
when 1
|
35
|
+
x = @que.pop
|
36
|
+
when 2
|
37
|
+
x = @que.delete_at(rand(@que.size))
|
38
|
+
end
|
39
|
+
return x
|
40
|
+
end
|
41
|
+
|
42
|
+
alias shift pop
|
43
|
+
alias deq pop
|
44
|
+
|
45
|
+
def empty?
|
46
|
+
@que.empty?
|
47
|
+
end
|
48
|
+
|
49
|
+
def clear
|
50
|
+
@que.clear
|
51
|
+
end
|
52
|
+
|
53
|
+
def length
|
54
|
+
@que.length
|
55
|
+
end
|
56
|
+
alias size length
|
57
|
+
|
58
|
+
def first
|
59
|
+
@que.first
|
60
|
+
end
|
61
|
+
|
62
|
+
def last
|
63
|
+
@que.last
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,366 @@
|
|
1
|
+
require "forwardable"
|
2
|
+
|
3
|
+
module Pwrake
|
4
|
+
|
5
|
+
class PriorityQueueArray < Array
|
6
|
+
def initialize(n)
|
7
|
+
super()
|
8
|
+
end
|
9
|
+
|
10
|
+
def shift
|
11
|
+
pop
|
12
|
+
end
|
13
|
+
|
14
|
+
def push(t)
|
15
|
+
priority = t.priority
|
16
|
+
if empty? || last.priority <= priority
|
17
|
+
super(t)
|
18
|
+
elsif first.priority > priority
|
19
|
+
unshift(t)
|
20
|
+
else
|
21
|
+
lower = 0
|
22
|
+
upper = size-1
|
23
|
+
while lower+1 < upper
|
24
|
+
mid = ((lower + upper) / 2).to_i
|
25
|
+
if self[mid].priority <= priority
|
26
|
+
lower = mid
|
27
|
+
else
|
28
|
+
upper = mid
|
29
|
+
end
|
30
|
+
end
|
31
|
+
insert(upper,t)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def index(t)
|
36
|
+
if size < 40
|
37
|
+
return super(t)
|
38
|
+
end
|
39
|
+
priority = t.priority
|
40
|
+
if last.priority < priority || first.priority > priority
|
41
|
+
nil
|
42
|
+
else
|
43
|
+
lower = 0
|
44
|
+
upper = size-1
|
45
|
+
while lower+1 < upper
|
46
|
+
mid = ((lower + upper) / 2).to_i
|
47
|
+
if self[mid].priority < priority
|
48
|
+
lower = mid
|
49
|
+
else
|
50
|
+
upper = mid
|
51
|
+
end
|
52
|
+
end
|
53
|
+
mid = upper
|
54
|
+
if self[mid].priority == priority
|
55
|
+
Log.debug "TQA#index=#{mid}, priority=#{priority}"
|
56
|
+
mid
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end # PriorityQueueArray
|
61
|
+
|
62
|
+
|
63
|
+
class LifoQueueArray < Array
|
64
|
+
def initialize(n_cores=nil)
|
65
|
+
super()
|
66
|
+
end
|
67
|
+
|
68
|
+
def shift(host_info)
|
69
|
+
(size-1).downto(0) do |i|
|
70
|
+
if at(i).acceptable_for(host_info)
|
71
|
+
return delete_at(i)
|
72
|
+
#else
|
73
|
+
# Log.debug "task[#{at(i).name}] is rejected"
|
74
|
+
end
|
75
|
+
end
|
76
|
+
nil
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
class FifoQueueArray < Array
|
81
|
+
def initialize(n_cores=nil)
|
82
|
+
super()
|
83
|
+
end
|
84
|
+
|
85
|
+
def shift(host_info)
|
86
|
+
size.times do |i|
|
87
|
+
if at(i).acceptable_for(host_info)
|
88
|
+
return delete_at(i)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
nil
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
class RankCounter
|
96
|
+
|
97
|
+
def initialize
|
98
|
+
@ntask = []
|
99
|
+
@nproc = 0
|
100
|
+
@mutex = Mutex.new
|
101
|
+
end
|
102
|
+
|
103
|
+
def add_nproc(n)
|
104
|
+
@mutex.synchronize do
|
105
|
+
@nproc += n
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
def incr(r)
|
110
|
+
@mutex.synchronize do
|
111
|
+
@ntask[r] = (@ntask[r]||0) + 1
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
def get_task
|
116
|
+
@mutex.synchronize do
|
117
|
+
(@ntask.size-1).downto(0) do |r|
|
118
|
+
c = @ntask[r]
|
119
|
+
if c && c>0
|
120
|
+
t = yield(c, @nproc, r)
|
121
|
+
#t = (c<=@n) ? pop_last_rank(r) : pop
|
122
|
+
if t
|
123
|
+
@ntask[t.rank] -= 1
|
124
|
+
Log.debug "RankCount rank=#{r} nproc=#{@nproc} count=#{c} t.rank=#{t.rank} t.name=#{t.name}"
|
125
|
+
end
|
126
|
+
return t
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
nil
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
# HRF mixin module
|
135
|
+
module HrfQueue
|
136
|
+
|
137
|
+
def hrf_init(n_cores=nil)
|
138
|
+
@nproc = n_cores || 0
|
139
|
+
@count = []
|
140
|
+
end
|
141
|
+
|
142
|
+
def hrf_push(t)
|
143
|
+
r = t.rank
|
144
|
+
c = @count[r]
|
145
|
+
@count[r] = (c) ? c+1 : 1
|
146
|
+
end
|
147
|
+
|
148
|
+
def hrf_get(host_info)
|
149
|
+
(@count.size-1).downto(0) do |r|
|
150
|
+
c = @count[r]
|
151
|
+
if c && c>0
|
152
|
+
t = (c <= @nproc) ? pop_last_rank(r,host_info) : pop_super(host_info)
|
153
|
+
hrf_delete(t) if t
|
154
|
+
return t
|
155
|
+
end
|
156
|
+
end
|
157
|
+
raise "no element"
|
158
|
+
nil
|
159
|
+
end
|
160
|
+
|
161
|
+
def pop_last_rank(r,host_info)
|
162
|
+
(size-1).downto(0) do |i|
|
163
|
+
tw = at(i)
|
164
|
+
if tw.rank == r && tw.acceptable_for(host_info)
|
165
|
+
return delete_at(i)
|
166
|
+
end
|
167
|
+
end
|
168
|
+
nil
|
169
|
+
end
|
170
|
+
|
171
|
+
def hrf_delete(t)
|
172
|
+
@count[t.rank] -= 1
|
173
|
+
end
|
174
|
+
|
175
|
+
def check(t=nil)
|
176
|
+
sum = 0
|
177
|
+
@count.each{|x| sum+=x if x}
|
178
|
+
if size != sum
|
179
|
+
#$stderr.puts self.inspect
|
180
|
+
#$stderr.puts t.inspect if t
|
181
|
+
raise "sise != @count.sum"
|
182
|
+
end
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
# LIFO + HRF
|
187
|
+
class LifoHrfQueueArray
|
188
|
+
include HrfQueue
|
189
|
+
extend Forwardable
|
190
|
+
def_delegators :@a, :empty?, :size, :first, :last, :at, :delete_at
|
191
|
+
|
192
|
+
def initialize(n_cores)
|
193
|
+
@a = LifoQueueArray.new
|
194
|
+
hrf_init(n_cores)
|
195
|
+
end
|
196
|
+
|
197
|
+
def push(t)
|
198
|
+
@a.push(t)
|
199
|
+
hrf_push(t)
|
200
|
+
end
|
201
|
+
|
202
|
+
def shift(host_info)
|
203
|
+
return nil if empty?
|
204
|
+
hrf_get(host_info)
|
205
|
+
end
|
206
|
+
|
207
|
+
def delete(t)
|
208
|
+
if x=@a.delete(t)
|
209
|
+
hrf_delete(t)
|
210
|
+
end
|
211
|
+
x
|
212
|
+
end
|
213
|
+
|
214
|
+
def pop_super(host_info)
|
215
|
+
@a.shift(host_info)
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
219
|
+
|
220
|
+
# Priority + HRF
|
221
|
+
class PriorityHrfQueueArray < PriorityQueueArray
|
222
|
+
include HrfQueue
|
223
|
+
|
224
|
+
def initialize(n)
|
225
|
+
super(n)
|
226
|
+
hrf_init(n)
|
227
|
+
end
|
228
|
+
|
229
|
+
def push(t)
|
230
|
+
super(t)
|
231
|
+
hrf_push(t)
|
232
|
+
end
|
233
|
+
|
234
|
+
def shift
|
235
|
+
return nil if empty?
|
236
|
+
hrf_get
|
237
|
+
end
|
238
|
+
|
239
|
+
def pop_super
|
240
|
+
pop
|
241
|
+
end
|
242
|
+
end
|
243
|
+
|
244
|
+
|
245
|
+
# Rank-Even Last In First Out
|
246
|
+
class RankQueueArray
|
247
|
+
|
248
|
+
def initialize(n)
|
249
|
+
@q = []
|
250
|
+
@size = 0
|
251
|
+
@n = (n>0) ? n : 1
|
252
|
+
end
|
253
|
+
|
254
|
+
def push(t)
|
255
|
+
r = t ? t.rank : 0
|
256
|
+
a = @q[r]
|
257
|
+
if a.nil?
|
258
|
+
@q[r] = a = []
|
259
|
+
end
|
260
|
+
@size += 1
|
261
|
+
a.push(t)
|
262
|
+
end
|
263
|
+
|
264
|
+
def size
|
265
|
+
@size
|
266
|
+
end
|
267
|
+
|
268
|
+
def empty?
|
269
|
+
@size == 0
|
270
|
+
end
|
271
|
+
|
272
|
+
def shift
|
273
|
+
if empty?
|
274
|
+
return nil
|
275
|
+
end
|
276
|
+
(@q.size-1).downto(0) do |i|
|
277
|
+
a = @q[i]
|
278
|
+
next if a.nil? || a.empty?
|
279
|
+
@size -= 1
|
280
|
+
if a.size <= @n
|
281
|
+
return pop_last_max(a)
|
282
|
+
else
|
283
|
+
return shift_weighted
|
284
|
+
end
|
285
|
+
end
|
286
|
+
raise "ELIFO: @q=#{@q.inspect}"
|
287
|
+
end
|
288
|
+
|
289
|
+
def shift_weighted
|
290
|
+
weight, weight_avg = RANK_STAT.rank_weight
|
291
|
+
wsum = 0.0
|
292
|
+
q = []
|
293
|
+
@q.each_with_index do |a,i|
|
294
|
+
next if a.nil? || a.empty?
|
295
|
+
w = weight[i]
|
296
|
+
w = weight_avg if w.nil?
|
297
|
+
# w *= a.size
|
298
|
+
wsum += w
|
299
|
+
q << [a,wsum]
|
300
|
+
end
|
301
|
+
#
|
302
|
+
x = rand() * wsum
|
303
|
+
Log.debug "shift_weighted x=#{x} wsum=#{wsum} weight=#{weight.inspect}"
|
304
|
+
q.each do |a,w|
|
305
|
+
if w > x
|
306
|
+
return a.pop
|
307
|
+
end
|
308
|
+
end
|
309
|
+
raise "ELIFO: wsum=#{wsum} x=#{x}"
|
310
|
+
end
|
311
|
+
|
312
|
+
def pop_last_max(a)
|
313
|
+
if a.size < 2
|
314
|
+
return a.pop
|
315
|
+
end
|
316
|
+
y_max = nil
|
317
|
+
i_max = nil
|
318
|
+
n = [@n, a.size].min
|
319
|
+
(-n..-1).each do |i|
|
320
|
+
y = a[i].input_file_size
|
321
|
+
if y_max.nil? || y > y_max
|
322
|
+
y_max = y
|
323
|
+
i_max = i
|
324
|
+
end
|
325
|
+
end
|
326
|
+
a.delete_at(i_max)
|
327
|
+
end
|
328
|
+
|
329
|
+
def first
|
330
|
+
return nil if empty?
|
331
|
+
@q.size.times do |i|
|
332
|
+
a = @q[i]
|
333
|
+
unless a.nil? || a.empty?
|
334
|
+
return a.first
|
335
|
+
end
|
336
|
+
end
|
337
|
+
end
|
338
|
+
|
339
|
+
def last
|
340
|
+
return nil if empty?
|
341
|
+
@q.size.times do |i|
|
342
|
+
a = @q[-i-1]
|
343
|
+
unless a.nil? || a.empty?
|
344
|
+
return a.last
|
345
|
+
end
|
346
|
+
end
|
347
|
+
end
|
348
|
+
|
349
|
+
def delete(t)
|
350
|
+
n = 0
|
351
|
+
@q.each do |a|
|
352
|
+
if a
|
353
|
+
a.delete(t)
|
354
|
+
n += a.size
|
355
|
+
end
|
356
|
+
end
|
357
|
+
@size = n
|
358
|
+
end
|
359
|
+
|
360
|
+
def clear
|
361
|
+
@q.clear
|
362
|
+
@size = 0
|
363
|
+
end
|
364
|
+
end
|
365
|
+
|
366
|
+
end
|