BOAST 1.0.9 → 1.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.
@@ -4,6 +4,8 @@ module BOAST
4
4
  include PrivateStateAccessor
5
5
  include Inspectable
6
6
  extend Functor
7
+ include Annotation
8
+ ANNOTATIONS = [ :name, :parameters, :constants ]
7
9
 
8
10
  attr_reader :name
9
11
  attr_reader :parameters
@@ -214,21 +216,22 @@ module BOAST
214
216
  s += ")"
215
217
  end
216
218
 
217
- def pr_align
218
- end
219
-
220
219
  def open_c
221
220
  s = indent + decl_c_s + "{"
222
221
  output.puts s
223
222
  increment_indent_level
224
223
  constants.each { |c|
225
- c.decl
224
+ BOAST::decl c
226
225
  }
227
226
  if lang == C then
228
227
  parameters.each { |p|
229
- p.pr_align
228
+ align = p.align
229
+ BOAST::pr align if align
230
230
  }
231
231
  end
232
+ if @properties[:return] then
233
+ BOAST::decl @properties[:return]
234
+ end
232
235
  return self
233
236
  end
234
237
 
@@ -239,12 +242,16 @@ module BOAST
239
242
  s += indent + "integer, parameter :: wp=kind(1.0d0)"
240
243
  output.puts s
241
244
  constants.each { |c|
242
- c.decl
245
+ BOAST::decl c
243
246
  }
244
247
  parameters.each { |p|
245
- p.decl
246
- p.pr_align
248
+ BOAST::decl p
249
+ align = p.align
250
+ BOAST::pr align if align
247
251
  }
252
+ if @properties[:return] then
253
+ BOAST::decl @properties[:return]
254
+ end
248
255
  return self
249
256
  end
250
257
 
@@ -13,7 +13,11 @@ module BOAST
13
13
  if v1 then
14
14
  if v2 then
15
15
  #@size = Expression::new(Substraction, v2, v1) + 1
16
- @size = v2-v1+1
16
+ begin
17
+ @size = v2-v1+1
18
+ rescue
19
+ @size = Expression::new(Substraction, v2, v1) + 1
20
+ end
17
21
  else
18
22
  @size = v1
19
23
  end
@@ -29,8 +33,10 @@ module BOAST
29
33
  return "#{@val1}:#{@val2}"
30
34
  elsif lang == FORTRAN and get_array_start != 1 then
31
35
  return "#{get_array_start}:#{@size-(1+get_array_start)}"
36
+ elsif lang == FORTRAN and size.nil?
37
+ return "*"
32
38
  else
33
- return @size
39
+ return @size.to_s
34
40
  end
35
41
  end
36
42
 
@@ -47,13 +53,17 @@ module BOAST
47
53
  return @val2
48
54
  elsif @size
49
55
  if 0.equal?(get_array_start) then
56
+ return @size - 1
57
+ else
50
58
  if 1.equal?(get_array_start) then
51
- return Expression::new(Addition, @size, get_array_start) - 1
52
- else
53
59
  return @size
60
+ else
61
+ begin
62
+ return @size + get_array_start - 1
63
+ rescue
64
+ return Expression::new(Addition, @size, get_array_start) - 1
65
+ end
54
66
  end
55
- else
56
- return Expression::new(Substraction, @size, 1)
57
67
  end
58
68
  else
59
69
  return nil
@@ -115,6 +125,8 @@ module BOAST
115
125
  include Arithmetic
116
126
  include Inspectable
117
127
  extend Functor
128
+ include Annotation
129
+ ANNOTATIONS = [ :name, :type, :dimension ]
118
130
 
119
131
  alias_method :orig_method_missing, :method_missing
120
132
 
@@ -146,7 +158,7 @@ module BOAST
146
158
  attr_reader :restrict
147
159
  attr_reader :deferred_shape
148
160
  attr_reader :optional
