BOAST 1.3.5 → 2.0.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 (45) hide show
  1. checksums.yaml +4 -4
  2. data/BOAST.gemspec +1 -1
  3. data/LICENSE +13 -1
  4. data/README.md +62 -13
  5. data/lib/BOAST.rb +3 -1
  6. data/lib/BOAST/Language/ARMCPUID_by_name.rb +3752 -0
  7. data/lib/BOAST/Language/Algorithm.rb +4 -24
  8. data/lib/BOAST/Language/Architectures.rb +5 -0
  9. data/lib/BOAST/Language/Arithmetic.rb +38 -5
  10. data/lib/BOAST/Language/BOAST_OpenCL.rb +7 -8
  11. data/lib/BOAST/Language/Case.rb +10 -3
  12. data/lib/BOAST/Language/Config.rb +36 -12
  13. data/lib/BOAST/Language/ControlStructure.rb +7 -3
  14. data/lib/BOAST/Language/DataTypes.rb +6 -0
  15. data/lib/BOAST/Language/Expression.rb +26 -2
  16. data/lib/BOAST/Language/For.rb +59 -30
  17. data/lib/BOAST/Language/FuncCall.rb +9 -5
  18. data/lib/BOAST/Language/Functors.rb +1 -1
  19. data/lib/BOAST/Language/HighLevelOperators.rb +172 -0
  20. data/lib/BOAST/Language/If.rb +25 -9
  21. data/lib/BOAST/Language/Index.rb +5 -5
  22. data/lib/BOAST/Language/Intrinsics.rb +40 -27
  23. data/lib/BOAST/Language/OpenMP.rb +1 -0
  24. data/lib/BOAST/Language/Operators.rb +221 -34
  25. data/lib/BOAST/Language/Parens.rb +3 -2
  26. data/lib/BOAST/Language/Procedure.rb +18 -5
  27. data/lib/BOAST/Language/Slice.rb +176 -44
  28. data/lib/BOAST/Language/Variable.rb +99 -56
  29. data/lib/BOAST/Language/While.rb +18 -3
  30. data/lib/BOAST/Language/{CPUID_by_name.rb → X86CPUID_by_name.rb} +0 -0
  31. data/lib/BOAST/Optimization/Optimization.rb +2 -0
  32. data/lib/BOAST/Runtime/AffinityProbe.rb +7 -3
  33. data/lib/BOAST/Runtime/CKernel.rb +3 -0
  34. data/lib/BOAST/Runtime/CRuntime.rb +4 -0
  35. data/lib/BOAST/Runtime/CompiledRuntime.rb +404 -77
  36. data/lib/BOAST/Runtime/Compilers.rb +44 -18
  37. data/lib/BOAST/Runtime/Config.rb +9 -0
  38. data/lib/BOAST/Runtime/EnergyProbe.rb +19 -3
  39. data/lib/BOAST/Runtime/FFIRuntime.rb +23 -0
  40. data/lib/BOAST/Runtime/FORTRANRuntime.rb +1 -1
  41. data/lib/BOAST/Runtime/MAQAO.rb +29 -0
  42. data/lib/BOAST/Runtime/NonRegression.rb +64 -3
  43. data/lib/BOAST/Runtime/OpenCLRuntime.rb +16 -6
  44. data/lib/BOAST/Runtime/Probe.rb +21 -1
  45. metadata +5 -3
@@ -11,15 +11,28 @@ module BOAST
11
11
  attr_reader :step
12
12
  attr_accessor :block
13
13
 
14
+ # returns the Boolean evaluation of the unroll attribute.
14
15
  def unroll?
15
16
  return !!@unroll
16
17
  end
17
18
 
19
+ # Sets the unroll attribute to val.
18
20
  def unroll=(val)
19
21
  @unroll = val
20
22
  end
21
23
 
