pwrake 0.9.9 → 0.9.9.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +23 -11
- data/bin/gfwhere-pipe +159 -0
- data/lib/pwrake.rb +1 -0
- data/lib/pwrake/application.rb +13 -3
- data/lib/pwrake/gfarm_feature.rb +1 -1
- data/lib/pwrake/gfwhere_pool.rb +0 -3
- data/lib/pwrake/host_list.rb +88 -0
- data/lib/pwrake/locality_aware_queue.rb +77 -23
- data/lib/pwrake/master.rb +2 -2
- data/lib/pwrake/mcgp.rb +444 -0
- data/lib/pwrake/option.rb +6 -48
- data/lib/pwrake/report/report.rb +15 -2
- data/lib/pwrake/task_algorithm.rb +52 -19
- data/lib/pwrake/task_queue.rb +126 -30
- data/lib/pwrake/version.rb +1 -1
- metadata +8 -3
data/lib/pwrake/master.rb
CHANGED
@@ -36,9 +36,9 @@ module Pwrake
|
|
36
36
|
return if @task_queue
|
37
37
|
timer = Timer.new("start_worker")
|
38
38
|
@finish_queue = Queue.new
|
39
|
-
@task_queue = @queue_class.new(
|
39
|
+
@task_queue = @queue_class.new(host_list)
|
40
40
|
@shell_set = (1..@num_noaction_threads).map{ NoActionShell.new }
|
41
|
-
|
41
|
+
host_list.core_list.each_with_index do |h,i|
|
42
42
|
@shell_set << @shell_class.new(h,@shell_opt)
|
43
43
|
end
|
44
44
|
start_threads
|
data/lib/pwrake/mcgp.rb
ADDED
@@ -0,0 +1,444 @@
|
|
1
|
+
require "rbmetis"
|
2
|
+
#require "pwrake/grviz"
|
3
|
+
|
4
|
+
module Pwrake
|
5
|
+
|
6
|
+
module MCGP
|
7
|
+
|
8
|
+
def graph_partition(target=nil)
|
9
|
+
t1 = Time.now
|
10
|
+
wgts = Pwrake.application.host_list.group_weight_sum
|
11
|
+
if wgts.size > 1
|
12
|
+
list = wgts.size.times.to_a
|
13
|
+
g = GraphTracer.new([list],[wgts]){|t| t.group}
|
14
|
+
trace(g,target)
|
15
|
+
g.part_graph_group
|
16
|
+
#g.write_dot('dag1.dot')
|
17
|
+
#return
|
18
|
+
end
|
19
|
+
|
20
|
+
#$debug2=true
|
21
|
+
|
22
|
+
list = Pwrake.application.host_list.group_hosts
|
23
|
+
wgts = Pwrake.application.host_list.group_core_weight
|
24
|
+
g = GraphTracer.new(list,wgts){|t| t.location}
|
25
|
+
trace(g,target)
|
26
|
+
g.part_graph_node
|
27
|
+
t2 = Time.now
|
28
|
+
Pwrake::Log.info "Time for TOTAL Graph Partitioning: #{t2-t1} sec"
|
29
|
+
#g.write_dot('dag2.dot')
|
30
|
+
#exit
|
31
|
+
end
|
32
|
+
module_function :graph_partition
|
33
|
+
|
34
|
+
def trace(g,target)
|
35
|
+
if target
|
36
|
+
g.trace(target)
|
37
|
+
else
|
38
|
+
Rake.application.top_level_tasks.each do |t|
|
39
|
+
g.trace(t)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
module_function :trace
|
44
|
+
|
45
|
+
end
|
46
|
+
|
47
|
+
|
48
|
+
class GraphTracer
|
49
|
+
|
50
|
+
def initialize(loc_list, weight_list, &block)
|
51
|
+
if loc_list.size != weight_list.size
|
52
|
+
raise ArgumentError, "array size of args mismatch"
|
53
|
+
end
|
54
|
+
@loc_list = loc_list
|
55
|
+
@weight_list = weight_list
|
56
|
+
@n_part = @loc_list.size
|
57
|
+
@location_finder = block
|
58
|
+
@traced = {}
|
59
|
+
@vertex_depth = {}
|
60
|
+
# @grviz = Grviz.new
|
61
|
+
@group_list = @n_part.times.map do |i|
|
62
|
+
GraphGroup.new(@loc_list[i],@weight_list[i],@vertex_depth,@grviz)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def trace( name = "default", target = nil )
|
67
|
+
|
68
|
+
task = Rake.application[name]
|
69
|
+
group_id = task.group_id || 0
|
70
|
+
group = @group_list[group_id]
|
71
|
+
loc_list = @loc_list[group_id]
|
72
|
+
depth = 0
|
73
|
+
|
74
|
+
if task.class == Rake::FileTask
|
75
|
+
tgid = target ? (Rake.application[target].group_id||0) : nil
|
76
|
+
|
77
|
+
if File.file?(name)
|
78
|
+
if tgid == group_id
|
79
|
+
locs = @location_finder.call(task)
|
80
|
+
if locs.empty?
|
81
|
+
Pwrake.application.postprocess(task)
|
82
|
+
locs = @location_finder.call(task)
|
83
|
+
end
|
84
|
+
task.get_file_stat
|
85
|
+
fsz = task.file_size
|
86
|
+
if fsz > 100000
|
87
|
+
#puts "g=#{group_id}, task=#{name}, target=#{target}, fsz=#{fsz}, locs="+locs.join("|")
|
88
|
+
group.push_loc_edge( locs, name, target, fsz/10000 )
|
89
|
+
end
|
90
|
+
else
|
91
|
+
#puts "g=#{group_id}, task=#{name}, tgid=#{tgid}, target=#{target}"
|
92
|
+
end
|
93
|
+
return depth
|
94
|
+
end
|
95
|
+
|
96
|
+
group.push_vertex( name )
|
97
|
+
if tgid == group_id
|
98
|
+
#puts "g=#{group_id}, task=#{name}, target=#{target}"
|
99
|
+
group.push_edge( name, target, nil )
|
100
|
+
end
|
101
|
+
target = name
|
102
|
+
end
|
103
|
+
|
104
|
+
if !@traced[name]
|
105
|
+
@traced[name] = true
|
106
|
+
|
107
|
+
task.prerequisites.each do |prereq|
|
108
|
+
d = trace( prereq, target )
|
109
|
+
depth = d if d and d > depth
|
110
|
+
end
|
111
|
+
|
112
|
+
if task.class == Rake::FileTask
|
113
|
+
depth += 1
|
114
|
+
end
|
115
|
+
|
116
|
+
@vertex_depth[name] = depth
|
117
|
+
end
|
118
|
+
|
119
|
+
return @vertex_depth[name]
|
120
|
+
end
|
121
|
+
|
122
|
+
def part_graph_group
|
123
|
+
@group_list.each do |g|
|
124
|
+
g.part_graph
|
125
|
+
g.set_group
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
def part_graph_node
|
130
|
+
@group_list.each do |g|
|
131
|
+
g.part_graph
|
132
|
+
g.set_node
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
def write_dot(file)
|
137
|
+
@grviz.write(file)
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
|
142
|
+
class GraphGroup
|
143
|
+
|
144
|
+
def summation(a)
|
145
|
+
s = 0
|
146
|
+
a.each{|x| s+=x}
|
147
|
+
s
|
148
|
+
end
|
149
|
+
|
150
|
+
def normalize(a)
|
151
|
+
s = summation(a).to_f
|
152
|
+
(s==0) ? a : a.map{|x| x/s}
|
153
|
+
end
|
154
|
+
|
155
|
+
def average(a)
|
156
|
+
s = summation(a).to_f
|
157
|
+
(a.empty?) ? nil : s/a.size
|
158
|
+
end
|
159
|
+
|
160
|
+
def initialize(loc_list, weight_list, vertex_depth, grviz)
|
161
|
+
if loc_list.size != weight_list.size
|
162
|
+
raise ArgumentError, "array size mismatch"
|
163
|
+
end
|
164
|
+
@n_part = loc_list.size
|
165
|
+
a = [loc_list, weight_list].transpose
|
166
|
+
a.sort_by!{|x| x[1]}
|
167
|
+
b = a.transpose
|
168
|
+
@loc_list = b[0]
|
169
|
+
@tpwgts = normalize(b[1])
|
170
|
+
|
171
|
+
b = @tpwgts[0]
|
172
|
+
a = @tpwgts[-1]-b
|
173
|
+
if a/b > 1e-3
|
174
|
+
@host_wgts = @tpwgts.map{|x| (((x-b)/a*0.45+1)*1000).to_i}
|
175
|
+
else
|
176
|
+
@host_wgts = @tpwgts.map{|x| 1000}
|
177
|
+
end
|
178
|
+
|
179
|
+
@vertex_name2id = {}
|
180
|
+
@vertex_id2name = []
|
181
|
+
@edges = []
|
182
|
+
@file_sizes = []
|
183
|
+
@loc_files = {}
|
184
|
+
@count = 0
|
185
|
+
|
186
|
+
@vertex_depth = vertex_depth
|
187
|
+
@grviz = grviz
|
188
|
+
|
189
|
+
@loc_list.each do |loc|
|
190
|
+
push_vertex(loc)
|
191
|
+
@vertex_depth[loc] = 0
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
def push_loc_edge(locs, name, target, fsz)
|
196
|
+
locs.each do |loc|
|
197
|
+
if @loc_list.include?(loc)
|
198
|
+
push_edge(loc, target, fsz)
|
199
|
+
@loc_files[loc] ||= []
|
200
|
+
@loc_files[loc] << name
|
201
|
+
end
|
202
|
+
end
|
203
|
+
@file_sizes << fsz
|
204
|
+
#p [object_id,target,fsz]
|
205
|
+
end
|
206
|
+
|
207
|
+
def push_vertex(name)
|
208
|
+
if !@vertex_name2id.has_key?(name)
|
209
|
+
@vertex_name2id[name] = @count
|
210
|
+
@vertex_id2name[@count] = name
|
211
|
+
@grviz.push_vertex(name) if @grviz
|
212
|
+
@count += 1
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
def push_edge(name, target, weight)
|
217
|
+
if target and (weight.nil? or weight>0)
|
218
|
+
push_vertex(name)
|
219
|
+
push_vertex(target)
|
220
|
+
v1 = @vertex_name2id[name]
|
221
|
+
v2 = @vertex_name2id[target]
|
222
|
+
(@edges[v1] ||= []).push [v2, weight]
|
223
|
+
(@edges[v2] ||= []).push [v1, weight]
|
224
|
+
@grviz.push_edge(name, target) if @grviz
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
def part_graph
|
229
|
+
@xadj = [0]
|
230
|
+
@adjcny = []
|
231
|
+
@adjwgt = []
|
232
|
+
@vwgt = []
|
233
|
+
|
234
|
+
depth_hist = []
|
235
|
+
@vertex_id2name.each do |name|
|
236
|
+
depth = @vertex_depth[name]
|
237
|
+
# puts "name=#{name}, depth=#{depth}"
|
238
|
+
depth_hist[depth] = (depth_hist[depth] || 0) + 1
|
239
|
+
end
|
240
|
+
|
241
|
+
map_depth = []
|
242
|
+
ubv = []
|
243
|
+
c = 0
|
244
|
+
depth_hist.each do |x|
|
245
|
+
if x and x>=@n_part
|
246
|
+
map_depth << c
|
247
|
+
c += 1
|
248
|
+
ubv << 1 + 0.5*@n_part/x
|
249
|
+
#ubv << ((x >= @n_part) ? 1.05 : 1.5)
|
250
|
+
else
|
251
|
+
map_depth << nil
|
252
|
+
end
|
253
|
+
end
|
254
|
+
ubv[0] = 1.0005
|
255
|
+
|
256
|
+
Pwrake::Log.info "loc_list=#{@loc_list}"
|
257
|
+
Pwrake::Log.info "partition_weights=#{@tpwgts}"
|
258
|
+
Pwrake::Log.info "ncon=#{c}"
|
259
|
+
Pwrake::Log.info "depth_hist=#{depth_hist.inspect}"
|
260
|
+
Pwrake::Log.info "ubvec=#{ubv.inspect}"
|
261
|
+
|
262
|
+
if @file_sizes.empty?
|
263
|
+
@edge_weight = 1
|
264
|
+
else
|
265
|
+
@edge_weight = average(@file_sizes).to_i*3
|
266
|
+
end
|
267
|
+
Pwrake::Log.info "default_edge_weight=#{@edge_weight}"
|
268
|
+
|
269
|
+
@vertex_id2name.size.times do |i|
|
270
|
+
if edg = @edges[i]
|
271
|
+
edg.sort_by!{|x| x[0]}
|
272
|
+
@adjcny.concat(edg.map{|x| x[0]})
|
273
|
+
@adjwgt.concat(edg.map{|x| x[1] || @edge_weight})
|
274
|
+
# @adjwgt.concat(edg.map{|x| x[1] ? 0 : @edge_weight})
|
275
|
+
end
|
276
|
+
@xadj.push(@adjcny.size)
|
277
|
+
end
|
278
|
+
|
279
|
+
@vertex_id2name.each_with_index do |name,i|
|
280
|
+
w = Array.new(c,0)
|
281
|
+
if i < @n_part
|
282
|
+
w[0] = @host_wgts[i]
|
283
|
+
# puts "name=#{name}, w=#{w.inspect}"
|
284
|
+
else
|
285
|
+
depth = @vertex_depth[name]
|
286
|
+
if depth and (j = map_depth[depth])
|
287
|
+
w[j] = 1
|
288
|
+
end
|
289
|
+
end
|
290
|
+
@vwgt.concat(w)
|
291
|
+
end
|
292
|
+
|
293
|
+
# puts "@vertex_id2name[#{i}]=#{@vertex_id2name[i]}, depth=#{depth}, edges="+@edges[i].map{|x| @vertex_id2name[x[0]]}.join("|")
|
294
|
+
|
295
|
+
t1 = Time.now
|
296
|
+
if false
|
297
|
+
puts "@vertex_id2name.size=#{@vertex_id2name.size}"
|
298
|
+
if $debug2
|
299
|
+
@vertex_id2name.each_with_index{|x,i| puts "#{i} #{x} #{@edges[i].inspect}"}
|
300
|
+
end
|
301
|
+
puts "@edges.size=#{@edges.size}"
|
302
|
+
puts "ncon=#{c}"
|
303
|
+
puts "@n_part=#{@n_part}"
|
304
|
+
puts "@xadj.size=#{@xadj.size}"
|
305
|
+
puts "@adjcny.size/2=#{@adjcny.size/2}"
|
306
|
+
puts "@adjwgt.size/2=#{@adjwgt.size/2}"
|
307
|
+
puts "@vwgt.size=#{@vwgt.size}"
|
308
|
+
puts "@vwgt.size/ncon=#{@vwgt.size/c}"
|
309
|
+
puts "depth_hist=#{depth_hist.inspect}"
|
310
|
+
puts "ubv=#{ubv.inspect}"
|
311
|
+
if $debug
|
312
|
+
puts "@xadj=#{@xadj.inspect}"
|
313
|
+
puts "@adjcny=#{@adjcny.inspect}"
|
314
|
+
puts "@adjwgt=#{@adjwgt.inspect}"
|
315
|
+
puts "@vwgt=#{@vwgt.inspect}"
|
316
|
+
end
|
317
|
+
#exit
|
318
|
+
end
|
319
|
+
if defined? RbMetis
|
320
|
+
hw = normalize(@host_wgts)
|
321
|
+
tpw = []
|
322
|
+
s = "tpwgts=[\n"
|
323
|
+
@tpwgts.each_with_index do |x,i|
|
324
|
+
a = [hw[i]]+[x]*(c-1)
|
325
|
+
tpw.concat(a)
|
326
|
+
s += " ["+a.map{|x|"%.5f"%x}.join(", ")+"]\n"
|
327
|
+
end
|
328
|
+
s += "]"
|
329
|
+
Log.info s
|
330
|
+
options = RbMetis.default_options
|
331
|
+
RbMetis::OPTION_NITER
|
332
|
+
options[RbMetis::OPTION_NCUTS] = 30
|
333
|
+
options[RbMetis::OPTION_NSEPS] = 30
|
334
|
+
options[RbMetis::OPTION_NITER] = 10
|
335
|
+
@part = RbMetis.part_graph_recursive(@xadj, @adjcny, @n_part, ncon:c, vwgt:@vwgt, adjwgt:@adjwgt, tpwgts:tpw, ubvec:ubv, options:options)
|
336
|
+
else
|
337
|
+
puts "tpw=#{tpw.inspect}"
|
338
|
+
@part = Metis.mc_part_graph_recursive2(c, @xadj,@adjcny, @vwgt,nil, @tpwgts)
|
339
|
+
end
|
340
|
+
t2 = Time.now
|
341
|
+
Pwrake::Log.info "Time for Graph Partitioning: #{t2-t1} sec"
|
342
|
+
count_partition
|
343
|
+
#puts "Time for Graph Partitioning: #{t2-t1} sec"
|
344
|
+
#if $debug
|
345
|
+
#p @part
|
346
|
+
#end
|
347
|
+
end
|
348
|
+
|
349
|
+
def count_partition
|
350
|
+
locs = Array.new(@n_part,nil)
|
351
|
+
@n_part.times do |i|
|
352
|
+
i_part = @part[i]
|
353
|
+
locs[i_part] ||= []
|
354
|
+
locs[i_part] << @vertex_id2name[i]
|
355
|
+
end
|
356
|
+
# p locs
|
357
|
+
sum = []
|
358
|
+
@vertex_id2name.each_with_index do |name,idx|
|
359
|
+
y = @vertex_depth[name]
|
360
|
+
x = @part[idx]
|
361
|
+
sum[y] ||= Array.new(@n_part,0)
|
362
|
+
sum[y][x] += 1
|
363
|
+
end
|
364
|
+
s = "partition count: \n"
|
365
|
+
s += sum.each_with_index.map do |row,idx|
|
366
|
+
" d=#{idx} "+row.inspect
|
367
|
+
end.join("\n")
|
368
|
+
#puts s
|
369
|
+
Log.info s
|
370
|
+
Log.info "@part[0:#{@n_part-1}]=#{@part[0...@n_part].inspect}"
|
371
|
+
sum[0].each{|i| raise RuntimeError,"Unequal partitioning" if i!=1}
|
372
|
+
end
|
373
|
+
|
374
|
+
|
375
|
+
def count_partition2(part)
|
376
|
+
sum = Array.new(0,0)
|
377
|
+
part.each do |x|
|
378
|
+
sum[x] ||= 0
|
379
|
+
sum[x] += 1
|
380
|
+
end
|
381
|
+
s = sum.each_with_index.map do |x,i|
|
382
|
+
"#{i}:#{x}"
|
383
|
+
end
|
384
|
+
puts "n_nodes=[ "+s.join(", ")+" ]"
|
385
|
+
puts "@part[0:#{@n_part-1}]=#{part[0...@n_part].inspect}"
|
386
|
+
end
|
387
|
+
|
388
|
+
def make_loc_list
|
389
|
+
rest = []
|
390
|
+
loc_list = []
|
391
|
+
@n_part.times do |i|
|
392
|
+
i_part = @part[i]
|
393
|
+
loc = @loc_list[i]
|
394
|
+
if loc_list[i_part]
|
395
|
+
rest << loc
|
396
|
+
else
|
397
|
+
loc_list[i_part] = loc
|
398
|
+
end
|
399
|
+
end
|
400
|
+
@n_part.times do |i|
|
401
|
+
unless loc_list[i]
|
402
|
+
loc_list[i] = rest.pop
|
403
|
+
end
|
404
|
+
end
|
405
|
+
loc_list
|
406
|
+
end
|
407
|
+
|
408
|
+
|
409
|
+
def set_group
|
410
|
+
loc_list = make_loc_list()
|
411
|
+
@vertex_id2name.each_with_index do |name,idx|
|
412
|
+
if idx >= @n_part
|
413
|
+
i_part = @part[idx]
|
414
|
+
task = Rake.application[name]
|
415
|
+
task.group_id = loc_list[i_part]
|
416
|
+
#puts "task=#{task.inspect}, i_part=#{i_part}, host=#{host}"
|
417
|
+
end
|
418
|
+
end
|
419
|
+
@loc_files.each do |gid,files|
|
420
|
+
files.each do |f|
|
421
|
+
task = Rake.application[f]
|
422
|
+
task.group_id = gid
|
423
|
+
# puts "gid=#{gid}, task=#{f}"
|
424
|
+
end
|
425
|
+
end
|
426
|
+
end
|
427
|
+
|
428
|
+
|
429
|
+
def set_node
|
430
|
+
loc_list = make_loc_list()
|
431
|
+
@vertex_id2name.each_with_index do |name,idx|
|
432
|
+
if idx >= @n_part
|
433
|
+
i_part = @part[idx]
|
434
|
+
task = Rake.application[name]
|
435
|
+
host = loc_list[i_part]
|
436
|
+
task.suggest_location = [host]
|
437
|
+
#puts "task=#{task.inspect}, i_part=#{i_part}, host=#{host}"
|
438
|
+
end
|
439
|
+
end
|
440
|
+
end
|
441
|
+
|
442
|
+
end # class MetisGraph
|
443
|
+
|
444
|
+
end
|