pwrake 0.9.9 → 0.9.9.2

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.
@@ -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