149
- attr_accessor :align
161
+ attr_accessor :alignment
150
162
  attr_accessor :replace_constant
151
163
  attr_accessor :force_replace_constant
152
164
 
@@ -191,7 +203,7 @@ module BOAST
191
203
  end
192
204
 
193
205
  def align?
194
- !!@align
206
+ !!@alignment
195
207
  end
196
208
 
197
209
  def deferred_shape?
@@ -207,7 +219,7 @@ module BOAST
207
219
  @texture = hash[:texture]
208
220
  @allocate = hash[:allocate]
209
221
  @restrict = hash[:restrict]
210
- @align = hash[:align]
222
+ @alignment = hash[:align]
211
223
  @deferred_shape = hash[:deferred_shape]
212
224
  @optional = hash[:optional]
213
225
  @force_replace_constant = false
@@ -271,8 +283,7 @@ module BOAST
271
283
 
272
284
  def dereference
273
285
  return copy("*(#{name})", :dimension => nil, :dim => nil, :direction => nil, :dir => nil) if [C, CL, CUDA].include?( lang )
274
- return self if lang == FORTRAN
275
- #return Expression::new("*",nil,self)
286
+ return Index::new(self, *(@dimension.collect { |d| d.start } ) ) if lang == FORTRAN
276
287
  end
277
288
 
278
289
  def struct_reference(x)
@@ -285,7 +296,7 @@ module BOAST
285
296
  end
286
297
 
287
298
  def [](*args)
288
- return Index::new(self,args)
299
+ return Index::new(self,*args)
289
300
  end
290
301
 
291
302
  def finalize
@@ -310,12 +321,7 @@ module BOAST
310
321
  if dimension? and use_vla? and lang != FORTRAN then
311
322
  s += "["
312
323
  s += @dimension.reverse.collect { |d|
313
- dim = d.to_s
314
- if dim then
315
- dim.to_s
316
- else
317
- ""
318
- end
324
+ d.to_s
319
325
  }.join("][")
320
326
  s += "]"
321
327
  end
@@ -386,12 +392,7 @@ module BOAST
386
392
  s += " #{@name}["
387
393
  s += "__restrict__ " if __restrict?
388
394
  s += @dimension.reverse.collect { |d|
389
- dim = d.to_s
390
- if dim then
391
- dim.to_s
392
- else
393
- ""
394
- end
395
+ d.to_s
395
396
  }.join("][")
396
397
  s += "]"
397
398
  else
@@ -413,8 +414,8 @@ module BOAST
413
414
  s +=")]"
414
415
  end
415
416
  end
416
- if __align? then
417
- a = ( align? ? align : 1 )
417
+ if __align? and lang != CUDA then
418
+ a = ( align? ? alignment : 1 )
418
419
  a = ( a >= default_align ? a : default_align )
419
420
  s+= " __attribute((aligned(#{a})))"
420
421
  end
@@ -423,7 +424,7 @@ module BOAST
423
424
  end
424
425
 
425
426
  def decl_texture_s
426
- raise "Unsupported language #{lang} for texture!" if not [CL, CUDA].include?( lang )
427
+ raise LanguageError, "Unsupported language #{lang} for texture!" if not [CL, CUDA].include?( lang )
427
428
  raise "Write is unsupported for textures!" if not (constant? or @direction == :in)
428
429
  dim_number = 1
429
430
  if dimension? then
@@ -454,69 +455,39 @@ module BOAST
454
455
  return self
455
456
  end
456
457
 
457
- def pr_align_c_s(a)
458
- return "__assume_aligned(#{@name}, #{a})"
459
- end
460
-
461
- def pr_align_c(a)
462
- s = ""
463
- s += indent
464
- s += pr_align_c_s(a)
465
- s += finalize
466
- output.print s
467
- return self
458
+ def align_c(a)
459
+ return FuncCall::new("__assume_aligned", @name, a)
468
460
  end
469
461
 
