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.
- checksums.yaml +4 -4
- data/BOAST.gemspec +1 -1
- data/LICENSE +13 -1
- data/README.md +62 -13
- data/lib/BOAST.rb +3 -1
- data/lib/BOAST/Language/ARMCPUID_by_name.rb +3752 -0
- data/lib/BOAST/Language/Algorithm.rb +4 -24
- data/lib/BOAST/Language/Architectures.rb +5 -0
- data/lib/BOAST/Language/Arithmetic.rb +38 -5
- data/lib/BOAST/Language/BOAST_OpenCL.rb +7 -8
- data/lib/BOAST/Language/Case.rb +10 -3
- data/lib/BOAST/Language/Config.rb +36 -12
- data/lib/BOAST/Language/ControlStructure.rb +7 -3
- data/lib/BOAST/Language/DataTypes.rb +6 -0
- data/lib/BOAST/Language/Expression.rb +26 -2
- data/lib/BOAST/Language/For.rb +59 -30
- data/lib/BOAST/Language/FuncCall.rb +9 -5
- data/lib/BOAST/Language/Functors.rb +1 -1
- data/lib/BOAST/Language/HighLevelOperators.rb +172 -0
- data/lib/BOAST/Language/If.rb +25 -9
- data/lib/BOAST/Language/Index.rb +5 -5
- data/lib/BOAST/Language/Intrinsics.rb +40 -27
- data/lib/BOAST/Language/OpenMP.rb +1 -0
- data/lib/BOAST/Language/Operators.rb +221 -34
- data/lib/BOAST/Language/Parens.rb +3 -2
- data/lib/BOAST/Language/Procedure.rb +18 -5
- data/lib/BOAST/Language/Slice.rb +176 -44
- data/lib/BOAST/Language/Variable.rb +99 -56
- data/lib/BOAST/Language/While.rb +18 -3
- data/lib/BOAST/Language/{CPUID_by_name.rb → X86CPUID_by_name.rb} +0 -0
- data/lib/BOAST/Optimization/Optimization.rb +2 -0
- data/lib/BOAST/Runtime/AffinityProbe.rb +7 -3
- data/lib/BOAST/Runtime/CKernel.rb +3 -0
- data/lib/BOAST/Runtime/CRuntime.rb +4 -0
- data/lib/BOAST/Runtime/CompiledRuntime.rb +404 -77
- data/lib/BOAST/Runtime/Compilers.rb +44 -18
- data/lib/BOAST/Runtime/Config.rb +9 -0
- data/lib/BOAST/Runtime/EnergyProbe.rb +19 -3
- data/lib/BOAST/Runtime/FFIRuntime.rb +23 -0
- data/lib/BOAST/Runtime/FORTRANRuntime.rb +1 -1
- data/lib/BOAST/Runtime/MAQAO.rb +29 -0
- data/lib/BOAST/Runtime/NonRegression.rb +64 -3
- data/lib/BOAST/Runtime/OpenCLRuntime.rb +16 -6
- data/lib/BOAST/Runtime/Probe.rb +21 -1
- metadata +5 -3
data/lib/BOAST/Language/For.rb
CHANGED
@@ -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
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
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
|
-
|
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
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
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
|
-
|
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
|
139
|
+
rescue Exception
|
119
140
|
open
|
120
|
-
|
121
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
176
|
+
block = @block unless block
|
177
|
+
return pr_unroll(*args, &block) if unroll?
|
151
178
|
open
|
152
|
-
if
|
153
|
-
|
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 [
|
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
|
data/lib/BOAST/Language/If.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
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 = ""
|