BOAST 1.0.9 → 1.1.0

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