BOAST 2.0.2 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. checksums.yaml +4 -4
  2. data/BOAST.gemspec +4 -3
  3. data/lib/BOAST.rb +1 -0
  4. data/lib/BOAST/Language/Arithmetic.rb +5 -1
  5. data/lib/BOAST/Language/BOAST_OpenCL.rb +6 -6
  6. data/lib/BOAST/Language/Case.rb +11 -11
  7. data/lib/BOAST/Language/Comment.rb +2 -2
  8. data/lib/BOAST/Language/Config.rb +5 -5
  9. data/lib/BOAST/Language/DataTypes.rb +31 -29
  10. data/lib/BOAST/Language/Expression.rb +16 -16
  11. data/lib/BOAST/Language/For.rb +6 -6
  12. data/lib/BOAST/Language/FuncCall.rb +7 -7
  13. data/lib/BOAST/Language/HighLevelOperators.rb +6 -6
  14. data/lib/BOAST/Language/If.rb +7 -7
  15. data/lib/BOAST/Language/Index.rb +31 -31
  16. data/lib/BOAST/Language/Intrinsics.rb +27 -27
  17. data/lib/BOAST/Language/OpenMP.rb +19 -19
  18. data/lib/BOAST/Language/Operators.rb +62 -50
  19. data/lib/BOAST/Language/Pragma.rb +4 -4
  20. data/lib/BOAST/Language/Procedure.rb +47 -47
  21. data/lib/BOAST/Language/Slice.rb +14 -14
  22. data/lib/BOAST/Language/State.rb +1 -1
  23. data/lib/BOAST/Language/Transitions.rb +1 -1
  24. data/lib/BOAST/Language/Variable.rb +83 -90
  25. data/lib/BOAST/Language/While.rb +4 -4
  26. data/lib/BOAST/Optimization/Optimization.rb +61 -37
  27. data/lib/BOAST/Runtime/AffinityProbe.rb +99 -15
  28. data/lib/BOAST/Runtime/CRuntime.rb +18 -6
  29. data/lib/BOAST/Runtime/CUDARuntime.rb +11 -7
  30. data/lib/BOAST/Runtime/CoExecute.rb +77 -0
  31. data/lib/BOAST/Runtime/CompiledRuntime.rb +274 -110
  32. data/lib/BOAST/Runtime/Compilers.rb +15 -15
  33. data/lib/BOAST/Runtime/Config.rb +3 -0
  34. data/lib/BOAST/Runtime/EnergyProbe.rb +86 -71
  35. data/lib/BOAST/Runtime/FFIRuntime.rb +1 -1
  36. data/lib/BOAST/Runtime/FORTRANRuntime.rb +15 -5
  37. data/lib/BOAST/Runtime/MPPARuntime.rb +30 -19
  38. data/lib/BOAST/Runtime/OpenCLRuntime.rb +2 -2
  39. data/lib/BOAST/Runtime/Probe.rb +122 -41
  40. metadata +29 -8
@@ -63,7 +63,7 @@ module BOAST
63
63
  else
64
64
  @first = Expression::new(Addition, s.first, @first )
65
65
  end
66
- if not scalar? then
66
+ unless scalar? then
67
67
  if s.step then
68
68
  if @step then
69
69
  @step = Expression::new(Multiplication, @step, s.step)
@@ -92,7 +92,7 @@ module BOAST
92
92
  attr_accessor :alignment
93
93
 
94
94
  def initialize(source, *slices)
95
- raise "Cannot slice a non array Variable!" if not source.dimension?
95
+ raise "Cannot slice a non array Variable!" unless source.dimension?
96
96
  raise "Invalid slice!" if slices.length != source.dimension.length
97
97
  @source = source
98
98
  @slices = slices.collect{ |s| SliceItem::new(s) }
@@ -105,7 +105,7 @@ module BOAST
105
105
  def dimension
106
106
  dims = []
