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.
@@ -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(@core_list)
39
+ @task_queue = @queue_class.new(host_list)
40
40
  @shell_set = (1..@num_noaction_threads).map{ NoActionShell.new }
41
- @core_list.each_with_index do |h,i|
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
@@ -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