BOAST 1.3.5 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
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 = ""