107
107
  slices.each_with_index { |slice, i|
108
- if not slice.scalar? then
108
+ unless slice.scalar? then
109
109
  if slice.all? then
110
110
  if source.dimension[i].size then
111
111
  dims.push Dimension::new( source.dimension[i].size )
@@ -127,15 +127,15 @@ module BOAST
127
127
 
128
128
  def pr
129
129
  s=""
130
- s += indent
131
- s += to_s
132
- s += ";" if [C, CL, CUDA].include?( lang )
130
+ s << indent
131
+ s << to_s
132
+ s << ";" if [C, CL, CUDA].include?( lang )
133
133
  output.puts s
134
134
  return self
135
135
  end
136
136
 
137
137
  def align?
138
- return !!@alignment
138
+ return @alignment
139
139
  end
140
140
 
141
141
  def set_align(align)
@@ -162,7 +162,7 @@ module BOAST
162
162
  }
163
163
  new_args = []
164
164
  slices.each_with_index { |s, i|
165
- if not s.scalar?
165
+ unless s.scalar?
166
166
  raise "Invalid slice!" if args.length == 0
167
167
  new_arg = SliceItem::new(args.shift)
168
168
  new_arg.recurse!(s, @source.dimension[i])
@@ -188,9 +188,9 @@ module BOAST
188
188
  else
189
189
  start = Expression::new(Subtraction, slice.first, dims[indx].start)
190
190
  s = "#{start}"
191
- if not slice.scalar? then
192
- s += ":#{slice.length}"
193
- # s += ":#{slice.step}" if slice.step
191
+ unless slice.scalar? then
192
+ s << ":#{slice.length}"
193
+ # s << ":#{slice.step}" if slice.step
194
194
  raise "Slice don't support step in C!" if slice.step
195
195
  end
196
196
  s
@@ -205,9 +205,9 @@ module BOAST
205
205
  ":"
206
206
  else
207
207
  s = "#{slice.first}"
208
- if not slice.scalar? then
209
- s += ":#{slice.last}"
210
- s += ":#{slice.step}" if slice.step
208
+ unless slice.scalar? then
209
+ s << ":#{slice.last}"
210
+ s << ":#{slice.step}" if slice.step
211
211
  end
212
212
  s
213
213
  end
@@ -64,7 +64,7 @@ EOF
64
64
  module_function
65
65
 
66
66
  def #{state}?
67
- !!@@#{state}
67
+ @@#{state}
68
68
  end
69
69
  EOF
70
70
  eval s
@@ -7,7 +7,7 @@ module BOAST
7
7
  def get_transition(type1, type2, operator)
8
8
  #STDERR.puts @@transitions.inspect
9
9
  ops = @@transitions[[type1,type2]]
10
- raise "Types #{[type1,type2]} have no relation!" if not ops
10
+ raise "Types #{[type1,type2]} have no relation!" unless ops
11
11
  t = ops[operator]
12
12
  return [t,operator] if t
13
13
  t = ops[:default]
@@ -48,7 +48,7 @@ module BOAST
48
48
  return "#{get_array_start}:#{@size-(1+get_array_start)}"
49
49
  else
50
50
  return @size.to_s
51
- end
51
+ end
52
52
  end
53
53
 
54
54
  # Returns the start of the {Dimension} as given at initialization or as computed {BOAST.get_array_start}.
@@ -111,16 +111,16 @@ module BOAST
111
111
  arr = flatten
112
112
  s = ""
113
113
  return s if arr.first.nil?
114
- s += "reshape(" if @shape
115
- s += "(/ &\n"
116
- s += arr.first.to_s
117
- s += @type.suffix if @type
114
+ s << "reshape(" if @shape
115
+ s << "(/ &\n"
116
+ s << arr.first.to_s
117
+ s << @type.suffix if @type
118
118
  arr[1..-1].each { |v|
119
- s += ", &\n"+v.to_s
120
- s += @type.suffix if @type
119
+ s << ", &\n"+v.to_s
120
+ s << @type.suffix if @type
121
121
  }
122
- s += " /)"
123
- s += ", shape(#{@shape}))" if @shape
122
+ s << " /)"
123
+ s << ", shape(#{@shape}))" if @shape
124
124
  return s
125
125
  end
126
126
 
@@ -128,14 +128,14 @@ module BOAST
128
128
  arr = flatten
129
129
  s = ""
130
130
  return s if arr.first.nil?
131
- s += "{\n"
132
- s += arr.first.to_s
133
- s += @type.suffix if @type
131
+ s << "{\n"
132
+ s << arr.first.to_s
133
+ s << @type.suffix if @type
134
134
  arr[1..-1].each { |v|
135
- s += ",\n"+v.to_s
136
- s += @type.suffix if @type
135
+ s << ",\n"+v.to_s
136
+ s << @type.suffix if @type
137
137
  }
138
- s += "}"
138
+ s << "}"
139
139
  end
140
140
 
141
141
  end
@@ -150,7 +150,7 @@ module BOAST
150
150
  ANNOTATIONS = [ :name, :type, :dimension ]
151
151
 
152
152
  def method_missing(m, *a, &b)
153
- if @type.methods.include?(:members) and @type.members[m.to_s] then
153
+ if @type.kind_of?(CStruct) and @type.members[m.to_s] then
154
154
  return struct_reference(type.members[m.to_s])
155
155
  elsif __vector? and m.to_s[0] == 's' and lang != CUDA then
156
156
  required_set = m.to_s[1..-1].chars.to_a
@@ -264,17 +264,10 @@ module BOAST
264
264
  # @option properties [Boolean] :optional for Fortran interface generation mainly see Fortran documentation
265
265
  def initialize(name, type, properties={})
266
266
  @name = name.to_s
267
- @direction = properties[:direction]
268
- @direction = properties[:dir] unless @direction
269
-
270
- @constant = properties[:constant]
271
- @constant = properties[:const] unless @constant
272
-
273
- @dimension = properties[:dimension]
274
- @dimension = properties[:dim] unless @dimension
275
-
276
- @local = properties[:local]
277
- @local = properties[:shared] unless @local
267
+ @direction = properties[:direction] or @direction = properties[:dir]
268
+ @constant = properties[:constant] or @constant = properties[:const]
269
+ @dimension = properties[:dimension] or @dimension = properties[:dim]
270
+ @local = properties[:local] or @local = properties[:shared]
278
271
 
279
272
  @texture = properties[:texture]
280
273
  @allocate = properties[:allocate]
@@ -304,7 +297,7 @@ module BOAST
304
297
  end
305
298
 
306
299
  def copy(name=nil,properties={})
307
- name = @name if not name
300
+ name = @name unless name
308
301
  h = @properties.clone
309
302
  properties.each { |k,v|
310
303
  h[k] = v
@@ -326,7 +319,7 @@ module BOAST
326
319
  hash[:dir] = nil
327
320
  return Variable::new(name, type.class, hash)
328
321
  end
329
-
322
+
330
323
  def to_s
331
324
  if force_replace_constant? or ( ( replace_constant? or replace_constants? ) and constant? and not dimension? ) then
332
325
  s = @constant.to_s + @type.suffix
@@ -350,12 +343,12 @@ module BOAST
350
343
  return copy("*(#{name})", :dimension => nil, :dim => nil, :direction => nil, :dir => nil) if [C, CL, CUDA].include?( lang )
351
344
  return Index::new(self, *(@dimension.collect { |d| d.start } ) ) if lang == FORTRAN
352
345
  end
353
-
346
+
354
347
  def struct_reference(x)
355
348
  return x.copy(name+"."+x.name) if [C, CL, CUDA].include?( lang )
356
349
  return x.copy(name+"%"+x.name) if lang == FORTRAN
357
350
  end
358
-
351
+
359
352
  def inc
360
353
  return Expression::new("++",self,nil)
361
354
  end
@@ -378,23 +371,23 @@ module BOAST
378
371
  return Index::new(self, *args)
379
372
  end
380
373
  end
381
-
374
+
382
375
  def boast_header(lang=C)
383
376
  return decl_texture_s if texture?
384
377
  s = ""
385
- s += "const " if constant? or @direction == :in
386
- s += @type.decl
378
+ s << "const " if constant? or @direction == :in
379
+ s << @type.decl
387
380
  if dimension? then
388
- s += " *" unless (use_vla? and lang != FORTRAN)
381
+ s << " *" unless (use_vla? and lang != FORTRAN)
389
382
  end
390
383
  if not dimension? and ( lang == FORTRAN or @direction == :out or @direction == :inout or @reference ) then
391
- s += " *"
384
+ s << " *"
392
385
  end
393
- s += " #{@name}"
386
+ s << " #{@name}"
394
387
  if dimension? and use_vla? and lang != FORTRAN then
395
- s += "["
396
- s += @dimension.reverse.collect(&:to_s).join("][")
397
- s += "]"
388
+ s << "["
389
+ s << @dimension.reverse.collect(&:to_s).join("][")
390
+ s << "]"
398
391
  end
399
392
  return s
400
393
  end
@@ -491,47 +484,47 @@ module BOAST
491
484
  def decl_c_s(device = false)
492
485
  return decl_texture_s if texture?
493
486
  s = ""
494
- s += "const " if __const?
495
- s += "__global " if __global?
496
- s += "__local " if __local?
497
- s += "__shared__ " if __shared?(device)
498
- s += @type.decl
487
+ s << "const " if __const?
488
+ s << "__global " if __global?
489
+ s << "__local " if __local?
490
+ s << "__shared__ " if __shared?(device)
491
+ s << @type.decl
499
492
  if __vla_array? then
500
- s += " #{@name}["
501
- s += "__restrict__ " if __restrict?
502
- s += @dimension.reverse.collect(&:to_s).join("][")
503
- s += "]"
493
+ s << " #{@name}["
494
+ s << "__restrict__ " if __restrict?
495
+ s << @dimension.reverse.collect(&:to_s).join("][")
496
+ s << "]"
504
497
  else
505
- s += " *" if __pointer?(device)
498
+ s << " *" if __pointer?(device)
506
499
  if __pointer_array?(device) and __restrict? then
507
500
  if lang == CL
508
- s += " restrict"
501
+ s << " restrict"
509
502
  else
510
- s += " __restrict__" unless use_vla?
503
+ s << " __restrict__" unless use_vla?
511
504
  end
512
505
  end
513
- s += " #{@name}"
506
+ s << " #{@name}"
514
507
  if dimension? and constant? then
515
- s += "[]"
508
+ s << "[]"
516
509
  end
517
510
  if __dimension?(device) then
518
- s +="[("
519
- s += @dimension.collect(&:to_s).reverse.join(")*(")
520
- s +=")]"
521
- end
511
+ s << "[("
512
+ s << @dimension.collect(&:to_s).reverse.join(")*(")
513
+ s << ")]"
514
+ end
522
515
  end
523
516
  if __align? and lang != CUDA then
524
517
  a = ( align? ? alignment : 1 )
525
518
  a = ( a >= default_align ? a : default_align )
526
- s+= " __attribute((aligned(#{a})))"
519
+ s << " __attribute((aligned(#{a})))"
527
520
  end
528
- s += " = #{@constant}" if constant?
521
+ s << " = #{@constant}" if constant?
529
522
  return s
530
523
  end
531
524
 
532
525
  def decl_texture_s
533
- raise LanguageError, "Unsupported language #{lang} for texture!" if not [CL, CUDA].include?( lang )
534
- raise "Write is unsupported for textures!" if not (constant? or @direction == :in)
526
+ raise LanguageError, "Unsupported language #{lang} for texture!" unless [CL, CUDA].include?( lang )
527
+ raise "Write is unsupported for textures!" unless (constant? or @direction == :in)
535
528
  dim_number = 1
536
529
  if dimension? then
537
530
  dim_number == @dimension.size
@@ -539,24 +532,24 @@ module BOAST
539
532
  raise "Unsupported number of dimension: #{dim_number}!" if dim_number > 3
540
533
  s = ""
541
534
  if lang == CL then
542
- s += "__read_only "
535
+ s << "__read_only "
543
536
  if dim_number < 3 then
544
- s += "image2d_t " #from OCL 1.2+ image1d_t is defined
537
+ s << "image2d_t " #from OCL 1.2+ image1d_t is defined
545
538
  else
546
- s += "image3d_t "
539
+ s << "image3d_t "
547
540
  end
548
541
  else
549
- s += "texture<#{@type.decl}, cudaTextureType#{dim_number}D, cudaReadModeElementType> "
542
+ s << "texture<#{@type.decl}, cudaTextureType#{dim_number}D, cudaReadModeElementType> "
550
543
  end
551
- s += @name
544
+ s << @name
552
545
  return s
553
546
  end
554
547
 
555
548
  def decl_c
556
549
  s = ""
557
- s += indent
558
- s += decl_c_s
559
- s += finalize
550
+ s << indent
551
+ s << decl_c_s
552
+ s << finalize
560
553
  output.print s
561
554
  return self
562
555
  end
@@ -595,42 +588,42 @@ module BOAST
595
588
 
596
589
  def decl_fortran
597
590
  s = ""
598
- s += indent
599
- s += @type.decl
600
- s += ", intent(#{@direction})" if @direction
601
- s += ", optional" if optional?
602
- s += ", allocatable" if allocate? and @allocate == :heap
603
- s += ", parameter" if constant?
591
+ s << indent
592
+ s << @type.decl
593
+ s << ", intent(#{@direction})" if @direction
594
+ s << ", optional" if optional?
595
+ s << ", allocatable" if allocate? and @allocate == :heap
596
+ s << ", parameter" if constant?
604
597
  if dimension? or __vector? then
605
- s += ", dimension("
598
+ s << ", dimension("
606
599
  if __vector? then
607
- s += "#{@type.vector_length}"
608
- s += ", " if dimension?
600
+ s << "#{@type.vector_length}"
601
+ s << ", " if dimension?
609
602
  end
610
- s += @dimension.collect { |d|
603
+ s << @dimension.collect { |d|
611
604
  if deferred_shape? or ( allocate? and @allocate == :heap )
612
605
  ":"
613
606
  else
614
607
  d.to_s
615
608
  end
616
609
  }.join(", ") if dimension?
617
- s += ")"
610
+ s << ")"
618
611
  end
619
- s += " :: #{@name}"
612
+ s << " :: #{@name}"
620
613
  if constant? then
621
614
  @constant.shape = self if dimension? and @constant.kind_of?(ConstArray)
622
- s += " = #{@constant}"
623
- s += @type.suffix if not dimension? and @type
615
+ s << " = #{@constant}"
616
+ s << @type.suffix if not dimension? and @type
624
617
  end
625
- s += finalize
618
+ s << finalize
626
619
  output.print s
627
620
  if ( dimension? and (align? or default_align > 1) and (constant? or ( allocate? and @allocate != :heap ) ) ) or ( vector? and not @direction ) then
628
621
  a = ( align? ? alignment : 1 )
629
622
  a = ( a >= default_align ? a : default_align )
630
623
  s = ""
631
- s += indent
632
- s += "!DIR$ ATTRIBUTES ALIGN: #{a}:: #{name}"
633
- s += finalize
624
+ s << indent
625
+ s << "!DIR$ ATTRIBUTES ALIGN: #{a}:: #{name}"
626
+ s << finalize
634
627
  output.print s
635
628
  end
636
629
  return self
@@ -638,8 +631,8 @@ module BOAST
638
631
 
639
632
  def finalize
640
633
  s = ""
641
- s += ";" if [C, CL, CUDA].include?( lang )
642
- s+="\n"
634
+ s << ";" if [C, CL, CUDA].include?( lang )
635
+ s << "\n"
643
636
  return s
644
637
  end
645
638
 
@@ -43,8 +43,8 @@ module BOAST
43
43
  # @return [self]
44
44
  def open
45
45
  s=""
46
- s += indent
47
- s += to_s
46
+ s << indent
47
+ s << to_s
48
48
  output.puts s
49
49
  increment_indent_level
50
50
  return self
@@ -71,8 +71,8 @@ module BOAST
71
71
  def close
72
72
  decrement_indent_level
73
73
  s = ""
74
- s += indent
75
- s += end_string
74
+ s << indent
75
+ s << end_string
76
76
  output.puts s
77
77
  return self
78
78
  end
@@ -42,6 +42,23 @@ module BOAST
42
42
  else
43
43
  @parameters = parameters
44
44
  end
45
+ if @checkers then
46
+ @checkers.each { |checker| eval checker }
47
+ end
48
+ if @rules then
49
+ s = <<EOF
50
+ def rules_checker(#{HASH_NAME})
51
+ return ( (#{@rules.join(") and (")}) )
52
+ end
53
+ EOF
54
+ else
55
+ s = <<EOF
56
+ def rules_checker(#{HASH_NAME})
57
+ return true
58
+ end
59
+ EOF
60
+ end
61
+ eval s
45
62
  end
46
63
 
47
64
  # Add to the parameters of the rules the name of the hash variable
@@ -59,16 +76,11 @@ module BOAST
59
76
  # Remove all points that do not meet ALL the rules.
60
77
  def remove_unfeasible (points = [])
61
78
  if @rules then
62
- if @checkers
63
- @checkers.each { |checker| eval checker }
64
- end
65
- s = <<EOF
66
- points.reject!{ |#{HASH_NAME}|
67
- not @rules.all?{ |r| eval r }
68
- }
69
- EOF
70
- eval s
79
+ points.select!{ |pt|
80
+ rules_checker(pt)
81
+ }
71
82
  end
83
+ return points
72
84
  end
73
85
 
74
86
  def to_h
@@ -184,46 +196,58 @@ EOF
184
196
  @seed = options[:seed]
185
197
  end
186
198
 
187
- def points
188
- params2 = @search_space.parameters.dup
189
- param = params2.shift
190
-
191
- pts = param.values.collect { |val| {param.name => val} }
192
- if params2.size == 0 then
193
- pts4 = pts
194
- else
195
- optim2 = BruteForceOptimizer::new(OptimizationSpace::new(*params2))
196
- pts3=[]
197
- pts.each{ |p1|
198
- optim2.each { |p2|
199
- pts3.push(p1.dup.update(p2))
200
- }
201
- }
202
- pts4 = pts3
203
- end
204
- @search_space.remove_unfeasible pts4
205
- return pts4
199
+ # def points
200
+ # array = @search_space.parameters.collect { |p| p.values.collect { |val| [p.name,val] } }
201
+ # pts = array[0]
202
+ # pts = pts.product(*array[1..-1]) if array.length > 1
203
+ # pts = pts.collect { |a| Hash[ *a.flatten ] }
204
+ # return pts.select{ |pt| @search_space.rules_checker(pt) }
205
+ # end
206
+
207
+ def to_a
208
+ return each.to_a
206
209
  end
207
210
 
208
- def each(&block)
209
- return self.points.each(&block)
211
+ alias points to_a
212
+
213
+ def each
214
+ array = @search_space.parameters.collect { |p| [p.name,p.values.to_a] }
215
+ lazy_block = lambda { |rank, data|
216
+ array[rank][1].each { |d|
217
+ data[array[rank][0]] = d
218
+ if rank == array.length - 1 then
219
+ yield data.dup if @search_space.rules_checker(data)
220
+ else
221
+ lazy_block.call(rank+1, data)
222
+ end
223
+ }
224
+ }
225
+ if block_given? then
226
+ lazy_block.call(0, {})
227
+ return self
228
+ else
229
+ return to_enum(:each)
230
+ end
210
231
  end
211
232
 
212
- def each_random(&block)
213
- return self.points.shuffle.each(&block)
233
+ def each_random( &block)
234
+ self.points.shuffle.each(&block)
235
+ return self if block_given?
214
236
  end
215
237
 
216
238
  def optimize(&block)
217
239
  @experiments = 0
218
240
  @log = {}
219
241
  best = [nil, Float::INFINITY]
220
- pts = points
242
+ e = each
221
243
 
222
- (@seed ? pts.shuffle!(random: Random.new(@seed)) : pts.shuffle!) if @randomize
223
-
224
- pts = pts.slice(@checkpoint,@checkpoint_size) if @checkpoint_size
244
+ if @randomize then
245
+ e = e.to_a
246
+ (@seed ? e.shuffle!(random: Random.new(@seed)) : e.shuffle!)
247
+ end
248
+ e = e.drop(@checkpoint).take(@checkpoint_size) if @checkpoint_size
225
249
 
226
- pts.each { |config|
250
+ e.each { |config|
227
251
  @experiments += 1
228
252
  metric = block.call(config)
229
253
  @log[config] = metric if optimizer_log