470
- def pr_align_fortran_s(a)
471
- return "!DIR$ ASSUME_ALIGNED #{@name}: #{a}"
462
+ def align_fortran(a)
463
+ return Pragma::new("DIR", "ASSUME_ALIGNED", "#{@name}: #{a}")
472
464
  end
473
465
 
474
- def pr_align_fortran(a)
475
- s = ""
476
- s += indent
477
- s += pr_align_fortran_s(a)
478
- s += finalize
479
- output.print s
480
- return self
481
- end
482
-
483
- def pr_align
466
+ def align
484
467
  if dimension? then
485
468
  if align? or default_align > 1 then
486
- a = ( align? ? align : 1 )
469
+ a = ( align? ? alignment : 1 )
487
470
  a = ( a >= default_align ? a : default_align )
488
- return pr_align_c(a) if lang == C
489
- return pr_align_fortran(a) if lang == FORTRAN
471
+ return align_c(a) if lang == C
472
+ return align_fortran(a) if lang == FORTRAN
490
473
  end
491
474
  end
475
+ return nil
492
476
  end
493
477
 
494
478
  def alloc_fortran( dims = nil )
495
- s = ""
496
- s += indent
497
- s += "allocate( #{name}("
498
- s += dims.collect { |d| d.to_s }.join(", ")
499
- s += ") )"
500
- s += finalize
501
- output.print s
502
- return self
479
+ return FuncCall::new(:allocate, FuncCall(name, * dims ) )
503
480
  end
504
481
 
505
482
  def alloc_c( dims = nil, align = get_address_size)
506
- s = ""
507
- s += indent
483
+ d = dims.collect { |d| d.to_s }.reverse.join(")*(")
508
484
  if align > (OS.bits/8) then
509
485
  # check alignment is a power of 2
510
486
  raise "Invalid alignment #{align}!" if align & (align - 1) != 0
511
- s += "(#{@type.decl} *) posix_memalign( &#{name}, #{align}, sizeof(#{@type.decl})*("
487
+ return FuncCall::new(:posix_memalign, self.address, align, FuncCall::new(:sizeof, @type.decl) * d)
512
488
  else
513
- s += "#{name} = (#{@type.decl} *) malloc( sizeof(#{@type.decl})*("
489
+ return self === FuncCall::new(:malloc, FuncCall::new(:sizeof, @type.decl) * d).cast(self)
514
490
  end
515
- s += dims.collect { |d| d.to_s }.reverse.join(")*(")
516
- s += ") )"
517
- s += finalize
518
- output.print s
519
- return self
520
491
  end
521
492
 
522
493
  def alloc( dims = nil, align = get_address_size )
@@ -528,21 +499,11 @@ module BOAST
528
499
  end
529
500
 
530
501
  def dealloc_fortran
531
- s = ""
532
- s += indent
533
- s += "deallocate( #{name} )"
534
- s += finalize
535
- output.print s
536
- return self
502
+ return FuncCall::new(:deallocate, self)
537
503
  end
538
504
 
539
505
  def dealloc_c
540
- s = ""
541
- s += indent
542
- s += "free( #{name} )"
543
- s += finalize
544
- output.print s
545
- return self
506
+ return FuncCall::new(:free, self)
546
507
  end
547
508
 
548
509
  def dealloc
@@ -561,13 +522,10 @@ module BOAST
561
522
  if dimension? then
562
523
  s += ", dimension("
563
524
  s += @dimension.collect { |d|
564
- dim = d.to_s
565
525
  if deferred_shape? or ( allocate? and @allocate == :heap )
566
526
  ":"
567
- elsif dim then
568
- dim.to_s
569
527
  else
570
- "*"
528
+ d.to_s
571
529
  end
572
530
  }.join(", ")
573
531
  s += ")"
@@ -581,7 +539,7 @@ module BOAST
581
539
  s += finalize
582
540
  output.print s