24
+ # Creates a new instance of the For construct.
25
+ # @param [Variable] iterator
26
+ # @param [#to_s] first iteration start
27
+ # @param [#to_s] last iteration stop (inclusive)
28
+ # @param [Hash] options contains named options
29
+ # @param [Proc,nil] block if given, will be evaluated when {pr} is called
30
+ # @option options [#to_s] :step spcifies the increment in the for loop
31
+ # @option options [Boolean,Hash] :openmp specifies if an OpenMP For pragma has to be generated. If a Hash is specified it conatins the OpenMP clauses and their values.
32
+ # @option options [Boolean] :unroll specifies if {pr} must try to unroll the loop
33
+ # @option options [Array<Object>] :args arguments to be passed to the block. Will be superseded by those provided by {pr}
22
34
  def initialize(iterator, first, last, options={}, &block)
35
+ super()
23
36
  default_options = {:step => 1}
24
37
  default_options.update( options )
25
38
  @options = options
@@ -39,21 +52,20 @@ module BOAST
39
52
  @openmp = OpenMP::For({})
40
53
  end
41
54
  end
42
- begin
43
- push_env( :replace_constants => true )
44
- if @step.kind_of?(Variable) then
45
- step = @step.constant
46
- elsif @step.kind_of?(Expression) then
47
- step = eval "#{@step}"
48
- else
49
- step = @step.to_i
55
+ push_env( :replace_constants => true ) {
56
+ begin
57
+ if @step.kind_of?(Variable) then
58
+ step = @step.constant
59
+ elsif @step.kind_of?(Expression) then
60
+ step = eval "#{@step}"
61
+ else
62
+ step = @step.to_i
63
+ end
64
+ @operator = ">=" if step < 0
65
+ rescue
66
+ STDERR.puts "Warning could not determine sign of step (#{@step}) assuming positive" if [C, CL, CUDA].include?( lang ) and debug?
50
67
  end
51
- @operator = ">=" if step < 0
52
- rescue
53
- STDERR.puts "Warning could not determine sign of step (#{@step}) assuming positive" if [C, CL, CUDA].include?( lang ) and debug?
54
- ensure
55
- pop_env( :replace_constants )
56
- end
68
+ }
57
69
  end
58
70
 
59
71
  def get_c_strings
@@ -74,19 +86,28 @@ module BOAST
74
86
  eval token_string_generator( * %w{for i b e s o})
75
87
  eval token_string_generator( * %w{end})
76
88
 
89
+ # Returns a string representation of the For construct.
77
90
  def to_s
78
91
  s = for_string(@iterator, @first, @last, @step, @operator)
79
92
  return s
80
93
  end
81
94
 
82
- def unroll
83
- opts = @options.clone
84
- opts[:unroll] = true
85
- return For::new(@iterator, @first, @last, opts, &block)
95
+ # Creates a copy of this For construct with the unroll option set and returns it if it is different from the current unroll flag.
96
+ # @return [For]
97
+ # @param [Boolean] flag specifying if the For should be unrolled or not
98
+ def unroll( flag = true )
99
+ if flag ^ @unroll then
100
+ opts = @options.clone
101
+ opts[:unroll] = flag
102
+ return For::new(@iterator, @first, @last, opts, &block)
103
+ else
104
+ return self
105
+ end
86
106
  end
87
107
 
88
- def pr_unroll(*args)
89
- raise "Block not given!" if not @block
108
+ def pr_unroll(*args, &block)
109
+ block = @block unless block
110
+ raise "Block not given!" unless block
90
111
  begin
91
112
  begin
92
113
  push_env( :replace_constants => true )
@@ -115,19 +136,17 @@ module BOAST
115
136
  ensure
116
137
  pop_env( :replace_constants )
117
138
  end
118
- rescue Exception => ex
139
+ rescue Exception
119
140
  open
120
- if @block then
121
- @block.call(*args)
122
- close
123
- end
141
+ block.call(*args)
142
+ close
124
143
  return self
125
144
  end
126
145
  range = first..last
127
146
  @iterator.force_replace_constant = true
128
147
  range.step(step) { |i|
129
148
  @iterator.constant = i
130
- @block.call(*args)
149
+ block.call(*args)
131
150
  }
132
151
  @iterator.force_replace_constant = false
133
152
  @iterator.constant = nil
@@ -135,6 +154,8 @@ module BOAST
135
154
 
136
155
  private :pr_unroll
137
156
 
