BOAST 2.0.2 → 2.1.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.
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