583
541
  if dimension? and (align? or default_align > 1) and (constant? or ( allocate? and @allocate != :heap ) ) then
584
- a = ( align? ? align : 1 )
542
+ a = ( align? ? alignment : 1 )
585
543
  a = ( a >= default_align ? a : default_align )
586
544
  s = ""
587
545
  s += indent
@@ -1,6 +1,8 @@
1
1
  module BOAST
2
2
 
3
3
  class While < ControlStructure
4
+ include Annotation
5
+ ANNOTATIONS = [ :condition ]
4
6
 
5
7
  attr_reader :condition
6
8
 
@@ -39,6 +41,7 @@ module BOAST
39
41
  end
40
42
 
41
43
  def pr(*args)
44
+ args = @args if args.length == 0 and @args
42
45
  open
43
46
  if @block then
44
47
  @block.call(*args)
@@ -0,0 +1,241 @@
1
+ module BOAST
2
+
3
+ class OptimizationParameter
4
+ attr_reader :name
5
+ attr_reader :values
6
+ def initialize( name, values )
7
+ @name = name
8
+ @values = values
9
+ end
10
+ end
11
+
12
+ class BooleanParameter < OptimizationParameter
13
+ def initialize( name )
14
+ super( name, [false, true] )
15
+ end
16
+ end
17
+
18
+ OP = OptimizationParameter
19
+ BP = BooleanParameter
20
+
21
+ class OptimizationSpace
22
+ attr_reader :parameters
23
+
24
+ def initialize( *parameters )
25
+ if parameters.length == 1 and parameters[0].is_a?(Hash) then
26
+ @parameters = []
27
+ parameters[0].each { |key, value|
28
+ @parameters.push( OptimizationParameter::new(key, value) )
29
+ }
30
+ else
31
+ @parameters = parameters
32
+ end
33
+ end
34
+
35
+ def to_h
36
+ h = {}
37
+ @parameters.each { |p|
38
+ h[p.name] = p.values
39
+ }
40
+ return h
41
+ end
42
+
43
+ end
44
+
45
+ class Optimizer
46
+ include PrivateStateAccessor
47
+ attr_reader :experiments
48
+ attr_reader :search_space
49
+ attr_reader :log
50
+
51
+ def initialize(search_space, options = {} )
52
+ @search_space = search_space
53
+ @experiments = 0
54
+ @log = {}
55
+ end
56
+ end
57
+
58
+ class GeneticOptimizer < Optimizer
59
+
60
+ def initialize(search_space, options = {} )
61
+ super
62
+ require 'darwinning'
63
+ s = <<EOF
64
+ @organism = Class::new(Darwinning::Organism) do
65
+ @@block = nil
66
+ def self.block
67
+ return @@block
68
+ end
69
+ def self.block=(block)
70
+ @@block = block
71
+ end
72
+ @@experiments = 0
73
+ def self.experiments
74
+ return @@experiments
75
+ end
76
+ def self.experiments=(experiments)
77
+ @@experiments = experiments
78
+ end
79
+ EOF
80
+ @search_space.parameters.each { |param|
81
+ s += <<EOF
82
+ @genes.push( Darwinning::Gene.new(name: #{param.name.inspect}, value_range: #{param.values.inspect}) )
83
+ EOF
84
+ }
85
+ s += <<EOF
86
+ def initialize(*args)
87
+ super
88
+ end
89
+
90
+ def fitness
91
+ return @fitness if @fitness
92
+ opts = {}
93
+ genes.each { |gene|
94
+ opts[gene.name] = genotypes[gene]
95
+ }
96
+ @fitness = @@block.call(opts)
97
+ @@experiments = @@experiments + 1
98
+ return fitness
99
+ end
100
+
101
+ def to_a
102
+ opts = {}
103
+ genes.each { |gene|
104
+ opts[gene.name] = genotypes[gene]
105
+ }
106
+ return [opts, fitness]
107
+ end
108
+
109
+ def to_s
110
+ return [opts, fitness].to_s
111
+ end
112
+
113
+ end
114
+ EOF
115
+ eval s
116
+ end
117
+
118
+ def optimize(options={}, &block)
119
+ opts = { :population_size => 20,
120
+ :fitness_goal => 0,
121
+ :generations_limit => 100 }
122
+ opts.update(options)
123
+ opts[:organism] = @organism
124
+ @organism.block = block
125
+ @organism.experiments = 0
126
+ population = Darwinning::Population.new(opts)
127
+ population.evolve!
128
+ @experiments = @organism.experiments
129
+ return population.best_member.to_a
130
+ end
131
+
132
+ end
133
+
134
+ class BruteForceOptimizer < Optimizer
135
+
136
+ def initialize(search_space, options = {} )
137
+ super
138
+ @randomize = options[:randomize]
139
+ end
140
+
141
+ def points
142
+ params2 = @search_space.parameters.dup
143
+ param = params2.shift
144
+ pts = param.values.collect { |val| {param.name => val} }
145
+ if params2.size == 0 then
146
+ return pts
147
+ else
148
+ optim2 = BruteForceOptimizer::new(OptimizationSpace::new(*params2))
149
+ pts3=[]
150
+ pts.each{ |p1|
151
+ optim2.each { |p2|
152
+ pts3.push(p1.dup.update(p2))
153
+ }
154
+ }
155
+ return pts3
156
+ end
157
+ end
158
+
159
+ def each(&block)
160
+ return self.points.each(&block)
161
+ end
162
+
163
+ def each_random(&block)
164
+ return self.points.shuffle.each(&block)
165
+ end
166
+
167
+ def optimize(&block)
168
+ @experiments = 0
169
+ @log = {}
170
+ best = [nil, Float::INFINITY]
171
+ pts = points
172
+ pts.shuffle! if @randomize
173
+ pts.each { |config|
174
+ @experiments += 1
175
+ metric = block.call(config)
176
+ @log[config] = metric if optimizer_log
177
+ best = [config, metric] if metric < best[1]
178
+ }
179
+ if optimizer_log_file then
180
+ File::open(File::basename(optimizer_log_file,".yaml")+".yaml", "w") { |f|
181
+ f.print YAML::dump(@log)
182
+ }
183
+ File::open(File::basename(optimizer_log_file,".yaml")+"_parameters.yaml", "w") { |f|
184
+ f.print YAML::dump(@search_space.to_h)
185
+ }
186
+ end
187
+ return best
188
+ end
189
+
190
+ end
191
+
192
+ class GenericOptimization
193
+
194
+ attr_accessor :repeat
195
+ attr_reader :parameters
196
+
197
+ def size
198
+ return @parameters.size
199
+ end
200
+
201
+ def points
202
+ params2 = @parameters.dup
203
+ param = params2.shift
204
+ pts = param.values.collect { |val| {param.name => val} }
205
+ if params2.size == 0 then
206
+ return pts
207
+ else
208
+ optim2 = GenericOptimization::new(*params2)
209
+ pts3=[]
210
+ pts.each{ |p1|
211
+ optim2.each { |p2|
212
+ pts3.push(p1.dup.update(p2))
213
+ }
214
+ }
215
+ return pts3
216
+ end
217
+ end
218
+
219
+ def each(&block)
220
+ return self.points.each(&block)
221
+ end
222
+
223
+ def each_random(&block)
224
+ return self.points.shuffle.each(&block)
225
+ end
226
+
227
+ def initialize( *parameters )
228
+ if parameters.length == 1 and parameters[0].is_a?(Hash) then
229
+ @parameters = []
230
+ parameters[0].each { |key, value|
231
+ @parameters.push( OptimizationParameter::new(key, value) )
232
+ }
233
+ else
234
+ @parameters = parameters
235
+ end
236
+ @repeat = 3
237
+ end
238
+
239
+ end
240
+
241
+ end