157
+ # Opens the For construct (keyword, iterator, bounds, step, opening bracket in C like languages). The result is printed to the BOAST output.
158
+ # @return [self]
138
159
  def open
139
160
  @openmp.open if @openmp
140
161
  s=""
@@ -145,17 +166,25 @@ module BOAST
145
166
  return self
146
167
  end
147
168
 
148
- def pr(*args)
169
+ # Prints the For construct to the BOAST output (see {open}).
170
+ # If a block is provided during initialization, it will be printed and the construct will be closed (see {close}).
171
+ # @param [Array<Object>] args any number of arguments to pass to the block
172
+ # @param [Proc] block an optional block to be evaluated. Supersede the one given at initialization
173
+ # @return [self]
174
+ def pr(*args, &block)
149
175
  args = @args if args.length == 0 and @args
150
- return pr_unroll(*args) if unroll?
176
+ block = @block unless block
177
+ return pr_unroll(*args, &block) if unroll?
151
178
  open
152
- if @block then
153
- @block.call(*args)
179
+ if block then
180
+ block.call(*args)
154
181
  close
155
182
  end
156
183
  return self
157
184
  end
158
185
 
186
+ # Closes the For construct (keyword, closing bracket in C like languages). The result is printed to the BOAST output.
187
+ # @return [self]
159
188
  def close
160
189
  decrement_indent_level
161
190
  s = ""
@@ -7,22 +7,25 @@ module BOAST
7
7
  include Inspectable
8
8
  extend Functor
9
9
 
10
- @return_type
11
- @options
12
-
13
10
  attr_reader :func_name
14
11
  attr_reader :args
15
12
  attr_accessor :prefix
16
13
 
17
14
  def initialize(func_name, *args)
15
+ @prefix = nil
18
16
  @func_name = func_name
19
17
  if args.last.kind_of?(Hash) then
20
18
  @options = args.last
21
19
  @args = args[0..-2]
22
20
  else
23
21
  @args = args
22
+ @options = {}
24
23
  end
25
- @return_type = @options[:returns] if @options
24
+ @return_type = @options[:return] ? @options[:return] : @options[:returns] if @options
25
+ end
26
+
27
+ def type
28
+ return @return_type.type if @return_type
26
29
  end
27
30
 
28
31
  def to_var
@@ -32,8 +35,9 @@ module BOAST
32
35
  else
33
36
  return Variable::new("#{self}", @return_type)
34
37
  end
38
+ else
39
+ return Variable::new("#{self}", get_default_type)
35
40
  end
36
- return nil
37
41
  end
38
42
 
39
43
  def to_s
@@ -49,7 +49,7 @@ EOF
49
49
  # Creates a new Variable of type $1.
50
50
  # @param [#to_s] name name of the Variable
51
51
  # @param [Object] args parameters to use when creating a Variable
52
- # @param [Block] block block of code will be forwarded
52
+ # @param [Proc] block block of code will be forwarded
53
53
  def var_functorize(klass)
54
54
  name = klass.name.split('::').last
55
55
  s = <<EOF
@@ -0,0 +1,172 @@
1
+ module BOAST
2
+
3
+ class HighLevelOperator < Operator
4
+ include Intrinsics
5
+ include Arithmetic
6
+ include Inspectable
7
+ end
8
+
9
+ class Sqrt < HighLevelOperator
10
+ extend Functor
11
+
12
+ attr_reader :operand
13
+ attr_reader :return_type
14
+
15
+ def initialize(a)
16
+ @operand = a
17
+ @return_type = a.to_var
18
+ unless @return_type.type.kind_of?(Real) then
19
+ @return_type = Variable::new(:sqrt_type, Real, :vector_length => @return_type.type.vector_length)
20
+ end
21
+ end
22
+
23
+ def convert_operand(op)
24
+ return "#{Operator.convert(op, @return_type.type)}"
25
+ end
26
+
27
+ private :convert_operand
28
+
29
+ def type
30
+ return @return_type.type
31
+ end
32
+
33
+ def to_var
34
+ sqrt_instruction = nil
35
+ rsqrt_instruction = nil
36
+ begin
37
+ sqrt_instruction = intrinsics(:SQRT,@return_type.type)
38
+ rescue
39
+ end
40
+ unless sqrt_instruction then
41
+ begin
42
+ rsqrt_instruction = intrinsics(:RSQRT,@return_type.type)
43
+ rescue
44
+ end
45
+ end
46
+
47
+ if [FORTRAN, CL].include?(lang) then
48
+ return @return_type.copy( "sqrt( #{@operand} )", DISCARD_OPTIONS )
49
+ elsif lang == CUDA or ( sqrt_instruction.nil? and rsqrt_instruction.nil? ) then
50
+ raise IntrinsicsError, "Vector square root unsupported on ARM architecture!" if architecture == ARM and @return_type.type.vector_length > 1
51
+ if @return_type.type.size <= 4 then
52
+ return @return_type.copy( "sqrtf( #{@operand} )", DISCARD_OPTIONS )
53
+ else
54
+ return @return_type.copy( "sqrt( #{@operand} )", DISCARD_OPTIONS )
55
+ end
56
+ end
57
+ op = convert_operand(@operand.to_var)
58
+ if sqrt_instruction then
59
+ return @return_type.copy( "#{sqrt_instruction}( #{op} )", DISCARD_OPTIONS )
60
+ else
61
+ return (op * @return_type.copy("#{rsqrt_instruction}( #{op} )", DISCARD_OPTIONS)).to_var
62
+ end
63
+ end
64
+
65
+ def to_s
66
+ return to_var.to_s
67
+ end
68
+
69
+ def pr
70
+ s=""
71
+ s += indent
72
+ s += to_s
73
+ s += ";" if [C, CL, CUDA].include?( lang )
74
+ output.puts s
75
+ return self
76
+ end
77
+
78
+ end
79
+
80
+ class TrigonometricOperator < HighLevelOperator
81
+ attr_reader :operand
82
+ attr_reader :return_type
83
+
84
+ def initialize(a)
85
+ @operand = a
86
+ @return_type = a.to_var
87
+ unless @return_type.type.kind_of?(Real) then
88
+ @return_type = Variable::new(:trig_type, Real, :vector_length => @return_type.type.vector_length)
89
+ end
90
+ end
91
+
92
+ def convert_operand(op)
93
+ return "#{Operator.convert(op, @return_type.type)}"
94
+ end
95
+
96
+ private :convert_operand
97
+
98
+ def type
99
+ return @return_type.type
100
+ end
101
+
102
+ def to_var
103
+ instruction = nil
104
+ begin
105
+ instruction = intrinsics(get_intrinsic_symbol,@return_type.type)
106
+ rescue
107
+ end
108
+
109
+ if [FORTRAN, CL].include?(lang) then
110
+ return @return_type.copy( "#{get_name[lang]}( #{@operand} )", DISCARD_OPTIONS )
111
+ elsif lang == CUDA or instruction.nil? then
112
+ raise IntrinsicsError, "Vector #{get_name[lang]} root unsupported on ARM architecture!" if architecture == ARM and @return_type.type.vector_length > 1
113
+ if @return_type.type.size <= 4 then
114
+ return @return_type.copy( "#{get_name[lang]}f( #{@operand} )", DISCARD_OPTIONS )
115
+ else
116
+ return @return_type.copy( "#{get_name[lang]}( #{@operand} )", DISCARD_OPTIONS )
117
+ end
118
+ end
119
+ op = convert_operand(@operand.to_var)
120
+ return @return_type.copy( "#{instruction}( #{op} )", DISCARD_OPTIONS )
121
+ end
122
+
123
+ def to_s
124
+ return to_var.to_s
125
+ end
126
+
127
+ def pr
128
+ s=""
129
+ s += indent
130
+ s += to_s
131
+ s += ";" if [C, CL, CUDA].include?( lang )
132
+ output.puts s
133
+ return self
134
+ end
135
+
136
+ end
137
+
138
+ def self.generic_trigonometric_operator_generator( name )
139
+ eval <<EOF
140
+ class #{name.capitalize} < TrigonometricOperator
141
+ extend Functor
142
+
143
+ def get_intrinsic_symbol
144
+ return :#{name.upcase}
145
+ end
146
+
147
+ def get_name
148
+ return { C => "#{name}", CUDA => "#{name}", CL => "#{name}", FORTRAN => "#{name}" }
149
+ end
150
+
151
+ end
152
+
153
+ EOF
154
+ end
155
+
156
+ generic_trigonometric_operator_generator( "sin" )
157
+ generic_trigonometric_operator_generator( "cos" )
158
+ generic_trigonometric_operator_generator( "tan" )
159
+ generic_trigonometric_operator_generator( "sinh" )
160
+ generic_trigonometric_operator_generator( "cosh" )
161
+ generic_trigonometric_operator_generator( "tanh" )
162
+ generic_trigonometric_operator_generator( "asin" )
163
+ generic_trigonometric_operator_generator( "acos" )
164
+ generic_trigonometric_operator_generator( "atan" )
165
+ generic_trigonometric_operator_generator( "asinh" )
166
+ generic_trigonometric_operator_generator( "acosh" )
167
+ generic_trigonometric_operator_generator( "atanh" )
168
+
169
+ generic_trigonometric_operator_generator( "exp" )
170
+ generic_trigonometric_operator_generator( "log" )
171
+ generic_trigonometric_operator_generator( "log10" )
172
+ end
@@ -5,7 +5,17 @@ module BOAST
5
5
 
6
6
  attr_reader :conditions
7
7
 
8
+ # Creates a new instance of the If construct
9
+ # @overload initialize(condition, &block)
10
+ # Creates a simple If construct
11
+ # @param [Expression] condition
12
+ # @param [Proc,nil] block if given, will be evaluated when {pr} is called
13
+ # @overload initialize(conditions, &block)
14
+ # Creates a multi-condition If construct
15
+ # @param [Hash{Expression, :else => Proc}] conditions each condition and its associated block (can be nil)
16
+ # @param [Proc,nil] block else block if :else is not specified in the conditions or nil
8
17
  def initialize(conditions, &block)
18
+ super()
9
19
  @conditions = []
10
20
  @blocks = []
11
21
  if conditions.is_a?(Hash) then
@@ -46,6 +56,8 @@ module BOAST
46
56
  eval token_string_generator( * %w{else} )
47
57
  eval token_string_generator( * %w{end} )
48
58
 
59
+ # Returns a string representation of the If construct.
60
+ # @param [Fixnum] condition_number condition to print
49
61
  def to_s(condition_number = 0)
50
62
  s = ""
51
63
  if condition_number == 0 then
@@ -60,26 +72,28 @@ module BOAST
60
72
  return s
61
73
  end
62
74
 
63
- def open
75
+ # Opens the If construct. The result is printed on the BOAST output. If a condition number is given, will print the corresponding condition (or else if none exist)
76
+ # @param [Fixnum] condition_number condition to print
77
+ # @return [self]
78
+ def open(condition_number = 0)
79
+ decrement_indent_level if condition_number > 0
64
80
  s = ""
65
81
  s += indent
66
- s += to_s
82
+ s += to_s(condition_number)
67
83
  output.puts s
68
84
  increment_indent_level
69
85
  return self
70
86
  end
71
87
 
88
+ # Prints the If construct to the BOAST output (see {open}).
89
+ # If block/blocks is/are provided during initialization, they will be printed and the construct will be closed (see {close}).
90
+ # @param [Array<Object>] args any number of arguments to pass to the block/blocks
91
+ # @return [self]
72
92
  def pr(*args)
73
93
  args = @args if args.length == 0 and @args
74
94
  if @blocks.size > 0 then
75
- increment_indent_level
76
95
  @blocks.each_index { |indx|
77
- decrement_indent_level
78
- s = ""
79
- s += indent
80
- s += to_s(indx)
81
- output.puts s
82
- increment_indent_level
96
+ open(indx)
83
97
  @blocks[indx].call(*args)
84
98
  }
85
99
  close
@@ -89,6 +103,8 @@ module BOAST
89
103
  return self
90
104
  end
91
105
 
106
+ # Closes the If construct (keyword, closing bracket in C like languages). The result is printed to the BOAST output.
107
+ # @return [self]
92
108
  def close
93
109
  decrement_indent_level
94
110
  s = ""